Seite 1 von 3

Speicherleck bei Images

Verfasst: 25.09.2017 18:55
von fabulouspaul
Hallo liebe Gemeinde,

ich weiß gerade nicht, ob ich was falsch mache oder ob ich einen Fehler im PB gefunden habe.
In einem Programm bearbeite ich sehr viele Images seriell hintereinander (immer nur eines zur Zeit im Speicher). Die Images werden mit LOADIMAGE() geladen und später mit FREEIMAGE() wieder freigegeben.
Trotzdem wird der RAM-Speicher nach und nach weniger bzw. im Taskmanager kann man verfolgen, wie das Programm nach und nach mehr Speicher konsumiert.

Hier ein Beispiel:

Code: Alles auswählen

EnableExplicit
UseTIFFImageDecoder()
UseJPEGImageDecoder()

Enumeration
  #img_handle
EndEnumeration

Global memex.MEMORYSTATUSEX
Global i

For i = 1 To 10000
  memex.MEMORYSTATUSEX
  memex\dwLength = SizeOf(MEMORYSTATUSEX)
  GlobalMemoryStatusEx_(@memex)
  Debug Str(i) +" RAM-Verbrauch vor IMAGELOAD(): "+Str((memex\ullTotalPhys-memex\ullAvailPhys)/1024/1024)+" MB"

  LoadImage(#img_handle, "test.tif")
  
  memex.MEMORYSTATUSEX
  memex\dwLength = SizeOf(MEMORYSTATUSEX)
  GlobalMemoryStatusEx_(@memex)
  Debug "RAM-Verbrauch nach IMAGELOAD(): "+Str((memex\ullTotalPhys-memex\ullAvailPhys)/1024/1024)+" MB"
  
  FreeImage(#PB_All)
  
  memex.MEMORYSTATUSEX
  memex\dwLength = SizeOf(MEMORYSTATUSEX)
  GlobalMemoryStatusEx_(@memex)
  Debug "RAM-Verbrauch nach FREEIMAGE: "+Str((memex\ullTotalPhys-memex\ullAvailPhys)/1024/1024)+" MB" + #LF$  
Next
Statt einer TIF-Datei funktioniert das auch mit JPGs - allerdings langsamer.
Ich habe es mit zig verschiedenen Images nachvollzogen, das Problem taucht immer auf.
Nachvollziehbar unter Windows 10 in PB 5.42/5.45/5.61 (x86 - x64 habe ich nicht probiert).

Fehler bei mir oder im PB... das ist die Frage. :)

PS: die Speicherabfrage habe ich mir bei RSBASIC ausgeliehen ;)

Re: Speicherleck bei Images

Verfasst: 25.09.2017 19:25
von Mijikai
Hab den Code etwas umgeschrieben bei mir ist alles ok...

Code:

Code: Alles auswählen

Procedure.i UsedMemory()
  Protected MSE.MEMORYSTATUSEX 
  MSE\dwLength = SizeOf(MEMORYSTATUSEX)
  If GlobalMemoryStatusEx_(@MSE)
    PrintN("RAM: "+Str((MSE\ullTotalPhys-MSE\ullAvailPhys)/1024/1024)+" MB")
  EndIf
