Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Geschwindigkeit von Delphi 2007 scheinbar enttäuschend... (https://www.delphipraxis.net/143336-geschwindigkeit-von-delphi-2007-scheinbar-enttaeuschend.html)

holliesoft 13. Nov 2009 15:50


Geschwindigkeit von Delphi 2007 scheinbar enttäuschend...
 
Hallo allerseits,

ich habe - da ich krank geschrieben bin - heute aus Langweile das "Sieb des Eratosthenes" zunächst mit Lazarus, dann mit c# (Visual Studio 2008) und zuletzt mit Delphi 2007 umgesetzt.

In allen 3 Varianten verwende ich denselben Algorithmus, nur bei den Laufzeiten muss Delphi 2007 eine Niederlage einstecken:

Das ermitteln aller Primzahlen von 1 bis 100000 dauert bei der Lazarus-Anwendung 156 ms, bei der c#-Variante 63 ms, und bei Delphi 2007 skandalöse 8019 ms (!).

Kann mir das einer plausibel erklären, weshalb Lazarus so extrem performanter ist als Delphi?

Schön ist das Ergebnis von der c#-Umsetzung, das zeigt doch mal, das .net nicht langsamer ist als nativer Code...

Hier die Quellen:

1. Delphi und Lazarus:
======================
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
Var
  Zahlen: Array of Boolean;
  Beginn, Dauer, i, j: Integer;
  PrimZahlen: TStringList;
begin
  Primzahlen := TStringList.Create;
  ProgressBar1.Max := SpinEdit1.Value;
  Beginn := GetTickCount;
  SetLength(Zahlen, SpinEdit1.Value);
  i := 2;
  while (i*i) < SpinEdit1.Value do
  begin
    j := i * i;
    repeat
      Zahlen[j-1] := True;
      inc(j, i);
    until j > SpinEdit1.Value;
    ProgressBar1.Position := i * i;
    Application.ProcessMessages;
    inc(i);
  end;
  for i := 0 to SpinEdit1.Value -1 do
    if not Zahlen[i] then
      PrimZahlen.Add(IntToStr(i+1));
  Memo1.Lines.Assign(PrimZahlen);
  Dauer := GetTickCount - Beginn;
  Label2.Caption := IntToStr(Dauer);
  FreeAndNil(PrimZahlen);
end;
2. C#
=====
Code:
private void buttonSieb_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
            StringBuilder primZahlen = new StringBuilder();
            progressBar1.Value = 0;
            progressBar1.Maximum = (int)numericUpDown1.Value;
            int beginn = System.Environment.TickCount;
            bool[] zahlen = new bool[(int)numericUpDown1.Value];
            for (int i = 0; i < (int)numericUpDown1.Value - 1; i++)
            {
                zahlen[i] = false;
            }
            for (int i = 2; (i * i) < numericUpDown1.Value; i++)
            {
                for (int j = i * i; j < numericUpDown1.Value; j = j + i)
                {
                    zahlen[j - 1] = true;
                }
                progressBar1.Value = i * i;
                Application.DoEvents();
            }
            for (int i = 1; i < (int)numericUpDown1.Value; i++)
            {
                if (!zahlen[i - 1])
                    primZahlen.Append(i.ToString() + System.Environment.NewLine);
            }
            int dauer = System.Environment.TickCount - beginn;
            labelDauer.Text = dauer.ToString();
            textBox1.Text = primZahlen.ToString();
        }
Gruß,
Patrick

//Edit: Titel angepasst, da das Nadelör (SpinEdit1.Value) gefunden wurde :-)

mirage228 13. Nov 2009 15:58

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Miss die Zeit, bevor Du ins Memo zeichnen lässt (Lines.Assign). Das frisst ne Menge Zeit.
Delphi-Quellcode:
  Dauer := GetTickCount - Beginn;
  Memo1.Lines.Assign(PrimZahlen);
Zeit ist 450 ms bei mir dann.
Edit: Fragst man nicht bei jedem Durchlauf SpinEdit.Value (Jedes mal ein Funktionaufruf an den Getter!) ab, dann habe ich als Zeit 0 ms (also nicht mehr messbar, < 16 ms). Speicher den Wert am Anfang in eine Integer-Variable und dann verwende im Folgenden diese.
Edit 2: Getestet mit Delphi 2005 Professional, dürfte bei D2007 aber genauso ablaufen.

Viele Grüße

holliesoft 13. Nov 2009 16:09

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von mirage228
Miss die Zeit, bevor Du ins Memo zeichnen lässt (Lines.Assign). Das frisst ne Menge Zeit.
Delphi-Quellcode:
  Dauer := GetTickCount - Beginn;
  Memo1.Lines.Assign(PrimZahlen);
Zeit ist 450 ms bei mir dann.

Viele Grüße

Witzig nur, dass genau der selbe Code bei Lazarus viel schneller ausgeführt wird... :roll:

So, Zeitmessung trotzdem mal verschoben. Nun braucht Delphi "nur" noch 5647 ms. Immer noch viel.

Vielleicht sollte ich noch erwählen, unter welcher Systemkonfiguration ich arbeite:

Intel Core2 Duo CPU @ 2 Ghz
4 GB RAM
Windows 7 Ultimate 64bit

