Autor Beitrag
LonghornUser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 23.05.10 18:21 
Da machst du wohl etwas falsch, aber ohne Code kann da niemand etwas dazu sagen. :nixweiss:

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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8553
Erhaltene Danke: 479

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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. :D

_________________
We are, we were and will not be.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: 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. :D


Dann hätteste mal einwandfreie Diskette nehmen sollen und keine mit zig Lesefehlern. :mrgreen:

_________________
Gruß
Hansa
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8553
Erhaltene Danke: 479

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: 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:
ausblenden volle Höhe Delphi-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

// Löschen einer vorhandenen INI-Datei
    if FileExists(Filename) then
      DeleteFile(Filename);
// Daten werden in Konfig.ini geschrieben (Andwendungsdaten des aktiven Users)
    ini := TIniFile.Create(Filename);
    i := 0;
    z := 0;
    for i := 0 to ListView1.GetCount-1 do begin // In einem ListView sind die Daten organisiert
      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]);

// Der folgende Teil kommt für bestimmte Elemente abgewandelt noch 6-mal

      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;

// (bis hier)

// Dieser Part teilt einen großen Text, der in einem Array steht in 100-Zeichen-Teile auf und schreibt ihn in die INI
      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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: 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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: Mo 24.05.10 17:25 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
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...


Danke für deine Mühe!! Das hätte ich nicht gedacht. Dabei speichere ich ja auch nicht wirklich viel. Sind wie gesagt vielleicht 1KB.

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
Vielleicht hilft das die FastIni-Unit von Silas das ganze etwas zu beschleunigen.

lg elundril


Das schaue ich mir nachher mal an, danke für den Tipp!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Mo 24.05.10 22:50 
Hallo,
user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: 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:
ausblenden 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+1100));
            ini.WriteString('Section'+inttostr(i+1), 'Count', inttostr(j+1));
          end;
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Di 25.05.10 18:57 
user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
Du hattest doch recht. Der Code (der unter uns gesagt mehrere Jahre alt ist ;)) war äußerst ineffizient.
ja, die Jugendsünden :wink:
Da sind immer noch überflüssige Schreibzugriffe und Berechnungen enthalten, teste mal den Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var Sec: String;
    Count: Integer;
begin
  Sec := 'Section' + IntToStr(Succ(i));
  Count := Succ(Length(Array3[i]) div 100));
  for j := 1 to Count do
    ini.WriteString(Sec, 'Key5_' + IntToStr(j), Copy(Array3[i], Pred(j)*100100));
  ini.WriteString(Sec, 'Count', IntToStr(Count);

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
LonghornUser Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 796



BeitragVerfasst: Di 25.05.10 19:08 
Ja, das war eine ziemliche Jugendsünde ;)

Was genau sind denn Succ und Pred?