Autor |
Beitrag |
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 24.12.11 11:45
Für ein etwas größeres Projekt muss ich rund 5000, meist kleinere, GIF- und JPG-Bilder verwalten und gegebenenfalls laden und anzeigen.
Bisher liegen die Dateien einzeln in mehreren Ordnern, sind im Moment in der Summe 80 MByte groß, belegen aber gute 95 MByte. Außerdem ist das Kopieren auf verschiedene Datenträger langwierig.
Aus diesem Grund möchte ich die Dateien in eine einzige Resourcen-DLL (wahrscheinlich um 80 MByte) packen.
Erste Versuche mit gerade mal 200 Bildern sind ganz erfolgreich. Für das Laden eines Bildes rufe ich loadlibrary, danach den Stream und gebe mit freelibrary alles wieder frei.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure gif_dll_laden(const kk:string;image:timage); var hl :HINST; Stream: TStream; GIF: TGIFImage; Bitmap: TBitmap; begin hl := LoadLibrary('bgif.dll'); try Stream := TResourceStream.Create(hl,kk,'GIF'); try GIF := TGIFImage.Create; try GIF.LoadFromStream(Stream); Image.Picture.Assign(nil); Bitmap := TBitmap.Create; try Bitmap.Assign(GIF); Image.Picture.Assign(Bitmap); finally Bitmap.Free; end; finally GIF.Free; end; finally Stream.Free; end; finally FreeLibrary(hl); end; end; |
Allerdings habe ich ein Problem, da mir nicht klar ist, wie Windows derartige Resourcen-DLLs verwaltet.
Angenommen ich möchte nur ein kleines GIF-Bild von etwa 2 kbyte aus der DLL laden, frage ich mich, wie Windows vorgeht.
Wird die ganze(!) DLL in den Speicher geladen (das wäre extrem langsam und damit untauglich) oder wird nur die Liste der Resourcen und die Adresse des Bildes geladen und danach gezielt der Speicherbereich, welcher das gewünschte Bild enthält.
Da es zukünftig wahrscheinlich noch mehr Bilder werden, wird eine solche DLL auch immer größer.
Vielleicht kann mir jemand helfen.
Moderiert von Gausi: Delphi-Tags hinzugefügt
|
|
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Sa 24.12.11 15:08
Hallo und in der Entwickler-Ecke!
Soweit ich weiß, mappt LoadLibrary alle Segmente in den Speicher. Dürfte aber bedeuten, dass die nicht von der Platte gelesen werden, bis wirklich was passiert - also sofort Ich denke, das Resourcensegment wird dann komplett gelesen... aber wirklich weiß ich das nicht.
Spricht etwas gegen ein einfaches Zip-Archiv?
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 24.12.11 20:02
Vielen Dank für die schnelle Antwort.
Zip-Archiv klingt gut. Ich müsste aber aus diesem Archiv mit dem Delphi-Programm das gewünschte Bild lesen. Geht das überhaupt ohne Zusatzkomponenten?
|
|
jaenicke
Beiträge: 19288
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 24.12.11 21:00
Da du in deinem Profil deine Delphiversion nicht angegeben hast, kann dir diese Frage niemand direkt beantworten. Falls du XE2 hast, lautet die Antwort ja, bei älteren Versionen nein.
Bei Delphi XE2 kannst du die Unit System.Zip in die uses schreiben und hast dann direkt mit TZipFile eine native Kapselung des ZIP Formats zur Verfügung.
Für Delphi XE und früher kann ich dir Abbrevia empfehlen. Das kannst du unter der MPL nutzen und ist sehr einfach.
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 24.12.11 22:24
Ich arbeite noch mit der "Steinzeit"-Version Delphi 5, die mir aber bisher alles geliefert hat, was ich brauchte.
Außerdem gehöre ich noch zu denen, die gern alles selbst erstellen.
Ich habe erst einmal Abbrevia geladen und werde sehen, ob es unter Delphi 5 funktioniert.
Dank für den Hinweis.
Nachtrag:
Wie zu erwarten, weigert sich mein Delphi 5 Abbrevia zu nutzen.
Ich werde etwas suchen, vieleicht find ich eine Alternative. Wenn nicht, erstelle ich meine große Resourcen-DLL (wird einiges an Arbeit) und dann sehe ich ja, ob es noch vernünftige Ladezeiten gibt.
|
|
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Sa 24.12.11 22:42
Abbrevia fand ich immer sinnlos groß und kompliziert. Ich kann KAZip empfehlen, da war allerdings irgendwann mal ein Bug beim extrahieren in einen MemoryStream. Der äußert sich allerdings in einer Exception, ist also sehr offensichtlich
Steht zwar D6/7 dran, aber soweit ich mich erinnern kann hatte ich das auch mal mit D4 zum laufen bekommen.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
BenBE
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 25.12.11 00:15
Es gibt mit LoadLibraryEx die Möglichkeit Windows die Verwendung der DLL mitzuteilen. Damit ist es möglich, dass man Windows den teilweise recht aufwändigen Schritt der Relocation von Code-Segmenten erspart und stattdessen wirklich nur die Datensegmente in den Speicher läd. Im Zweifelsfalle möchtest Du deine Resourcen-DLL aber auch nicht für jedes Bild neu laden, sondern einmal beim Programmstart holen und dann basierend auf dieser einmalig geladenen Kopie alle Resourcen lesen. Damit ersparst Du dir das ständige Lesen von der Platte.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Für diesen Beitrag haben gedankt: Mathematiker
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 26.12.11 11:40
JPG-Files in ein ZIP-File zu packen macht keinen Sinn.
|
|
Boldar
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mo 26.12.11 11:57
Doch, wenn es so viele sind. Das verringert enorm die fragmentierung und erhöht die Kopiergeschwindigkeit.
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 26.12.11 14:09
Die Komponente TPictureContainer ist vermutlich besser geeignet:
Hier enthalten:
www.delphipages.com/download.php?id=2188
Zuletzt bearbeitet von hathor am Mo 26.12.11 15:18, insgesamt 1-mal bearbeitet
|
|
jaenicke
Beiträge: 19288
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 26.12.11 15:08
Die Komponente hat den gravierenden Nachteil, dass die Dateien direkt in der .exe landen. Für Anfänger mag das erst einmal interessant klingen, weil es "cool" ist, wenn es nur eine Datei ist, aber für 90% der normalen Anwendungsfälle taugt das weniger.
Das hat mehrere Gründe: - Wenn die Anwendung sehr groß ist, dauert es umso länger, wenn man mit dem Windows Explorer den Ordner anschaut, insbesondere wenn die Anwendung auf einem langsamen Datenträger wie einem USB-Stick liegt. Denn es wird die ganze Datei analysiert.
- Wenn man nur ein Bild austauschen will, muss man die ganze Anwendung neu kompilieren und austauschen.
- Man kann programmseitig die Dateien nicht verändern.
|
|
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 26.12.11 16:14
hathor hat folgendes geschrieben : | JPG-Files in ein ZIP-File zu packen macht keinen Sinn. |
Ich hab nie was von komprimieren gesagt. ZIP kann auch "store" statt "deflate".
Boldar hat folgendes geschrieben : | Doch, wenn es so viele sind. Das verringert enorm die fragmentierung und erhöht die Kopiergeschwindigkeit. |
Sagen wir "wenn es viele kleine sind". Viele Dateien die einzeln nicht mal ein Cluster füllen würden verschwenden extrem Performance.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 26.12.11 17:46
|
|
jaenicke
Beiträge: 19288
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 26.12.11 17:50
Dass das geht, ist klar, aber ich sehe da eigentlich nur Nachteile gegenüber z.B. einem Zip-Archiv. (Langsamer, keine Baumstruktur, Dateiformat muss zusätzlich verwaltet werden, schlecht durch den Anwender änderbar, ...)
Worin siehst du denn da einen Vorteil?
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 27.12.11 01:54
Ich finde eine Bilder-Datenbank sehr reizvoll, weil sie beliebig erweiterbar ist, z.B. mit Bild-Beschreibungen (Autor, Datum, Kamera, Ort, MP3-Files mit Soundausgabe oder AVI-Filmchen, individuelle Einstellung der Dia-Wechsel, etc.)
3 Anhänge: Bitte die Inline-Anhänge einblenden
Einloggen, um Attachments anzusehen!
Zuletzt bearbeitet von hathor am Di 27.12.11 11:21, insgesamt 3-mal bearbeitet
|
|
baka0815
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Di 27.12.11 10:50
Dann aber doch eher SQLite als Access...
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Mi 08.02.12 00:22
Mittlerweile habe ich über 2500 GIFs, 600 animierte GIFs und 1200 JPG-Dateien in jeweils eine DLL gepackt. Diese haben 22 MByte, 15 MByte und 28 MByte Umfang, sind also noch nicht sehr groß.
Dennoch kann ich jetzt schon feststellen, dass mit dem Tipp
BenBE hat folgendes geschrieben : | Es gibt mit LoadLibraryEx die Möglichkeit Windows die Verwendung der DLL mitzuteilen. |
Windows (Vista und 7) bei einem Aufruf eines Bildes in den DLLs nur die jeweils benötigten Daten ruft.
Fazit: Durch das Packen in die DLLs wurde die Ladezeit für mehrere Bildaufrufe sogar noch gesenkt! Ein Test, bei dem einmal die einzelnen Dateien von der Festplatte geladen wurden, zum anderen aus einer DLL heraus, ergab einen klaren Geschwindigkeitsgewinn für die DLL.
Damit ist mein Problem gelöst.
Vielen Dank für die Hinweise.
Mathematiker
|
|
Mathematiker
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Mo 05.03.12 22:18
Hallo,
ich muss das Thema noch einmal aufgreifen, da ich mittlerweile bei einem Gesamtumfang von 100 MByte DLL bin und es noch mehr wird.
Da ich mich schon mit Computern herumgeärgert habe, als die meisten im Forum noch nicht geboren waren, bekomme ich ein Problem nicht aus dem Kopf: Eines der Hauptkriterien für ein gutes Programm war stets die minimale(!) Nutzung des Hauptspeichers. Mein erster PC hatte gerade mal 64 kbyte Hauptspeicher, wirklich!
Nun frage ich mich, wie weit man heute einen Rechnerspeichner belasten darf. Lese ich die DLL zu Programmbeginn ein, bekomme ich zwar einen Geschwindigkeitsgewinn während des Programmlaufs, der vom Programm genutzte Speicher erreicht aber schnell die 100 MByte.
Hat jemand eine Empfehlung, wieviel man noch vertretbar als Arbeitsspeicher "okkupieren" darf oder ist eine solche Frage in Zeiten von Gigabyte-Speichern sinnlos?
Grüße
Mathematiker
|
|
jaenicke
Beiträge: 19288
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 05.03.12 22:47
Das kommt auf das Programm und dessen Zielgruppe an. Wenn die Nutzer größtenteils einen starken PC haben, kannst du das auch nutzen. Ich kenne aber auch viele, die nicht so viel RAM haben. Da wäre das eher ungünstig.
Wenn jemand nicht so viel RAM hat, wird der Speicher auf die Festplatte ausgelagert. Dann kann es sein, dass du eine deutlich geringere Geschwindigkeit hast als z.B. mit MMFs. Solange genug Speicher da ist, sollte deine jetzige Lösung aber nicht viel langsamer sein als MMFs.
Für diesen Beitrag haben gedankt: Mathematiker
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 06.03.12 11:03
GetMaxAppAddress : 1,99 GB (2147418111)
GetMinAppAddress : 64 KB (65536)
Maximaler Speicher, der einer EXE zugeteilt wird: GetMaxAppAddress - GetMinAppAddress
|
|
|