2010-03-21 3 views
2

J'ai une application Delphi 6 Pro qui traite les trames jpeg entrantes à partir d'un serveur vidéo en streaming. Le code fonctionne mais j'ai récemment remarqué qu'il génère un grand nombre de fautes de pages souples au fil du temps. Après quelques recherches, les fautes de page semblent provenir d'une opération graphique particulière. Notez que les bitmaps non compressés en question ont une taille de 320 x 240 ou d'environ 300 Ko, ce qui n'est pas dû à la manipulation de grandes images. Le nombre de défauts de page générés n'est pas tolérable. Plus d'une heure, il peut facilement dépasser les défauts de la page 1000000.Nombre important de fautes de page lors de l'affectation d'une image TJpegImage à un TBitmap

J'ai créé un cas de test dépouillé qui exécute le code que j'ai inclus ci-dessous sur une minuterie, 10 fois par seconde. Les erreurs de page semblent se produire lorsque j'essaie d'affecter le TJpegImage à un TBitmap dans la méthode GetBitmap(). Je le sais parce que j'ai commenté cette ligne et les fautes de page ne se produisent pas. Le assign() déclenche une opération de décompression sur la partie de TJpegImage car il pousse les bits décompressés dans un bitmap nouvellement créé que GetBitmap() renvoie. Quand je lance l'utilitaire pfmon de Microsoft (surveillance de défaut de page), j'obtiens un grand nombre de lignes d'erreurs de fautes de pages souples concernant RtlFillMemoryUlong, de sorte qu'il semble se produire lors d'une opération de remplissage de mémoire tampon.

Une note déroutante. La partie résumée du rapport de pfmon où il montre quelle DLL a causé quelle erreur de page n'affiche aucun nom de DLL dans la colonne extrême gauche. J'ai essayé cela sur un autre système et ça arrive aussi.

Quelqu'un peut-il suggérer un correctif ou une solution de contournement? Voici le code. Remarque: IReceiveBufferForClientSocket est un objet de classe simple qui contient des octets dans un tampon d'accumulation.

function GetBitmap(theJpegImage: TJpegImage): Graphics.TBitmap; 
begin 
    Result := TBitmap.Create; 

    Result.Assign(theJpegImage); 
end; 

// --------------------------------------------------------------- 

procedure processJpegFrame(intfReceiveBuffer: IReceiveBufferForClientSocket); 
var 
    theBitmap: TBitmap; 
    theJpegStream, theBitmapStream: TMemoryStream; 
    theJpegImage: TJpegImage; 
begin 

    theBitmap := nil; 
    theJpegImage := TJPEGImage.Create; 
    theJpegStream:= TMemoryStream.Create; 
    theBitmapStream := TMemoryStream.Create; 

    try // 2 
     // ************************ BEGIN JPEG FRAME PROCESSING 

     // Load the JPEG image from the receive buffer. 
     theJpegStream.Size := intfReceiveBuffer.numBytesInBuffer; 
     Move(intfReceiveBuffer.bufPtr^, theJpegStream.Memory^, intfReceiveBuffer.numBytesInBuffer); 

     theJpegImage.LoadFromStream(theJpegStream); 

     // Convert to bitmap. 
     theBitmap := GetBitmap(theJpegImage); 

    finally 
     // Free memory objects. 
     if Assigned(theBitmap) then 
      theBitmap.Free; 
     if Assigned(theJpegImage) then 
      theJpegImage.Free; 
     if Assigned(theBitmapStream) then 
      theBitmapStream.Free; 
     if Assigned(theJpegStream) then 
      theJpegStream.Free; 
    end; // try() 
end; 

// --------------------------------------------------------------- 

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    processJpegFrame(FIntfReceiveBufferForClientSocket); 
end; 

// --------------------------------------------------------------- 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    S: string; 
begin 
    FIntfReceiveBufferForClientSocket := TReceiveBufferForClientSocket.Create(1000000); 

    S := loadStringFromFile('c:\test.jpg'); 

    FIntfReceiveBufferForClientSocket.assign(S); 
end; 

// --------------------------------------------------------------- 

Merci, Robert

+0

La taille du test JPEG affecte directement le nombre de défauts de page. Avec une image JPEG d'environ 2 Ko, j'ai eu un défaut de 80 pages. Avec une image de 40 Ko, il est passé à environ 2800. Je suis sûr que la vraie relation tourne autour de la taille des images quand elles ne sont pas compressées, mais le La taille de l'image JPEG fonctionne comme un proxy grossier pour indiquer que c'est le bitmap créé dynamiquement qui génère les fautes de la page douce. –

Répondre

0

Sonne comme les allocations que vous allouez et libre ne sont pas recyclés par le gestionnaire de mémoire.

Utilisez fastmm, ou mieux, regroupez-les et recyclez-les vous-même.

+0

J'utilise FastMM avec des options complètes sur. Il y a quelque chose avec la façon dont TJpegImage crée un TBitmap quand il décompresse pendant l'opération Assign() qui semble générer les fautes de page souples. –

+0

Essayez toujours de regrouper. Si la classe passe par un changement d'état, le regroupement peut aider, puisque la classe reste dans le même état. Dans de tels cas, la règle de base est toujours de minimiser les allocations dynamiques (répétées), puis d'aller plus loin. –

Questions connexes