Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Tricks um Programm zu beschleunigen (https://www.delphipraxis.net/59187-tricks-um-programm-zu-beschleunigen.html)

opfer.der.genauigkeit 19. Dez 2005 10:08

Re: Tricks um Programm zu beschleunigen
 
Schlankerer Code ist schneller? Höchstens doch in Zusammenarbeit mit Bibliotheken. Je weniger ich drumherum habe und desto direkter ich arbeite, desto mehr Effizenz kann ich erzeugen.
Wie FriFra schon mit "Ballast" erwähnte.
Aber "schlanker Code == schneller Code" würde ich so nicht verallgemeinert sagen.
Schlüßelwörter wie virtual und inline sorgen für Schnelligkeit auf Kosten der Größe.

HERMES 19. Dez 2005 10:13

Re: Tricks um Programm zu beschleunigen
 
Was soll das mit Virtual zu tun haben? Virtual ist schneller als Dynamic, ober nicht schneller als eine statische Mathode, die nicht überschrieben werden kann, weil da nicht erst nechgesehen werden muss welche jetzt eigentlich genommen werden soll und wo die steht.

opfer.der.genauigkeit 19. Dez 2005 10:19

Re: Tricks um Programm zu beschleunigen
 
Auszug aus der Hilfe:
Zitat:

Virtuelle und dynamische Methoden sind von der Semantik her identisch. Sie unterscheiden sich nur bei der Implementierung der Aufrufverteilung zur Laufzeit. Virtuelle Methoden werden auf Geschwindigkeit, dynamische Methoden auf Code-Größe optimiert.
Aus diesem Grund hatte ich das erwähnt. Vielleicht hätte ich static als Beispiel verwenden sollen, das wäre sicherlich eher angenommen worden.

HERMES 19. Dez 2005 10:28

Re: Tricks um Programm zu beschleunigen
 
Das hab ich ja nicht bestritten, allerdings, geht es hier nur darum, dass der aufruf einer statischen methode schneller ist der einer dymischen/ virtuellen. Bei der angesprochenen optimierung auf geschwindigkeit und größe, geht es nur um den AUFRUF nicht um die AUSFÜHRUNG. Die eigentliche ausfürhrung der Methoden ist gleich, denn der Inhalt der Methoden wird immer mit O3 ( ausser wenn in den Projektoptionen was anderes eingestellt ist) optimiert. O3 bedeutet maximale optimierung wobei auch eine vergrößerung des Codes zugunsten der Ausführungszeit in kauf genommen wird.

alzaimar 19. Dez 2005 10:54

Re: Tricks um Programm zu beschleunigen
 
Ihr redet hier von Optimierungen im Nachkommabereich.

Wenn es aber darum geht, ein Programm erstmal von 'lahm' (mit 'h') auf schnell (mit 'l' :zwinker: ) zu drehen, sollte man sich nicht darum kümmern, sondern um solche Sachen wie:
1. Algorithmen und deren Komplexität. Damit meine ich *nicht*, wie kompliziert ein Algorithmus ist, sondern sein Laufzeitverhalten ('big oh'). Der alte Satz stimmt immer noch, das ein Quicksort auf einem 8MHZ 8086 immer schneller ablaufen wird, als ein Bubblesort auf einer Cray (bildlich gesprochen). Gilt natürlich erst ab einer bestimmten Arraygröße. Das liegt daran, das Bubblesort vom Laufzeitverhalten bei doppelter Arraygröße 4x langsamer ist, ein Quicksort aber nur 1,3x langsamer.

Faustregel: Es gibt keine optimalen Algorithmen, deren Laufzeitverhalten > n^3 ist (Also 3 ineinander verschachtelte Schleifen). Matrizenmultiplikation ist ein Extrembeispiel, wo jedoch durch Tricks die Komplexität inzwischen bei ca. O(n^2.3) liegt.

2.Vermeidung von dynamischen Stringvariablen
Die Konkatenation von Strings, also a:= a+'Foo' ist ein Pferdefuss. Vergleiche mal:
Delphi-Quellcode:
Function LameConcat (aStrings : TStrings) : String;
Var
  i : Integer;

Begin
  Result :='';
  For i:=0 To aStrings.Count - 1 do
     Result := Result + aStrings[i];
End;
mit
Delphi-Quellcode:
Function FasterConcat (aStrings : TStrings) : String;
Var
  p, i, n : Integer;

Begin
  n := 0;
  For i:=0 To aStrings.Count - 1 do
    inc (n, Length (aStrings[i]);
  SetLength (Result, l);
  p := 1;
  For i:=0 To aStrings.Count - 1 do begin
    n := Length (aStrings[i]);
    System.Move (@aStrings[i][1], @Result[p], n);
    inc (p,n);
  End;
End;
Beide Funktionen sollen die Zeile einer Stringliste hintereinander packen und zurückliefern.
Code #1 hängt einfach die i.te Zeile an einen anfangs leeren String. Dabei wird bei jedem Anhängen neuer Speicher reserviert, der alte Teilstring reinkopiert und die Zeile hintendran gebeppt. Das verbraucht natürlich Zeit, nämlich umso mehr, je länger der String ist.
Code#2 rechnet erstmal aus, wieviel Platz von Nöten ist, reserviert den Platz einmalig und kopiert einfach die Zeilen hintereinander und ist damit, je nach Anzahl der Zeilen. ca. 20-100x schneller.

3. Vermeiden von unnötigen Visualisierungen.
Sobald man mit Listen/Datenmengen arbeitet, die in einem Formular visualisiert werden (Memo, Listbox, DBGrid etc.) sollte man die BeginUpdate/EndUpdate (bzw. DisableControls/EnableControls) Methoden verwenden.

4. Gute DBMS
Das ist ein Thema für sich.

5..999: Sachen, die ich vergessen habe

1000. Ab hier sind wir im einstelligen Prozentbereich und können dynamische und virtuelle Methoden analyieren.

Unterm Strich bleibt zu sagen, das mit dieser Thematik Bücherwände füllen könnte.

dizzy 19. Dez 2005 10:56

Re: Tricks um Programm zu beschleunigen
 
Zum Problem der Optimierung an und für sich:
Zunächst steht, wie oben bereits erwähnt, eine Analyse des Programmes an, durch die kritische Teile im Code ausfindig gemacht werden. Ein Profiler stellt hier die pragmatischte Variante dar, ein anderer Weg ist es für jede Zeile abzuschätzen wie viele CPU-Cycles für diese benötigt werden. (Das hinkt jedoch auch etwas, da eben andere Hardware ausgenommen wird, wie in deinem Fall z.B. das Netzwerk! Somit ist das eher was für arithmetische Algos.) Alles weitere ist nun absolut fallabhängig.

Ein klassischer Optimierungsfall ist z.B. die 2D Cosinunstransformation (die u.a. bei jpeg und mp3 zum Einsatz kommt). Ein rein von der mathem. Formel abgeleiteter Algo besitzt eine 3-fach Schleife in der mehrfach trigonometrische Operationen und andere Rechungen durchgeführt werden. Dies ist extrem lahm 8). Da man aber weiss, dass die 2D-Transformation auch berechnet werden kann, indem man erst alle Zeilen, und dann alle Spalten berechnet, kann man rein algorithmisch optimieren, nämlich zu 2 2-fach Schleifen. Damit spart man schon eine ganze Menge, da viele Teilrechnungen nicht mehr so oft redundant durchgeführt werden müssen. Nach und nach mit steigender Kenntnis des Algos, hat man soweit optimieren können, dass nunmehr eine Hand voll Multiplikationen und Additionen kombiniert mit wenigen vorberechneten Konstanten ausreichen. Verglichen mit dem ersten Algo hat man immens Gewinn gemacht.
Die Moral? Tja, das ist eben ganz speziell nur für diesen Fall zugeschnitten, da das Verfahren so ist wie es ist. Optimierung heisst in den meisten Fällen gleichzeitig auch Spezialisierung, und somit Konzentration auf genau diesen einen Fall. Und genau DAS macht es eigentlich unmöglich generelle Aussagen zur Optimierung zu machen.

Weniger Code = schneller?:
Eine Schleife z.B. ist immer minimal langsamer als alle Durchläufe aufgedröselt hintereinander weg geschrieben, da die Verwaltung der Schleife hinzu kommt, und meist auch Sprünge im Code (was aktuelle Jump Predictions der CPU jedoch mittlerweile ganz gut im Griff haben, so dass das Caching/Pipelining nicht mehr so leidet wie es mal war). Das ist idR nicht viel, aber es wiederlegt o.g. Aussage. Die Dynamik und Wartbarkeit leidet da allerdings doch etwas zu sehr, als dass sich das im entferntesten lohnen könnte ;)