//Edit: Habe gerade Dein Edit gesehen. Vielleicht ist das Compilat das Delphi 2007 erzeugt langsamer als das von Delphi 2005 (hab hier in der DP neulich gelesen, dass da unter der Haube der Compiler von Delphi 7 werkelt?)

//Edit2: Hmm, tatsächlich, der Zugriff auf Spinedit1.Value kostet doch eine Menge Zeit. Nun schafft meine Delphi-Variante das in 16ms.
Trotzdem komisch, dass Lazarus hier soviel schneller ist (und c# auch).

Bernhard Geyer 13. Nov 2009 16:14

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von holliesoft
Kann mir das einer plausibel erklären, weshalb Lazarus so extrem performanter ist als Delphi?

Vermutlich GUI-Aktualisierungen die Lazarus unterschlägt

Zitat:

Zitat von holliesoft
Schön ist das Ergebnis von der c#-Umsetzung, das zeigt doch mal, das .net nicht langsamer ist als nativer Code...

Hätte ich dir (oder z.B. entsprechende Artikel der c't) auch sagen können. Zu 98% ist managed Code ähnlich schnell wie native Code. Es gibt einige Fälle das ist native Code um welten langsamer, aber lässt sich entsprechend umschiffen bzw. oft vermeiden.

mirage228 13. Nov 2009 16:19

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von holliesoft
//Edit2: Hmm, tatsächlich, der Zugriff auf Spinedit1.Value kostet doch eine Menge Zeit. Nun schafft meine Delphi-Variante das in 16ms.
Trotzdem komisch, dass Lazarus hier soviel schneller ist (und c# auch).

Also ich weiß nicht, wie sorgfältig das Delphi SpinEdit programmiert wurde bzw. ob da beim Getter noch etwas passiert.
Aber am Compiler selbst sollte es eigentlich nicht liegen... zumindest wüsste ich nicht, dass der Delphi 2007 irgendwo besonders suboptimal arbeitet...

Ich hab es auch mit Windows 7 getestet, jedoch 32-bit Professional (Prozessor ist Core i7 860 und RAM habe ich 4 GB).

Zitat:

(hab hier in der DP neulich gelesen, dass da unter der Haube der Compiler von Delphi 7 werkelt?)
Soweit ich weiß, ist das korrekt. Ist der Compiler von D7 Update 2.

Viele Grüße

toms 13. Nov 2009 16:21

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von mirage228
Edit: Fragst man nicht bei jedem Durchlauf SpinEdit.Value (Jedes mal ein Funktionaufruf an den Getter!) ab, dann habe ich als Zeit 0 ms (also nicht mehr messbar, < 16 ms). Speicher den Wert am Anfang in eine Integer-Variable und dann verwende im Folgenden diese.

Hast du das gemacht? Beschleunigt den Code um das Vielfache.

mirage228 13. Nov 2009 16:23

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von toms
Hast du das gemacht? Beschleunigt den Code um das Vielfache.

Japp, habe ich so probiert. Am Anfang SpinEdit1.Value in eine Integer Variable und alle folgenden Zugriffe auf SpinEdit1.Value durch diese Variable ersetzt - die gemessene Zeit stammt auch von diesem Versuch. :)

RWarnecke 13. Nov 2009 16:28

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von mirage228
Zitat:

Zitat von toms
Hast du das gemacht? Beschleunigt den Code um das Vielfache.

Japp, habe ich so probiert. Am Anfang SpinEdit1.Value in eine Integer Variable und alle folgenden Zugriffe auf SpinEdit1.Value durch diese Variable ersetzt - die gemessene Zeit stammt auch von diesem Versuch. :)

Ich habe es ebengerade mal mit Delphi 2007 ausprobiert. Wenn ich es so mache, wie im Zitat, zeigt mir mein Rechner 15 ms an. Wenn ich jetzt aber noch diese zwei Zeilen weglasse, dann zeigt er mir 0 an :
Delphi-Quellcode:
    PBar_1.Position := i * i;
    Application.ProcessMessages;

holliesoft 13. Nov 2009 16:31

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zitat:

Zitat von toms
Zitat:

Zitat von mirage228
Edit: Fragst man nicht bei jedem Durchlauf SpinEdit.Value (Jedes mal ein Funktionaufruf an den Getter!) ab, dann habe ich als Zeit 0 ms (also nicht mehr messbar, < 16 ms). Speicher den Wert am Anfang in eine Integer-Variable und dann verwende im Folgenden diese.

Hast du das gemacht? Beschleunigt den Code um das Vielfache.

Ja, das beschleunigt den Code tatsächlich um ein vielfaches.

Kein Wunder, wenn man sich die Implementierung des Getters ansieht:

Delphi-Quellcode:
function TSpinEdit.GetValue: LongInt;
begin
  try
    Result := StrToInt (Text);
  except
    Result := FMinValue;
  end;
end;
:shock:

Da wird jedesmal ein String zu einem Integer konvertiert...

RWarnecke 13. Nov 2009 16:34

Re: Geschwindigkeit von Delphi 2007 enttäuschend...
 
Zusätzlich sollte man sich noch diesen Beitrag anschauen. Dort wird auch an einer schnellen Variante rumprobiert für Primzahlen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:04 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz