Speicherleck bei Images

Für allgemeine Fragen zur Programmierung mit PureBasic.
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Speicherleck bei Images

Beitrag 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 ;)
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Speicherleck bei Images

Beitrag 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
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Re: Speicherleck bei Images

Beitrag 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?
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Speicherleck bei Images

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Re: Speicherleck bei Images

Beitrag 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.
Benutzeravatar
Rings
Beiträge: 971
Registriert: 29.08.2004 08:48

Re: Speicherleck bei Images

Beitrag 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.
Rings hat geschrieben:ziert sich nich beim zitieren
Benutzeravatar
Lupo
Beiträge: 147
Registriert: 16.02.2005 15:15

Re: Speicherleck bei Images

Beitrag 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
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Re: Speicherleck bei Images

Beitrag 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?
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Re: Speicherleck bei Images

Beitrag 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
Benutzeravatar
Lupo
Beiträge: 147
Registriert: 16.02.2005 15:15

Re: Speicherleck bei Images

Beitrag 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.
Antworten