Was deinen speziellen Fall hier angeht, da bist du tatsächlich an die Grenzen der Hardware/API gebunden. Irgendwo ist halt Schluss.


Gruss,
Fabian

Der_Unwissende 19. Dez 2005 11:09

Re: Tricks um Programm zu beschleunigen
 
Zitat:

Zitat von dizzy
Die Moral? Tja, das ist eben ganz speziell nur für diesen Fall zugeschnitten, da das Verfahren so ist wie es ist. Optimierung heisst in den meisten Fällen gleichzeitig auch Spezialisierung, und somit Konzentration auf genau diesen einen Fall. Und genau DAS macht es eigentlich unmöglich generelle Aussagen zur Optimierung zu machen.

Geb ich dir Recht, aber eigentlich ist die Herangehensweise auch (fast) immer die gleiche. Man nennt es Dynamische Programmierung, man berechnet Zwischenergebnisse vor (kostengünstig) und mit diesen weiter und landet dann bei einer geringeren Laufzeit als bei einem Greedy-Algorithmus (also irgendeiner offensichtlichen Lösung). Das ist (wenn ich mich richtig erinnere) auch der Trick für Matrizenmultiplikation. Damit kommen wir häufig auch auf mehr Code, da gibt es doch diese effizientere Multiplikation zweier Komplexer Zahlen, da benötigt man deutlich mehr Additionen, aber weniger Multiplikationen, hat mehr Codezeilen und spart trotzdem Zeit (schon allein weil eine Multiplikation "teurer" ist als ein Addition).

