| Autor |
Beitrag |
LonghornUser
      
Beiträge: 796
|
Verfasst: So 23.05.10 18:07
Hallo,
ich habe im Moment das Problem, dass das Schreiben von INI-Dateien schon bei einer Größe von ~1KB knapp 1 Sekunde dauert. Wenn ich das ganze auf einem langsameren Rechner (Notebook) mache, dauert es schon 5-6 Sekunden.
Ist das normal?? Gibt es eine Möglichkeit, diesen Vorgang zu beschleunigen (etwa ein anderes Format)?
Danke!!
Ciao LHUser
|
|
jaenicke
      
Beiträge: 19335
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 23.05.10 18:21
Da machst du wohl etwas falsch, aber ohne Code kann da niemand etwas dazu sagen.
Ich hatte jedenfalls damals als ich noch INIs verwendet habe auch größere in wenigen Millisekunden eingelesen oder erstellt. Die Frage ist aber wie, denn es gibt die API-Funktionen, die Delphikapselung dazu (beides deprecated, also veraltet markiert, da nur für Kompatibilität zu Windows 3.x noch vorhanden) und eigene Möglichkeiten.
Zum Vergleich: Das Einlesen von Registrydateien, die im Grunde ja auch nur INIs sind, schaffe ich mit ca. 30-90 MiB/s, je nach Festplattengeschwindigkeit...
// EDIT:
Ach ja: wenn dir Geschwindigkeit wichtig ist, warum benutzt du dann INI-Dateien?!?
|
|
Gausi
      
Beiträge: 8553
Erhaltene Danke: 479
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: So 23.05.10 19:17
Ini-Dateien sind nicht zur Datenspeicherung da, aber ich habe auch einige im Bereich von einigen kb. Nutzt du TIniFile oder TMemIniFile? Letzteres arbeitet erstmal nur im Speicher, auf Platte muss explizit durch MyIni.UpdateFile geschrieben werden.
Hatte das Problem mal, als ich noch mit einer Diskette gearbeitet habe. Mit IniFile war das Laufwerk ne Minute am rödeln, mit TMemIniFile ging das recht flott. 
_________________ We are, we were and will not be.
|
|
hansa
      
Beiträge: 3079
Erhaltene Danke: 9
|
Verfasst: So 23.05.10 19:32
| Zitat: | Hatte das Problem mal, als ich noch mit einer Diskette gearbeitet habe. Mit IniFile war das Laufwerk ne Minute am rödeln, mit TMemIniFile ging das recht flott.  |
Dann hätteste mal einwandfreie Diskette nehmen sollen und keine mit zig Lesefehlern. 
_________________ Gruß
Hansa
|
|
Gausi
      
Beiträge: 8553
Erhaltene Danke: 479
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: So 23.05.10 20:01
Lesen ging auch recht zügig, aber 200 mal Schreibzugriff auf ne Floppy war dann doch etwas doof. 
_________________ We are, we were and will not be.
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Mo 24.05.10 13:56
OK. Da ich auch denke, dass ich nur einen Fehler drin habe, der die Sache lang macht, hier mal der entsprechende (gekürzte) Quelltext:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
| procedure TForm1.Save(Filename:String); var ini:TIniFile; i,z,q,j,l:Integer; s1:string; begin
if FileExists(Filename) then DeleteFile(Filename); ini := TIniFile.Create(Filename); i := 0; z := 0; for i := 0 to ListView1.GetCount-1 do begin q := 1; s1 := ''; INC(z); ini.WriteString('Section'+inttostr(i+1),'Section', ListView1.Items[i].Caption); ini.WriteString('Section'+inttostr(i+1),'Key1', ListView1.Items[i].SubItems.Strings[0]);
if ListView1.Items[i].SubItems.Strings[0] = someString1 then begin if (Array1[i] <> '') and (Array1[i] <> someString2) then ini.WriteString('Section'+inttostr(i+1),'Key2',Array1[i]) else ini.WriteString('Section'+inttostr(i+1),'Key2',SomeString2); ini.WriteString('Section'+inttostr(i+1),'Key3',Array2[i]); ini.WriteString('Section'+inttostr(i+1),'Key4',Array3[i]); end;
if ListView1.Items[i].SubItems.Strings[0] = someString3 then if (Array3[i]<>'') and (Array3[i]<>someString4) then begin for j := 1 to length(Array3[i]) do begin if j MOD 100 = 0 then begin INC(q); s1 := ''; ini.WriteString('Section'+inttostr(i+1),'Key5_'+inttostr(q),s1); end; if Array3[i][j] <> '' then begin ini.WriteString('Section'+inttostr(i+1),'Count',inttostr(q)); s1 := s1 + Array3[i][j]; ini.WriteString('Section'+inttostr(i+1),'Key5_'+inttostr(q),s1); end; end; if q = 1 then begin ini.WriteString('Section'+inttostr(i+1),'Key5_1',s1); ini.WriteString('Section'+inttostr(i+1),'Count','1'); end; end else ini.WriteString('Section'+inttostr(i+1),'Key5',someString4);
end; ini.WriteInteger('SectionCount','Count',z); ini.Free; end; |
|
|
jaenicke
      
