Buona sera a tutti!MakeScreenshot perde?
In un progetto corrente, sto vivendo una perdita di memoria piuttosto preoccupante che non riesco a collegare.
Ho lasciato l'applicazione in esecuzione durante la notte con l'utilizzo standard in corso e quando mi sono svegliato 8 ore più tardi, stava mangiando fino a ~ 750 MB di memoria mentre iniziò a ~ 50 MB. Task Manager di Windows non è adatto per il controllo di perdite diverse dal consentire di scoprire che ne esiste uno in primo luogo.
Ho risolto alcune altre perdite di memoria già, con la principale collegata a Firemonkeys 'TGlowEffect
. Non viene rilevato da ReportLeaksOnShutdown
ma l'utilizzo della memoria di esso diventa estremamente eccessivo su oggetti modificati dinamicamente (ad esempio, cambi di scala o di scala).
L'ho rintracciato fino a un timer (e disabilitandolo interrompe completamente la perdita), e ho bisogno di assistenza per ripararlo se possibile.
Descrizione: Questo codice utilizza la funzione FireMonkey MakeScreenshot
per salvare l'aspetto visivo di un TPanel (SigPanel)
ad un TMemoryStream
. I dati del flusso vengono quindi caricati su un server FTP remoto utilizzando un codice standard (vedere di seguito). All'interno di SigPanel
, ci sono 4 bambini TLabel
, 1 TRectangle
bambini e 6 TImage
bambini.
Note:CfId
è una stringa globale e viene generato in base su un extended
valore float casuale che viene poi hash con il DateTime in formato yyyymmdd_hhnnsszzz
. Questa generazione viene eseguita quando il modulo viene creato e si ripete finché non diventa un valore valido CfId
(ovvero non contiene caratteri illegali per l'utilizzo nei nomi file di Windows). Una volta ottenuto un valore valido per CfId
, non viene eseguito nuovamente (poiché non è necessario generare un nuovo ID). Questo mi consente di eliminare quasi completamente la possibilità di duplicare CfId
.
Il codice nel timer è il seguente;
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 il timer NON esecuzione, le funzioni di codice completamente senza perdite e ReportMemoryLeaksOnShutdown
fa NON generare un messaggio. Con il timer abilitato e il permesso di "correre" almeno una volta, sto ottenendo un sacco di perdite che aumenta il numero di volte in cui il timer viene eseguito. Le perdite riportate sono le seguenti;
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
Come viene eseguito il timer, questi valori sono moltiplicati n volte (n essendo il numero di volte in cui il timer è eseguito). I blocchi medi e grandi hanno n del 200236 (ad esempio se il timer ha eseguito 3 volte, è 200236, 200236, 200326).
Di Interesse, se rimuovo il codice associato a MakeScreenshot
, la perdita non esiste più e l'utilizzo della memoria rimane a un livello un po 'normale. Oltre al consueto utilizzo della memoria, non c'è nulla fuori dall'ordinario e non vengono segnalate perdite. Ho provato più esempi di codice, sia con il salvataggio in un flusso e il caricamento da lì, o il salvataggio in streaming> File e quindi il caricamento del file, ma sembra esserci una perdita all'interno della funzione stessa.Ho anche aggiunto MakeScreenshot.Free
una volta che ho scoperto una perdita qui, ma semplicemente non riesco a collegarlo, e, naturalmente, ho usato try..finally
in uno dei miei "test di codice" del mio codice.
Ho persino eseguito il codice con GDI + come tipo di tela e la stessa perdita si verifica lì (con l'unica differenza che il D2D perde riferimento GDI + invece).
Apprezzerei molto qualsiasi ricerca o note che qualcuno ha su questo e, inoltre, una soluzione al problema.
Credo che hai appena trovato una perdita di memoria in FM (: – ComputerSaysNo
Credo che l'impostazione 'ReportMemoryLeaksOnShutdown: = True;' nell'inizializzazione della tua app dovrebbe fare il trucco per mostrarti cosa sta perdendo ... –
@DorinDuminica Credo di sì, ma credo di aver trovato il problema è che il 'Risultato' in' FMX.Types.MakeScreenshot' non è effettivamente liberati. Stanno chiamando semplicemente "Result.Canvas.EndScene' e non lo liberano mai! @Je rryDodge Questo è quello che ho cercato per scoprire cosa stava perdendo esattamente come non sarei stato in grado di ottenere una lista precisa senza di essa :) –