EndProcedure
OpenConsole("IMG-Test!")
UsedMemory()
For i = 1 To 10000
  If LoadImage(#PB_Any,"XYZ.bmp")
    ii + 1
    FreeImage(#PB_All)
  EndIf
Next
PrintN(Str(ii) +" - images loaded & freed!")
UsedMemory()
Input()
CloseConsole()
End

Re: Speicherleck bei Images

Verfasst: 25.09.2017 20:10
von fabulouspaul
:( Hmmm, bei mir hilft das nicht.

Wenn ich Mijikais Code laufen lasse, erhalte ich trotzdem eine (zwar kleinere) Differenz beim RAM. Mein BMP hat DIN A4-Format und eine Dateigröße von ca. 450kB.

Code: Alles auswählen

RAM: 2235 MB
10000 - images loaded & freed!
RAM: 2238 MB
Wenn ich das BMP-Format gegen TIF austausche (gleicher Inhalt nur in anderes Format konvertiert; Dateigröße ca. 126kB) wird die Differenz deutlich grösser (nur 1000 Durchläufe weil es sonst so lange dauert).

Code: Alles auswählen

RAM: 2238 MB
1000 - images loaded & freed!
RAM: 2410 MB
Könnte es an der Grafik-Library liegen?

Ich habe mittlerweile auch den PC gewechselt, aber das Ergebnis bleibt.

@MIJIKAI: konntest Du denn mit meinem Code-Schnippsel das Problem bei Dir nachvollziehen?

Re: Speicherleck bei Images

Verfasst: 25.09.2017 21:44
von STARGÅTE
Wie verändert sich denn die Größe, wenn du mehr oder weniger Images lädst?

Ich würde ehr vermuten, dass es die jeweiligen Dekoder-Bestandteile sind, die beim ersten LoadImage in den Ram geladen (initialisiert) werden.

Re: Speicherleck bei Images

Verfasst: 25.09.2017 22:07
von fabulouspaul
@Stargate: je mehr Images geladen (und dann auch wieder freigegeben werden) desto mehr speicher wird belegt. Oder meinst Du wenn man mehr als ein Image gleichzeitig im Speicher hält (also x Images laden und dann einmal freigeben mit #PB_all)? Das probiere ich morgen mal aus.

Da es jeder Dekoder macht (BMP, TIF, JPG ausprobiert, unterscheiden sich nur in der Größenordnung in dem sie Speicher nicht wieder freigeben) und das bei jedem LOADIMAGE() bin ich noch nicht sicher was es ist.
#PB_ANY und eine als Konstante vergebene Image-Nummer spielen schonmal keine Rolle.

Re: Speicherleck bei Images

Verfasst: 26.09.2017 09:17
von Rings
poste doch bitte einmal ein Bild, wo genau das passiert.
Oder besser noch erstelle ein zip wo code und bild drin ist,
so das man es direkt out of the box selbst ausprobieren kann.

Dann wird es einfacher das Problem einzugrenzen und evtl. auch zu fixen.

Re: Speicherleck bei Images

Verfasst: 26.09.2017 16:50
von Lupo
Ich hatte bei einer älteren PB-Version (4.5) einen eigenartigen Fehler mit einem Crash in Abhängigkeit der Abfolge der Zeilen UseTIFFImageDecoder() und UseJPEGImageDecoder().

Schrieb man UseTIFFImagedecoder() vor UseJPEGImagedecoder() so gab es einen Crash in weiterer Folge. Schrieb man die zwei Zeilen vertauscht, hat alles bestens funktioniert. Der Fehler wurde mit Version 4.60 RC2 laut Kommentar behoben.

Eventuell hat sich da wieder was eingeschlichen? Es wäre ein rascher Versuch, einmal diese beiden Zeilen zu vertauschen!

http://forums.purebasic.com/german/view ... 16&t=24787

Re: Speicherleck bei Images

Verfasst: 28.09.2017 13:13
von fabulouspaul
Ich habe noch mal eine Weile herumexperimentiert.

Der Fehler tritt immer beim Laden von Images im TIF-Format auf und ist leicht nachvollziehbar, wenn man den Taskmanager öffnet und sich den Zuwachs des Speicherverbrauchs des folgenden kompilierten Programms anschaut:

Code: Alles auswählen

UseTIFFImageDecoder()

Enumeration
  #img_handle
EndEnumeration
MessageRequester("!", "Schau auf den Speicherverbrauch im Taskmanager!")
For i = 1 To 1000
  LoadImage(#img_handle, "testimage.tif")
  FreeImage(#PB_All)    ; #PB_All kann auch gegen #img_handle ersetzt werden -> gleiches Ergebnis
Next 
MessageRequester("!", "Schau auf den Speicherverbrauch im Taskmanager!")
End
Das TIF kann ein beliebiges Image sein (größere Formate äußern sich in schneller wachsendem Speicherverbrauch).
Da das TIF-Format eine Art Container für verschiedene Image-Komprimierungen ist, habe ich verschiedene Komprimierungsmethoden ausprobiert.
Besonders krass war das Ergebnis mit einem TIF-Image in schwarz/weiß komprimiert nach Fax G3. Hier hat sich der Speicherverbrauch des Programms von 1.820kB auf sagenhafte 241.492kB vermehrt! Bei Fax G4 war es noch stolze 124.632kB und bei JPG immerhin noch 87.472kB.

Probiert man gleiches mit einem Image im JPG-Format (UseJPEGImageDecoder()), ergibt sich jeweils nur ein konstanter größerer Speicherverbrauch (auf 1.968kB) der vermutlich aus der von Stargate erwähnten Initialisierung des Decoders resultiert.

Kann das jemand bei sich nachvollziehen?

Re: Speicherleck bei Images

Verfasst: 28.09.2017 13:35
von fabulouspaul
Lupo hat geschrieben: Eventuell hat sich da wieder was eingeschlichen? Es wäre ein rascher Versuch, einmal diese beiden Zeilen zu vertauschen!
Hallo Lupo,

das passiert auch, wenn ich nur den TIF-Decoder im Code habe :P

Re: Speicherleck bei Images

Verfasst: 28.09.2017 16:57
von Lupo
Dann wird es wohl nicht das Reihenfolgeproblem von UseTIFFImageDecoder() und UseJPEGImageDecoder() bei PB4.5x sein.

Ich habe deinen Code mit PB4.51 mit W7/32 getestet und es gibt keine Speicherlecks.

Das hätte mich auch gewundert, da beim mir an die 10000 s/w-Tiffs pro Tag durch den Server laufen und da wären Speicherprobleme in jedem Fall aufgefallen. Aber wie gesagt, da läuft PB4.51.

Leider habe ich hier an dem Arbeitsplatz hier kein aktuelles PB zur Hand.

Ganz ausschließen könnte man aber nicht, dass das Leck vom geladenen Tiff-Bild abhängig ist. Multi-Tiff kämen mir da in den Sinn. Eventuell könntest du dein Testbild zum Download bereitstellen?

Sicher könnte dann auch ein Kollege mit einer aktuellen PB-Version testen.