AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert
Thema durchsuchen
Ansicht
Themen-Optionen

Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

Ein Thema von moelski · begonnen am 18. Sep 2010 · letzter Beitrag vom 16. Nov 2016
Antwort Antwort
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 8. Nov 2016, 19:22
Der Punkt mit den Forms ist gut, aber mit MSDN-Library durchsuchenSetProcessWorkingSetSize die Pages zwangsweise auslagern zu wollen ist in meinen Augen großer Schwachsinn. Windows macht das nämlich ganz von alleine, wenn die betroffene Page einige Zeit lang nicht mehr verwendet wurde. Greift das Programm irgendwann wieder darauf zu, gibt es ein Page Fault und der Windows Memory Manager läd die Seite wieder in den RAM. Da sind im Hintergrund Algorithmen aktiv, die ziemlich gute Vorhersagen treffen.

Außerdem adressiert die diese API wieder nicht das eigentliche Problem. Also nochmal: Die großen Bitmaps erfordern große zusammenhängende Speicherblöcke im virtuellen Adressraum. Die Pages auszulagern entlastet aber nicht den virtuellen Adressraum, sondern nur den physikalischen Speicher.

Deshalb kann ich auch nur nochmal empfehlen die ganze Herangehensweise mit Messen des aktuell benutzten Speichers so schnell wie möglich zu vergessen. Man kann einfach nicht zuverlässig vorhersagen ab welcher Größe ein EOutOfMemory auftreten wird. Wie gesagt kann es sogar passieren, dass dein Prozess noch kaum Arbeitsspeicher verwendet, aber dank Fragmentierung kein genügend großer zusammenhängender Block verfügbar ist. Kannst du ganz leicht testen, indem du mal 1 GiB Speicher am Stück mit GetMem anforderst. Dieser Aufruf wird bei einem 32-Bit Programm in den meisten Fällen direkt scheitern. 1 GiB in mehreren kleinen 10 MiB Blöcken anzufordern, wird dahingegen sehr wahrscheinlich Erfolg haben. Auch wirst du merken, dass dein Bitmap Tool als 64-Bit Kompilat ohne Änderung vermutlich sehr viele Bitmaps mehr laden kann. Schlussfolgerung ist, dass nicht der physikalische RAM das Limit darstellt, sondern der virtuelle Adressraum.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl ( 8. Nov 2016 um 19:28 Uhr)
  Mit Zitat antworten Zitat
Jim Carrey
(Gast)

n/a Beiträge
 
#2

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 8. Nov 2016, 20:21
Das mit den Forms mache ich teilweise auch so. Ich erstelle komplexe Formulare erst wenn sie wirklich benötigt werden.
Das verschnellert den Programmstart und hält den Speicherverbrauch ein wenig niedriger.
Hat einzig den Nachteil der Usability im Sinne von "Wenn ich da drauf klicke, soll sofort was passieren" - ist dann eben nicht der Fall.
  Mit Zitat antworten Zitat
Bambini
(Gast)

n/a Beiträge
 
#3

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 09:15
Das mit den Forms mache ich teilweise auch so. Ich erstelle komplexe Formulare erst wenn sie wirklich benötigt werden.
Das verschnellert den Programmstart und hält den Speicherverbrauch ein wenig niedriger.
Hat einzig den Nachteil der Usability im Sinne von "Wenn ich da drauf klicke, soll sofort was passieren" - ist dann eben nicht der Fall.
... das wäre doch eine schöne Aufgabe für einen Hintergrund-Thread.
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
578 Beiträge
 
Delphi 12 Athens
 
#4

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 14:32
Jetzt habe ich Zacherls Vorschlag implementiert. Funktioniert auch. Aufgrund der Streams kann die Größe der Bitmaps jetzt genau angegeben werden. Der Taskmanager - der ja augenscheinlich erschütternd unzuverlässig ist - zeigt nun statt 500 MB nur noch 180 MB an.
Die ganze Geschichte läuft aber merklich langsamer ab als mit den direkt gespeicherten Bitmaps. Die Erstellung der Bitmaps/Streams ist in asychrone Threads ausgelagert, auch damit scheint es Probleme zu geben, das Programm hängt sich bei forcierter Belastung auf ("forcierte Belastung" heißt, ich halte die Weiter-Taste gedrückt und nudle 100 Bilder durch, dadurch müssen pausenlos Bilder geladen, gelesen und verworfen werden). Hab's jetzt aber noch nicht richtig handoptimiert, mal sehen.
  Mit Zitat antworten Zitat
Bambini
(Gast)

n/a Beiträge
 
#5

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 15:13
Jetzt habe ich Zacherls Vorschlag implementiert. Funktioniert auch. Aufgrund der Streams kann die Größe der Bitmaps jetzt genau angegeben werden. Der Taskmanager - der ja augenscheinlich erschütternd unzuverlässig ist - zeigt nun statt 500 MB nur noch 180 MB an.
Die ganze Geschichte läuft aber merklich langsamer ab als mit den direkt gespeicherten Bitmaps.
Nun ja, der Stream liegt damit jetzt nicht mehr im RAM sondern alle auf der Platte. Auch wenn Windows hierbei einiges puffert. So schnell wie RAM ist eine Platte nie
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
578 Beiträge
 
Delphi 12 Athens
 
