Autor |
Beitrag |
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 12.04.08 15:23
Ich habe gerade ein kleines Delphi-Projekt nach Lazarus konvertiert. Die automatische Konvertierung hat nicht so ganz geklappt, daher hat das etwas länger gedauert. Aber jetzt läuft es so halbwegs.
Aber: Es läuft deutlich langsamer. Da steckt ein Faktor zwischen 2 und 3 drin. Hat jemand Erfahrung damit, kann das bestätigen oder weiß, ob man da was drehen kann? Gibt es da Compiler-Optionen, die das verursachen können, oder ist der Freepascal-Compiler einfach nur deutlich schlechter als der von Delphi?
_________________ We are, we were and will not be.
|
|
Jakob_Ullmann
      
Beiträge: 1747
Erhaltene Danke: 15
Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
|
Verfasst: Sa 12.04.08 16:20
1. Warum konvertierst du das Projekt denn nach Lazarus?
2. Ich denke, es wird schon seine Gründe haben, weshalb Delphi einen (hohen) Preis hat und Lazarus / FreePascal kostenlos ist.
|
|
Dunkel
      
Beiträge: 682
Mac OS X Snow Leopard
Xcode 3.1
|
Verfasst: Sa 12.04.08 17:01
Jakob_Ullmann hat folgendes geschrieben: | 1. Warum konvertierst du das Projekt denn nach Lazarus? |
Hast Du schon mal probiert eine Delphi-Echse unter Linux auszuführen? Oder unter Mac OS, oder auf einem PPC, oder, oder oder...
Jakob_Ullmann hat folgendes geschrieben: |
2. Ich denke, es wird schon seine Gründe haben, weshalb Delphi einen (hohen) Preis hat und Lazarus / FreePascal kostenlos ist. |
Nicht alles, was Open-Source oder Freeware ist, ist zwangsläufig schlechter als das kommerzielle Pendent.
BTT:
Keine Ahnung. Ich habe vor Urzeiten auch mal versucht, ein Projekt nach Lazarus/Free Pascal zu portieren. Hat ebenfalls nicht wirklich geklappt. Außerdem hat mir die IDE nicht wirklich gefallen; also habe ich es gelassen. 
_________________ Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Sa 12.04.08 19:31
In den Projektoptionen gab es meiner Meinung nach einen Schalter für Optimierungen. Also ich hab auch schon andere Meinungen gehört, dass freepascal wesentlich schneller ist, was ich mir durchaus eher vorstellen kann, da ich jedesmal nen Krampf bekomme, wenn ich das Delphi CPU Window öffne.
Vielleicht liegt das an deren LCL oder wie sie es nennen. Die programmieren ja immer noch die VCL nach. Könnte mir vorstellen, dass das noch nicht so läuft bzw die erstmal Masse statt Klasse schaffen wollen.
Vlt hilft es ja auch Teile davon mit dem gcc zu compilieren. Da soll ja auch ein pascal-part drin sein. Das ist aber nur eine Anregung ich jedenfalls weiß über das speziell gar nichts.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Sa 12.04.08 20:31
Hallo,
Eine Konsolenanwendung hat aber kein geändertes Verhalen ( ausser der gigantischen Grösse 1,6 Mb..6,3 Mb (Zeileneinformationen des debuggers an ))
www.delphi-forum.de/viewtopic.php?p=452360
Turbo Delphi 2007
8 bit lookup table (Reference): 1034435
16 bit lookup table: 530772
Horst_H: 541955 <--
Horst_H2: 220742
Reinhard Kern: 1692761
Freepascal 2.2.0
optimiert Register variable Optimierugen O2 und für AMD eingestellt, aller debugger Kram raus.
8 bit lookup table (Reference): 1381376
16 bit lookup table: 653001
Horst_H: 248621 <--
Horst_H2: 235787
Reinhard Kern: 1354820
Lazarus
optimiert für AMD nicht eingestellt
8 bit lookup table (Reference): 1094116
16 bit lookup table: 596681
Horst_H: 399932 <--
Horst_H2: 226541
Reinhard Kern: 1281640
Ohne die Registeroptimierung ist es aber viel langsamer
Gruß Horst
|
|
Gausi 
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 12.04.08 20:40
Hm. In der Tat. Jetzt ist es schneller. Aber ich glaube das liegt daran, dass einfach ganze Funktionen wegoptimiert wurden, als ich {$mode delphi} auf {$mode objfpc} gesetzt habe. Also alle Funktionen bis auf die, die ca. 600mal so lange wie unter Delphi braucht. Der Aufbau einer bestimmten Datenstruktur braucht auf einmal ein paar Zehnerpotenzen mehr Zeit.
Ich fürchte, da geht irgendwas komplett daneben. 
_________________ We are, we were and will not be.
|
|
Gausi 
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: So 13.04.08 13:28
Ok, das Problem mit dem mode ist geklärt - da wurden Strings als Pascal-Strings und nicht mehr als Ansi-Strings interpretiert.
Trotz aller Optimierungen in den Compiler-Einstellungen des Projekts bleibt das ganze langsamer. Besonders extrem ist das bei dieser Funktion (ist mal egal, was die macht. Die macht halt was  )
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: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87:
| TDawgRecord = record Init: Integer; Len: Array of Integer; Terminal: Array of Boolean; SuffixLink: Array of Integer; Target: Array of Array[Char] of Integer; end;
function BuildDawg(p: AnsiString): TDawgRecord; var m,i,NodeCount: Integer; last, u, v, w, r: Integer; c:Char; CopyC: Char; begin m := length(p); Setlength(result.Len, 2*m+2); Setlength(result.Terminal, 2*m+2); Setlength(result.SuffixLink, 2*m+2); Setlength(result.Target, 2*m+2); result.Init := 0; result.SuffixLink[0] := -1; for c := Low(Char) to High(Char) do result.Target[0,c] := -1; NodeCount := 0; last := 0;
for i := 1 to m do begin u := last; inc(NodeCount); v := NodeCount; result.Len[v] := result.Len[u] + 1; result.Terminal[v] := False; for c := Low(Char) to High(Char) do result.Target[v,c] := -1;
While (u > 0) and (result.Target[u,p[i]] = -1) do begin result.Target[u,p[i]] := v; u := result.SuffixLink[u]; end;
if result.Target[u,p[i]] = -1 then begin result.Target[0,p[i]] := v; result.SuffixLink[v] := 0; end else begin w := result.Target[u,p[i]]; if result.Len[u] + 1 = result.Len[w] then begin result.SuffixLink[v] := w; end else begin inc(NodeCount); r := NodeCount; result.Terminal[r] := False;
for CopyC := Low(Char) to High(Char) do result.Target[r,CopyC] := result.Target[w,CopyC]; result.SuffixLink[r] := result.SuffixLink[w];
result.Len[r] := result.Len[u] + 1; result.SuffixLink[w] := r; result.SuffixLink[v] := r;
while (u >= 0) and (result.Target[u,p[i]] = w) do begin result.Target[u,p[i]] := r; u := result.SuffixLink[u]; end; end; end; last := v; end; result.Terminal[last] := True; while last >= 0 do begin last := result.SuffixLink[last]; result.Terminal[last] := True; end; end; |
Folgendermaßen messe ich die Zeiten:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| QueryPerformanceFrequency(freq); QueryPerformanceCounter(s); BuildDawg('das ist ein test'); QueryPerformanceCounter(e); Showmessage(Format('%.8f', [(e-s)/freq])); |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| EpikTimer1.Clear; EpikTimer1.Start; s := EpikTimer1.Elapsed; BuildDawg('das ist ein test'); e := EpikTimer1.Elapsed; Showmessage(Format('%.8f', [e-s])); |
Zeit unter Delphi: ca. 0.00009 Sekunden. Unter Lazarus: ca. 0.25 Sekunden. Die Einheiten stimmen - wenn das sleep(1000) drin ist, gibts beides mal ca. eine Sekunde mehr.
Jetzt die Aufgabe an die Optimierungs-Freak: Woran kann das liegen? Ein Faktor 2-3 mag ich ja noch verschmerzen können, aber das hier ist dann doch etwas zu extrem...
_________________ We are, we were and will not be.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Mo 14.04.08 13:28
Hallo,
Test mit freepascal
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: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126:
| program testDawG;
uses windows,sysutils; type tCharInt = Array[Char] of Integer; TDawgRecord = record Init: Integer; Len: Array of Integer; Terminal: Array of Boolean; SuffixLink: Array of Integer; Target: Array of tCharInt; end; var e,s,freq: Int64;
function BuildDawg(const p: AnsiString): TDawgRecord; var e,s: Int64; m,i,NodeCount: Integer; last, u, v, w, r: Integer; c:Char; CopyC: Char; pCharInt : ^tCharInt; begin QueryPerformanceCounter(s); m := length(p); with result do begin Setlength(Len, 2*m+2); Setlength(Terminal, 2*m+2); Setlength(SuffixLink, 2*m+2); Setlength(Target, 2*m+2); Init := 0; SuffixLink[0] := -1; end; with result do begin pCharINt := @Target[0]; for c := Low(Char) to High(Char) do pCharInt^[c]:= -1;
NodeCount := 0; last := 0; for i := 1 to m do begin u := last; inc(NodeCount); v := NodeCount; Len[v] := Len[u] + 1; Terminal[v] := False; for c := Low(Char) to High(Char) do Target[v][c] := -1;
While (u > 0) and (Target[u,p[i]] = -1) do begin Target[u,p[i]] := v; u := SuffixLink[u]; end;
if Target[u,p[i]] = -1 then begin Target[0,p[i]] := v; SuffixLink[v] := 0; end else begin w := Target[u,p[i]]; if Len[u] + 1 = Len[w] then begin SuffixLink[v] := w; end else begin
inc(NodeCount); r := NodeCount; Terminal[r] := False; for CopyC := Low(Char) to High(Char) do Target[r,CopyC] := Target[w,CopyC]; SuffixLink[r] := SuffixLink[w]; Len[r] := len[u] + 1; SuffixLink[w] := r; SuffixLink[v] := r; while (u >= 0) and (Target[u,p[i]] = w) do begin Target[u,p[i]] := r; u := SuffixLink[u]; end;
end; end; last := v; end; Terminal[last] := True; while last >= 0 do begin last := SuffixLink[last]; Terminal[last] := True; end; writeln(nodecount); QueryPerformanceCounter(e); writeln(Format('Zeit innerhalb Funktion %.8f', [(e-s)/freq])); end;
end;
Begin QueryPerformanceFrequency(freq); QueryPerformanceCounter(s); BuildDawg('das ist ein test'); QueryPerformanceCounter(e); writeln(Format('%.8f', [(e-s)/freq])); end. |
Ergibt
22
Zeit innerhalb Funktion 0,00019109
0,22291409
Na da kann man nur EXTREM staunen...
Da hilft es, wenn man statt function eine procedure mit out Parameter nimmt funktioniert es in 0.0003 Sekunden
Delphi-Quelltext 1:
| procedure BuildDawg(const p: AnsiString,result:TDawgRecord); |
Gruß Horst
|
|
Gausi 
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 14.04.08 13:52
Hey, danke!
Hab die Funktion grade mal zu einer Prozedur umgebaut - das geht ja wirklich. Komischerweise dauert der Aufbau weiterhin solange, wenn ich die Funktion außerhalb eines Button-Clicks in einer anderen Unit benutze.
Hat jemand ne Idee, warum das als Funktion solange dauert, und als Prozedur mit var/out-Parameter so schnell ist?
_________________ We are, we were and will not be.
|
|
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: Mi 16.04.08 15:27
Bei VAR-\OUT-Parametern stellt die Aufrufende Funktion den Ergebnis-Puffer bereit, bei Funktionen wird dieser i.d.R. von der aufgerufenen Funktion alloziiert.
Wo liegt da der Unterschied: Wenn man Rekursive Funktionen hat, wird u.U. der globale Aufruf-Puffer einfach durchgeschleift und es wird nicht jedes Mal eine Kopie angelegt. Das spart Zeit UND der Compiler kann Optimierungen vornehmen, die so tun, als ob das Funktionsergebnis durch Manipulation innerhalb der Routine entstehen; brauch also nicht vorher irgendwas sichern, was er so einfach nur umverteilen kann, weil er weiß, wie die Verarbeitung abläuft ...
_________________ 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.
|
|
|