Autor |
Beitrag |
Tilman
      
Beiträge: 1405
Erhaltene Danke: 51
Win 7, Android
Turbo Delphi, Eclipse
|
Verfasst: Do 08.11.07 20:59
Hallo,
Ich brauche für eine Anwendung eine Schleife die auf verschiedenene Rechner möglichst gleichschnell läuft. Die Schleife läuft in einem eigenen Thread. Das Problem ist dass die Schleife aber auch möglichst schnell laufen soll (am besten sollte der Benutzer selber wählen können wie schnell die Schleife ist).
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:
| procedure TMyOwnThread.Execute; var t: integer; o: Integer; begin try t := gettickcount; o := 0; repeat inc(o); if (t+0 < gettickcount) then begin t := gettickcount; form1.Label2.Caption := IntToStr(o); o := 0; if links then mouse_event(MOUSEEVENTF_MOVE,4294967290,0,0,0); if oben then mouse_event(MOUSEEVENTF_MOVE,0,4294967290,0,0); end;
until application.Terminated; except end; end; |
Das Problem ist: obwohl mit (t+0) auf den geringstmöglichen Wert gestellt ist, läuft die Schleife wesentlich langsamer als ohne "Bremse". Mit o gemessen erhalte ich ca. 20.000 "übersprungene" Durchläufe. Gibt es ein feineres Verfahren als getTickCount?
Die Prozessorauslastung geht dabei auf 100%, was z.B, auf meinem Laptop die Auswirkung hat dass der Lüfter anspringt. Um dies zu Vermeiden benutze ich in älteren Versionen meines Programms die Zeile sleep(1), mit der die Auslastung deutlich verringert wird. Gibt es dazu eine Alternative?
_________________ Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
|
|
oldmax
      
Beiträge: 380
D3 Prof, D4 Prof
|
Verfasst: Fr 09.11.07 07:57
Hi
Mir scheint, dein Ansatz ist falsch. Was machst du eigentlich mit der Variable o ? Du setzt diese auf 0, ok. Du incrementierst o in der Schleife und schreibst das in Label2. Dann setzt du wieder auf 0.
Soweit, so gut, aber wofür ?
Da ich mit GetTickCount bisher nicht gearbeitet habe, kann ich nur vermuten, das ich eine Zahl zurückbekomme.
Wenn ich nun Schleifendurchläufe mit gettickcount steuern möchte, so sollte die Schleife so aufgebaut sein ( ungeprüft ):
Delphi-Quelltext 1: 2: 3: 4:
| t:=Gettickcount+o; Repeat ..... until t<=Gettickcount; |
Übrigends, es ist besser du benutzt etwas aussagekräftigere Variablennamen. "o" , das dürfte dir jetzt auch klar sein, ist sehr leicht mit 0 verwechselt und da der Compiler das völlig ok findet, ist die Überraschung erst zur Laufzeit festzustellen. Dann such mal in einem Programm mit teilweise komplizierten Zeilenstrukturen, warum deine Rechnung nicht stimmt....
Gruß oldmax
//Edit: Sorry, verfgiß den Text, hab jetzt erst dein Problem erkannt....
_________________ Zier dich nich so, ich krieg dich schon....
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Fr 09.11.07 09:38
Wieso benutzt Du nicht die Suchfunktion. Das GetTickCount nur auf xx ms genau geht, wäre Dir dann irgendwie aufgefallen. Alternativ gibt es noch soetwas wie 'F1'. Aber ich sehe gerade, das Du noch mit D3 und D7 arbeitest, und da ist die Hilfe ungenau...
Google ist auch ganz nett. Da findest Du dann an 2. oder 3.Stelle das hier: msdn2.microsoft.com/...ibrary/ms724408.aspx
_________________ Na denn, dann. Bis dann, denn.
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 09.11.07 10:33
Tilman hat folgendes geschrieben: | Das Problem ist dass die Schleife aber auch möglichst schnell laufen soll. |
Das widerspricht deinem Quelltext... Du benutzt try..except als Bremse, aber die Schleife soll möglichst schnell sein.
Dadurch, dass du auf den Label etwas ausgibst, bremst du im if nochmal. Visuelle Komponenten solltest du in zeitkritischen Prozessen am besten gar nicht ansprechen, weil dies stark bremst.
Zudem ist es sowieso ein Fehler, dass du aus einem Thread heraus ohne Synchronisierung eine Komponente der VCL ansprichst, denn diese sind nicht threadsicher. Das darf man nie machen.
Jedenfalls gibt es QueryPerformanceCounter, was sehr viel genauer als GetTickCount ist. Da findest du für Delphi auch leicht Beispiele.
|
|
Tilman 
      