Beiträge: 19335
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 24.05.10 14:39
Der größte Fehler, der auf Anhieb klar ist, ist, dass die Daten offenbar nur in der TListView liegen. Und der Zugriff auf die visuellen Komponenten ist nun einmal langsam. Die Daten gehören dort nur angezeigt, mehr nicht...
Wenn du die Daten im Hintergrund in einer geeigneten Datenstruktur hältst, dann ist der Zugriff auch entsprechend schneller. Ansonsten ist die größte Bremse wohl die Benutzung von INIs selbst. Dass das soo langsam ist, hätte ich trotzdem nicht gedacht.
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Mo 24.05.10 16:16
Ich wollte ja mal BigIni ausprobieren, aber unter Delphi 2010 bekomme ich das ganze nicht zum Laufen (es kommen Fehler beim Kompilieren von BigIni.pas)  Ob das was helfen würde?
Ich kann irgendwie nicht glauben, dass nur die Benutzung des ListViews soviel Zeit kosten soll (im Sekundenbereich) 
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Mo 24.05.10 16:29
Hallo,
wenn ich das richtig sehe schreibt der Code bei jedem der 100 Zeichen immer wieder das gleiche in die ini:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| for j := 1 to length(Array3[i]) do begin if j MOD 100 = 0 then begin INC(q); s1 := ''; ini.WriteString('Section'+inttostr(i+1),'Key5_'+inttostr(q),s1); end; if Array3[i][j] <> '' then begin ini.WriteString('Section'+inttostr(i+1),'Count',inttostr(q)); s1 := s1 + Array3[i][j]; ini.WriteString('Section'+inttostr(i+1),'Key5_'+inttostr(q),s1); end; end; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Mo 24.05.10 16:48
Nö, das macht er eigentlich nicht. Ist vielleicht etwas kryptisch geschrieben, aber tut seinen Zweck
Aber vielleicht gibt es eine bessere Variante, einen Text in 100-Zeichen-Abschnitte zu zerteilen? Es hat sich nämlich gezeigt, dass genau dieser Abschnitt Probleme macht (der MOD-Abschnitt). Irgendetwas ist da ziemlich langsam.
|
|
jaenicke
      
Beiträge: 19335
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 24.05.10 17:12
So, ich habe es einmal getestet. Der Flaschenhals ist wie ich auch hauptsächlich dachte die INI-Nutzung. Beim Lesen aus der ListView ist diese (anders als ein Memo!!) nicht langsamer (das hätte ich nicht gedacht).
Zum Vergleich: Die normale Speicherung in einem eigenen Format dauert unter 15 Millisekunden für 1000 Einträge, bei einer INI sind es ca. 50 Sekunden...
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Mo 24.05.10 17:21
Vielleicht hilft das die FastIni-Unit von Silas das ganze etwas zu beschleunigen.
lg elundril
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Mo 24.05.10 17:25
|
|
jaenicke
      
Beiträge: 19335
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 24.05.10 17:35
Ich habe es einmal mit TMemIniFile und TFastIniFile getestet. Die beiden sind nur etwa 7 bis 12 Mal langsamer als eine eigene Speicherung (100ms bis 150ms gegenüber 12-16ms). Die nehmen sich aber nicht viel, jedenfalls bei meinem Test waren die fast genauso schnell.
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Mo 24.05.10 18:10
Also kann ich praktisch auch das bereits in Delphi integrierte MemIni nehmen?
Edit: Ich habe es jetzt einfach mal mit TMemIniFile probiert und siehe da: Das Schreiben funktioniert wesentlich schneller.
Vielen Dank für eure Hilfe bis dahin!!!
Ist MemIniFile eigentlich auch beim Lesen schneller als IniFile?
|
|
jaenicke
      
Beiträge: 19335
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 24.05.10 18:33
Ich habe es nicht ausprobiert, aber ich denke ja, denn es basiert ja darauf, dass die Daten im Arbeitsspeicher gehalten werden.
Und wie gesagt: Mit einer eigenen Datenspeicherung hat man kleinere Datendateien, deutlich mehr Geschwindigkeit und einfacher ist es auch.
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Mo 24.05.10 22:50
Hallo,
LonghornUser hat folgendes geschrieben : | | Nö, das macht er eigentlich nicht. |
dann gib mal zusätzlich die geschriebenen Ini-Werte in einem Memo aus.
Es ist richtig, der Code liefert im Ergebnis das was du willst, der letzte Schreibvorgang schreibt den Eintrag den du möchtest. Zuvor wird aber 100-mal der Ini-Eintrag überschrieben. Und da zwei Einträge geschrieben werden sind es 200 Schreibvorgänge.
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Di 25.05.10 13:00
Du hattest doch recht. Der Code (der unter uns gesagt mehrere Jahre alt ist  ) war äußerst ineffizient.
Daher habe ich das ganze überarbeitet und dieser Code hier sollte mit deutlich weniger Schreibzugriffen auskommen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| for j := 0 to length(Array3[i]) div 100 do begin ini.WriteString('Section'+inttostr(i+1), 'Key5_'+inttostr(j+1), ''); ini.WriteString('Section'+inttostr(i+1), 'Key5_'+inttostr(j+1), Copy(Array3[i], j*100+1, 100)); ini.WriteString('Section'+inttostr(i+1), 'Count', inttostr(j+1)); end; |
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: Di 25.05.10 18:57
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
LonghornUser 
      
Beiträge: 796
|
Verfasst: Di 25.05.10 19:08
Ja, das war eine ziemliche Jugendsünde
Was genau sind denn Succ und Pred?
|
|
|