Buenas tardes a todos!MakeScreenshot goteando?
En un proyecto actual, estoy experimentando una fuga de memoria bastante preocupante que parece que no puedo conectar.
Dejé la aplicación ejecutándose durante la noche con el uso estándar y cuando desperté 8 horas después, estaba consumiendo ~ 750MB de memoria mientras que comenzaba en ~ 50MB. El Administrador de tareas de Windows no es adecuado para verificar fugas que no sean para permitirle saber que existe una en primer lugar.
He aclarado algunas otras pérdidas de memoria ya, la principal está relacionada con Firemonkeys 'TGlowEffect
. No es detectado por ReportLeaksOnShutdown
pero el uso de la memoria se vuelve extremadamente excesivo en objetos modificados dinámicamente (por ejemplo, cambios de rotación o escala).
Lo he rastreado a un temporizador (y deshabilitarlo detiene por completo la fuga), y necesito ayuda para solucionarlo si es posible.
Descripción: Este código utiliza la función FireMonkey MakeScreenshot
para guardar la apariencia visual de un TPanel (SigPanel)
a un TMemoryStream
. Esta información de flujo se carga luego en un servidor FTP remoto utilizando un código estándar (ver a continuación). Dentro de SigPanel
, hay 4 TLabel
niños, 1 TRectangle
niño y 6 TImage
niños.
Notas:CfId
es una cadena global y se genera en base a un valor aleatorio extended
flotador que se hash a continuación, junto con el DateTime en formato yyyymmdd_hhnnsszzz
. Esta generación se realiza cuando se crea el formulario y se repite hasta que obtiene un CfId
válido (es decir, no contiene caracteres ilegales para su uso en nombres de archivos de Windows). Una vez que obtiene un CfId
válido, no se ejecuta de nuevo (ya que no hay necesidad de que genere una nueva ID). Esto me permite eliminar casi por completo la posibilidad de duplicar CfId
.
El código en el temporizador es el siguiente;
var
i : Integer;
SigStream : TMemoryStream;
begin
SigStream := TMemoryStream.Create;
SigPanel.MakeScreenshot.SaveToStream(SigStream);
SigPanel.MakeScreenshot.Free;
if VT2SigUp.Connected then
begin
VT2SigUp.Put(SigStream,'Sig_'+CfId+'.png',False);
end else
begin
VT2SigUp.Connect;
VT2SigUp.Put(SigStream,'Sig_'+CfId+'.png',False);
end;
SigStream.Free;
end;
Con el temporizador NO en funcionamiento, el código funciona completamente sin fugas y ReportMemoryLeaksOnShutdown
hace NO generar un mensaje. Con el temporizador habilitado y se le permite "correr" al menos una vez, estoy obteniendo una gran cantidad de fugas que aumentan cuantas más veces se ejecute el temporizador. Las filtraciones reportadas son las siguientes;
Small Block Leaks
1 - 12 Bytes: Unknown x 1
13 - 20 Bytes: TList x 5, Unknown x 1
21 - 28 Bytes: TFont x 2, TGradientPoint x 8, TGradientPoints x 4, Unknown x 4
29 - 36 Bytes: TObjectList<FMX.Types.TCanvasSaveState> x 1, TBrushBitmap x 4,
TBrushGrab x 4, TPosition x 24, TGradient x 4, UnicodeString x1
37 - 44 Bytes: TBrushResource x 4
53 - 60 Bytes: TBrush x 4
61 - 68 Bytes: TBitmap x 5
69 - 76 Bytes: TD2DCanvasSaveState x 1
205 - 220 Bytes: TCanvasD2D x 1
Sizes of Medium and Large Block Leaks
200236
Como el funcionamiento del temporizador, estos valores se multiplican n veces (n siendo el número de veces que el temporizador ha de ejecución). Los bloques medianos y grandes tienen n valor de 200236 (por ejemplo, si el temporizador se ha ejecutado 3 veces, es 200236, 200236, 200326).
De interés, si elimino el código asociado con MakeScreenshot
, la fuga ya no existe y el uso de la memoria se mantiene en un nivel algo normal. Además del uso habitual de la memoria, no hay nada fuera de lo común y no se informan las fugas. Probé varias muestras de código, tanto con guardar en una transmisión y cargar desde allí, o guardar en transmisión> Archivo y luego subir el archivo, pero parece que hay una fuga dentro de la función.Incluso agregué MakeScreenshot.Free
una vez que descubrí una fuga aquí, pero simplemente parece que no puedo conectarla, y por supuesto, he usado try..finally
en uno de mis "análisis de prueba" de código.
Incluso he ejecutado el código con GDI + como el tipo de lienzo y la misma fuga se produce allí (con el único cambio que las fugas D2D hacen referencia a GDI + en su lugar).
Agradecería cualquier investigación o notas que alguien tenga sobre esto y, además, una solución al problema.
Creo que acabas de encontrar una pérdida de memoria en FM (: – ComputerSaysNo
Creo que la configuración 'ReportMemoryLeaksOnShutdown: = True;' en la inicialización de su aplicación debe hacer el truco para mostrarle lo que se está filtrando ... –
@DorinDuminica Creo que sí. Sin embargo, creo que he encontrado que el 'Resultado' en 'FMX.Types.MakeScreenshot' no es realmente liberados. Simplemente están llamando a 'Result.Canvas.EndScene' y ¡nunca lo liberaron! @Je rryDodge Eso es lo que corrí para descubrir lo que se estaba filtrando exactamente, ya que no habría podido obtener una lista precisa sin él :) –