Autor Beitrag
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Sa 24.12.11 12: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.

ausblenden 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 user profile iconGausi: Delphi-Tags hinzugefügt
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Sa 24.12.11 16:08 
Hallo und :welcome: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Sa 24.12.11 21: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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 24.12.11 22: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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Sa 24.12.11 23: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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Sa 24.12.11 23: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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: So 25.12.11 01: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



BeitragVerfasst: Mo 26.12.11 12:40 
JPG-Files in ein ZIP-File zu packen macht keinen Sinn.
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Mo 26.12.11 12:57 
Doch, wenn es so viele sind. Das verringert enorm die fragmentierung und erhöht die Kopiergeschwindigkeit.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 26.12.11 15: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 16:18, insgesamt 1-mal bearbeitet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 26.12.11 16: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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mo 26.12.11 17:14 
user profile iconhathor hat folgendes geschrieben Zum zitierten Posting springen:
JPG-Files in ein ZIP-File zu packen macht keinen Sinn.
Ich hab nie was von komprimieren gesagt. ZIP kann auch "store" statt "deflate".

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
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



BeitragVerfasst: Mo 26.12.11 18:46 
Anregung:
Pictures inside a database
delphi.about.com/od/...base/l/aa030601a.htm
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 26.12.11 18:50 
Dass das geht, ist klar, aber ich sehe da eigentlich nur Nachteile gegenüber z.B. einem Zip-Archiv. :gruebel: (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



BeitragVerfasst: Di 27.12.11 02: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 12:21, insgesamt 3-mal bearbeitet
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: Di 27.12.11 11:50 
Dann aber doch eher SQLite als Access...
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 08.02.12 01: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
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
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. :lol:

Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mo 05.03.12 23: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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 05.03.12 23: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



BeitragVerfasst: Di 06.03.12 12:03 
GetMaxAppAddress : 1,99 GB (2147418111)
GetMinAppAddress : 64 KB (65536)

Maximaler Speicher, der einer EXE zugeteilt wird: GetMaxAppAddress - GetMinAppAddress