Wie hier schon zu genüge gesagt wurde, es geht nicht wirklich ohne Profiler. Aber am wichtigsten, an den wenigsten Stellen bringt Optimierung etwas. Natürlich kannst du dich totoptimieren an fast jedem Code und da wirklich ordentlich was rausholen und der Benutzer würde es nicht in Ansätzen merken. Das liegt dann einfach daran, dass die 80/20 Regel greift, 80% der Dinge die mit der Software gemacht werden, entsprechen gerade einmal 20% der Funktionen. Wenn du etwas optimieren möchtest, sollte es also tunlichst in diesen 20% liegen, da sonst die Kosten für eine Optimierung sämtlichen Nutzen übersteigen dürften (auch hier gilt eher 80/20, nicht immer).

Gruß Der Unwissende

Jasocul 19. Dez 2005 11:24

Re: Tricks um Programm zu beschleunigen
 
Es gibt bei mir zwei Dinge, die ich immer wieder bei der Programmierung bedenke:
1. Fehlerbehandlung selbst übernehmen. Try..Except ist eine Todesfalle schnellen Code.
2. Keine Visualisierung von automatischen Abläufen. Zumindest auf das nötigste beschränken.

Ein paar andere Dinge gibt es auch noch, die man beachten sollte, werden aber nicht so regelmäßig notwendig sein:
- Möglichst selten Daten nachladen (DB- und Dateizugriffe sind langsamer als Speicherzugriffe)
- Nur da optimieren, wo es sind macht: Im Dialog mit dem Anwender ist das nahezu sinnlos. Der Anwender ist bestimmt langsamer.
- In langsamen Routinen mehr Werte zwischenspeichern. Dann müssen diese nicht immer wieder neu berechnet werden.
- Vor Allem Schleifen prüfen, ob dort immer wieder das selbe berechnet wird. Passiert oft bei Stringvergleichen mit der Pos-Funktion, um nur ein Beispiel zu nennen.

