Autor Beitrag
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: 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).

ausblenden 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
            //sleep(1);
            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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 380


D3 Prof, D4 Prof
BeitragVerfasst: 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 ):

ausblenden Delphi-Quelltext
1:
2:
3:
4:
t:=Gettickcount+o; // momentaner Wert von Gettickcount + offset für wartezeit
Repeat
  .....
until  t<=Gettickcount; // gettickcount erhöht sich selbst, daher der Vergleich mit Vorbesetzung von t


Ü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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 09.11.07 10:33 
user profile iconTilman 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. :nixweiss:

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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Fr 09.11.07 17:57 
Okay danke erstmal... mit QueryPerformanceCounter funzt es.
ausblenden 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[1or rdown[2or rdown[3or rdown[4]) then sleep(100);
            if rdown[1then mouse_event(MOUSEEVENTF_MOVE,cardinal(-5),0,0,0);
            if rdown[2then mouse_event(MOUSEEVENTF_MOVE,0,cardinal(-5),0,0);
            if rdown[3then mouse_event(MOUSEEVENTF_MOVE,5,0,0,0);
            if rdown[4then 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 :zustimm:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 148

XP
D6, D2007 prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

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

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Fr 09.11.07 20:09 
user profile iconTilman 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Fr 09.11.07 20:16 
user profile iconalzaimar hat folgendes geschrieben:
user profile iconTilman 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)