Beiträge: 1405
Erhaltene Danke: 51
Win 7, Android
Turbo Delphi, Eclipse
|
Verfasst: Fr 09.11.07 17:57
Okay danke erstmal... mit QueryPerformanceCounter funzt es.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| procedure TMyOwnThread.Execute; var t,n: int64; begin try QueryPerformanceCounter(t); repeat QueryPerformanceCounter(n); if (t +10000 < n) then begin QueryPerformanceCounter(t); if not (rdown[1] or rdown[2] or rdown[3] or rdown[4]) then sleep(100); if rdown[1] then mouse_event(MOUSEEVENTF_MOVE,cardinal(-5),0,0,0); if rdown[2] then mouse_event(MOUSEEVENTF_MOVE,0,cardinal(-5),0,0); if rdown[3] then mouse_event(MOUSEEVENTF_MOVE,5,0,0,0); if rdown[4] then mouse_event(MOUSEEVENTF_MOVE,0,5,0,0); end;
until application.Terminated; except end; end; |
Wie ihr sehen könnt hab ich auch für sleep ne lösung gefunden... gesleept wird jetzt nur noch wenn die Schleife sich im "Ruhezustand" befindet, also wenn sie eigentlich nicht benötigt wird.
@oldmax: was o angeht hab ich doch alles im ersten Post beschrieben... es handelte sich um eine Debugging-Konstruktion zum testen der Geschwindigkeit, sprich ich wollte wissen ob die Funktion so lahm ist wegen meinem Code oder weil getTickCount so ungenau ist. Ergebnis: ca. 25.000 ausgelassene Schleifendurchläufe... wie gesagt
@alzaimar: dein Post hat mir leider nicht weitergeholfen.
@jaenicke: Danke für den Hinweis auf QueryPerformanceCounter, die funktion kannte ich wirklich noch nicht und sie ist hier die Lösung
Allerdinsg, nur zu deiner Information: try..except dient dazu eventuell auftretende Fehler abzufangen. Als "Bremse" wurde hingegen die Systemzeit bzw. der sleep-Befehl verwandt.
_________________ Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
|
|
TProgger
      
Beiträge: 148
XP
D6, D2007 prof
|
Verfasst: Fr 09.11.07 18:04
Zur Erläterung: try .. except veranlasst den Compiler, an dieser Stelle zusätzlichen Code in die EXE zu bauen, dessen Abarbeitung dann auch deutlich langsamer ist. Das war wohl mit Bremse gemeint.
_________________ Wir haben für jede Lösung das richtige Problem
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 09.11.07 19:06
Ja, das mit der Bremse war ironisch gemeint  . try..except verlangsamt schon deutlich, und deshalb sollte man schon so wenig wie möglich Code da hineinpacken. Und wo sollte denn da ein Fehler auftreten? Der einzige Fehler, der mir so einfällt, wäre als du den Zugriff auf das Label noch drinne hattest, da kann sowas mal passieren.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Fr 09.11.07 20:09
Tilman hat folgendes geschrieben: |
@alzaimar: dein Post hat mir leider nicht weitergeholfen. |
Kein Wunder, Du hast ihn auch nicht verstanden.
_________________ Na denn, dann. Bis dann, denn.
|
|
Tilman 
      
Beiträge: 1405
Erhaltene Danke: 51
Win 7, Android
Turbo Delphi, Eclipse
|
Verfasst: Fr 09.11.07 20:16
alzaimar hat folgendes geschrieben: | Tilman hat folgendes geschrieben: |
@alzaimar: dein Post hat mir leider nicht weitergeholfen. |
Kein Wunder, Du hast ihn auch nicht verstanden. |
Da magst du recht haben. Ich habs mir nochmal durchgelesen, denke du wolltest mir den Wink geben mal nach multimedia timer und high-resolution timer zu fahnden, muss aber sagen das mein Englisch nich sooo pralle ist, daher hab ich das gelassen. Aber es funzt ja jetzt auch so.
_________________ Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
|
|
|