Alles andere sind Spezial-Dinge, die im Einzelnen untersucht werden müssen.

mumu 19. Dez 2005 12:33

Re: Tricks um Programm zu beschleunigen
 
Zitat:

Fehlerbehandlung selbst übernehmen. Try..Except ist eine Todesfalle schnellen Code.
soweit ich aber weiß ist das jedoch nur beim debug zeitpunkt so. in der runtime umgebung sollte ein try except nicht wirklich sehr performance schädigend sein, oder? ich mein der stack, lokale Variablen, und weitere informationen werden bei einer exception bei debuggen gesammelt und deshalb ist hier das programm langsamer, oder?

bigg 19. Dez 2005 12:35

Re: Tricks um Programm zu beschleunigen
 
Zitat:

Zitat von XeRo
ich geb mal mein konkretes beispiel:

unit stammt von Florian Bernd
Delphi-Quellcode:
unit ActiveConnections;

interface

uses windows, classes, Unit1;

procedure ScanNetworkResources(ResourceType, DisplayType: DWord; List: TStrings);

implementation

type
  PNetResourceArray = ^TNetResourceArray;
  TNetResourceArray = array[0..100] of TNetResource;



function CreateNetResourceList(ResourceType: DWord;
                              NetResource: PNetResource;
                              out Entries: DWord;
                              out List: PNetResourceArray): Boolean;
var
  EnumHandle: THandle;
  BufSize: DWord;
  Res: DWord;
begin
  Result := False;
//  List := Nil;
  Entries := 0;
  if WNetOpenEnum(RESOURCE_GLOBALNET,
                  ResourceType,
                  0,
                  NetResource,
                  EnumHandle) = NO_ERROR then begin
    try
      BufSize := $4000; // 16 kByte
      GetMem(List, BufSize);
      try
        repeat
          Entries := DWord(-1);
          FillChar(List^, BufSize, 0);
          Res := WNetEnumResource(EnumHandle, Entries, List, BufSize);
       {   if Res = ERROR_MORE_DATA then
          begin
            ReAllocMem(List, BufSize);
          end;                      }
        until Res <> ERROR_MORE_DATA;

        Result := Res = NO_ERROR;
        if not Result then
        begin
          FreeMem(List);
          List := Nil;
          Entries := 0;
        end;
      except
        FreeMem(List);
        raise;
      end;
    finally
      WNetCloseEnum(EnumHandle);
    end;
  end;
end;

procedure ScanNetworkResources(ResourceType, DisplayType: DWord; List: TStrings);

procedure ScanLevel(NetResource: PNetResource);
var
  Entries: DWord;
  NetResourceList: PNetResourceArray;
  i: Integer;
begin
  if CreateNetResourceList(ResourceType, NetResource, Entries, NetResourceList) then try
    for i := 0 to Integer(Entries) - 1 do
    begin

      if (DisplayType = RESOURCEDISPLAYTYPE_GENERIC) or
        (NetResourceList[i].dwDisplayType = DisplayType) then begin
        If (Copy(NetResourceList[i].lpRemoteName,1,2)='\\') then
        Form1.ListBox1.Items.AddObject(NetResourceList[i].lpRemoteName, Pointer(NetResourceList[i].dwDisplayType));
      end;
      if (NetResourceList[i].dwUsage and RESOURCEUSAGE_CONTAINER) <> 0 then
        ScanLevel(@NetResourceList[i]);
    end;
  finally
    FreeMem(NetResourceList);
  end;
end;

begin
  ScanLevel(Nil);
end;

end.
die ganzen schleifen (denke ich) machen die unit so lam....könnt ihr mir zeigen wie ihr das beschleunigen würdet.

Was macht der Code denn überhaupt?


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:49 Uhr.
Seite 3 von 4     123 4      

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