#6

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 16:00
Laut Zacherl müsste das alles im RAM liegen.
  Mit Zitat antworten Zitat
Bambini
(Gast)

n/a Beiträge
 
#7

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 16:43
Laut Zacherl müsste das alles im RAM liegen.
wenn du diesen Code verwendest:
Delphi-Quellcode:
 inherited Create(CreateFile(PChar(TPath.GetTempFileName), GENERIC_READ or GENERIC_WRITE,
    0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY or
    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED or FILE_ATTRIBUTE_HIDDEN or FILE_FLAG_DELETE_ON_CLOSE, 0));
dann nicht.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#8

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 17:13
Laut Zacherl müsste das alles im RAM liegen.
Laut Zacherl müsste das alles im RAM liegen.
wenn du diesen Code verwendest:
Delphi-Quellcode:
 inherited Create(CreateFile(PChar(TPath.GetTempFileName), GENERIC_READ or GENERIC_WRITE,
    0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY or
    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED or FILE_ATTRIBUTE_HIDDEN or FILE_FLAG_DELETE_ON_CLOSE, 0));
dann nicht.
Beachte das FILE_ATTRIBUTE_TEMPORARY Flag. Solange dem System genug freier physikalischer zur Verfügung steht und nichts ausgelagert werden muss, befindet sich die Datei tatsächlich komplett im RAM.

Der Taskmanager - der ja augenscheinlich erschütternd unzuverlässig ist - zeigt nun statt 500 MB nur noch 180 MB an.
Wie gesagt, der Taskmanager zeigt mit dem WorkingSet nur den momentan tatsächlich physikalisch verwendeten Speicher des Prozesses an. Also exklusive ausgelagerter Pages. Daten, die du in den FileCache lädst sind darin auch nicht enthalten.

Die ganze Geschichte läuft aber merklich langsamer ab als mit den direkt gespeicherten Bitmaps. Die Erstellung der Bitmaps/Streams ist in asychrone Threads ausgelagert, auch damit scheint es Probleme zu geben, das Programm hängt sich bei forcierter Belastung auf ("forcierte Belastung" heißt, ich halte die Weiter-Taste gedrückt und nudle 100 Bilder durch, dadurch müssen pausenlos Bilder geladen, gelesen und verworfen werden). Hab's jetzt aber noch nicht richtig handoptimiert, mal sehen.
Tatsächlich haben auch diese speziellen Streams einen Performance Nachteil gegenüber der direkten Speicherung im RAM. Das liegt mitunter daran, dass Windows die Dateien im Filesystem "simuliert" und auch Eigenschaften wie die letzte Zugriffszeit etc. jeweils aktualisiert. Normalen FileStreams sind sie aber trotzdem noch weit überlegen.

Optimieren könntest du noch, indem du nach dem Laden des ersten Bildes im Hintergrund schon anfängst Nummer zwei (und evtl. danach noch Nummer 3) zu laden, etc. Sind sicher noch einige Verbesserungen drinnen.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
t.roller
(Gast)

n/a Beiträge
 
#9

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 19:00
Schon mal an RAMDisk gedacht?
Angehängte Grafiken
Dateityp: jpg 20140124_Ramdiskwindows_write.jpg (46,6 KB, 16x aufgerufen)
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
578 Beiträge
 
Delphi 12 Athens
 
#10

AW: Speicherlast des Programms mittels GetMemoryManagerState - komischer Wert

  Alt 9. Nov 2016, 19:07
Optimieren könntest du noch, indem du nach dem Laden des ersten Bildes im Hintergrund schon anfängst Nummer zwei (und evtl. danach noch Nummer 3) zu laden...
Das geschieht ja mit den asynchronen Threads, und da ich einen Threadpool mit MaxThreads := 2 * System.CPUCount; verwende, werden sogar alle BMP gleichzeitig geladen (und geht bei einer SSD richtig schnell, bei einer normalen Festplatte ist das eher kontraproduktiv). Dieses Laden geht bei Bitmaps viel schneller. Aber daran könnte ich wohl noch schrauben.

RAMDisk sieht sehr interessant aus, ist für meine Anwendung aber eher nichts (müsste erst eingerichtet werden, der Platzbedarf ändert sich dauernd mit den Einstellungen und der Größe der Bitmaps usw.). Aber für andere Sachen wäre das vielleicht wirklich interessant!

PS:
Ich habe jetzt in einer Schleife 100 Bilder einzeln geladen, dekomprimiert, in den Stream geladen und wieder freigegeben. Das dauerte etwa 37 Sekunden, also eine drittel Sekunde pro Bild. Das Wiederauslesen des Streams und Laden in ein Bitmap verlängerte die Prozedur um 5 Sekunden, also eine Zwanzigstelsekunde je Bitmap. Da scheint mir kaum Potenzial für Verbesserungen zu sein. Ich gucke mir nochmal das Management der Threads an.

PPS:
Das RAM-Disk-Tool ImDisk findet man jetzt hier, oder besser noch bei Sourceforge mit Konfigurator.

PPPS:
Von der RAM-Disk aus läuft der Prozess mit den 100 Bildern in 35 (!) Sekunden. Das scheint mir kein echtes Optimierungspotenzial.

Geändert von Benmik ( 9. Nov 2016 um 20:05 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz