Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi JCLCounter - High Performance Counter (https://www.delphipraxis.net/93991-jclcounter-high-performance-counter.html)

creality 14. Jun 2007 13:03


JCLCounter - High Performance Counter
 
Hallo Forum,

ich verwende seit einiger zeit (6Monate) den JCLCounter aus der JCL Lib. Damit versuche ich genaue Zeitmessungen durchzuführen. Ging immer...bis gestern.

Seit gestern kann ich kein einziges Tool mehr starten ohne das die Exception ausgelöst wird: No high performance counters supported. Das würde bedeuten, das meine CPU sowas nicht unterstützt. Sinnlos...weil es über n halbes Jahr ging.

Weiß jemand woran das liegen könnte?

mfg, Marko

:coder:

Bernhard Geyer 14. Jun 2007 13:06

Re: JCLCounter - High Performance Counter
 
Zitat:

Zitat von creality
Seit gestern kann ich kein einziges Tool mehr starten ohne das die Exception ausgelöst wird: No high performance counters supported. Das würde bedeuten, das meine CPU sowas nicht unterstützt. Sinnlos...weil es über n halbes Jahr ging.

(Vor)Gestern sind doch Windows-Updates eingetrutelt ... :gruebel:

fLaSh11 14. Jun 2007 13:13

Re: JCLCounter - High Performance Counter
 
zu faul um ne zeitmessung selber zu amchen? :-D
Ist doch viel einfacher als irgendeine Kompo zu nutzen...

Delphi-Quellcode:
var
  freq,time1,time2: int64;
begin
  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(time1);

  //Do Something

  QueryPerformanceCounter(time2);

  ShowMessage(FloatToStr((time2-time1)/freq));
Man sollte die Zeit dann evtl runden, weil ja durch den Gleitkommawert das ergebnis verfälsch wird...

Robert Marquardt 14. Jun 2007 13:23

Re: JCLCounter - High Performance Counter
 
Nuetzt aber wahrscheinlich nichts, wenn QueryPerformanceFrequency 0 zurueckliefert.
Pruef mal nach was diese Funktion zurueckliefert. Wenn wirklich 0 zurueckkommt, dann hat das Windows Update einen Fehler eingeschleppt.

shmia 14. Jun 2007 13:32

Re: JCLCounter - High Performance Counter
 
Zitat:

Zitat von fLaSh11
zu faul um ne zeitmessung selber zu amchen? Ist doch viel einfacher als irgendeine Kompo zu nutzen...

Na ja, die Klassen aus der JCL haben schon ihre Berechtigung.
1. kann der Zeitoverhead für den Funktionsaufruf herausgerechnet werden
2. kann man mehr als nur eine Zeitmessung vornehmen. Ohne Kapselung in eine Klasse verliert man völlig den Überblick.
3. man kann die Zeit anhalten und die abgelaufene Zeit erst viel später anzeigen
4. dein code-Schnippsel prüft den Returnwert von QueryPerformanceFrequency nicht !!

Aber egal, auch TJclCounter benützt QueryPerformanceCounter/Frequency.
Delphi-Quellcode:
  // hier der entscheidende Ausschnitt aus dem Sourcecode
  if not QueryPerformanceFrequency(FFrequency) then
    // 'No high performance counters supported'
    raise EJclCounterError.CreateRes(@RsNoCounter);
Die MSDE sagt:
Zitat:

If the function fails, the return value is zero. To get extended error information, call GetLastError. For example, if the installed hardware does not support a high-resolution performance counter, the function fails.
Also, was sagt GetLastError ?

fLaSh11 14. Jun 2007 13:36

Re: JCLCounter - High Performance Counter
 
Zitat:

Zitat von shmia
2. kann man mehr als nur eine Zeitmessung vornehmen. Ohne Kapselung in eine Klasse verliert man völlig den Überblick.
3. man kann die Zeit anhalten und die abgelaufene Zeit erst viel später anzeigen
4. dein code-Schnippsel prüft den Returnwert von QueryPerformanceFrequency nicht !!

zu 2. und 3. kann man mit dem QueryPerformanceCounter genauso
zu 4. sollte nur ein kurzes unvollständiges Beispiel sein... natüröich kann ich noch dies und das prüfen und verbessern

shmia 14. Jun 2007 14:00

Re: JCLCounter - High Performance Counter
 
Zitat:

Zitat von fLaSh11
Zitat:

Zitat von shmia
2. kann man mehr als nur eine Zeitmessung vornehmen. Ohne Kapselung in eine Klasse verliert man völlig den Überblick.
3. man kann die Zeit anhalten und die abgelaufene Zeit erst viel später anzeigen
4. dein code-Schnippsel prüft den Returnwert von QueryPerformanceFrequency nicht !!

zu 2. und 3. kann man mit dem QueryPerformanceCounter genauso
zu 4. sollte nur ein kurzes unvollständiges Beispiel sein... natüröich kann ich noch dies und das prüfen und verbessern

Du hast den Vorteil von Objektorientierter Programmierung noch nicht vollständig verstanden.
Angenommen, du möchtest 10 verschiedene Zeiten messen. Ohne Kapselung in einer Klasse artet das doch in ein Gemetzel aus.
Delphi-Quellcode:
var
  freq,time1Start,time1Stop,time2Start,time2Stop, time3Start,time3Stop, ...... : int64;
Jetzt könnte man natürlich einen Record für die Start und Stopzeit bauen und ein Array nutzen:
Delphi-Quellcode:
type
   TTimeRec = record
     start, stop : Int64;
   end;
var
   freq : int64;
   zeitliste : array[1..10] of TTimeRec;
Der halbe Weg zur Klasse ist schon getan.
Delphi-Quellcode:
// die objekt-orientierte Variante
// kein "herumgerechne", kein Aufruf von Low-Level-Funktionen
// einfach, sauber & klar
var
   zeitliste : array[1..10] of TJclCounter;
begin
   zeitliste[1].Start;
   ...
   zeitlist[1].Stop;
   ...
   ShowMessageFmt('Zeit 1: %f',[zeitlist[1].ElapsedTime]);

Robert Marquardt 14. Jun 2007 14:02

Re: JCLCounter - High Performance Counter
 
Liste der Anhänge anzeigen (Anzahl: 1)
creality, kannst du mal ein simples Testprogramm ausprobieren und das Ergebnis hier posten?

creality 14. Jun 2007 14:08

Re: JCLCounter - High Performance Counter
 
So ich mal wieder:

QueryPerformanceFrequency liefert komischerweise nicht 0 zurück. Und zu faul bin ich auch nich ne Zeitmessung selber zu schreiben...vielleicht schreib ich ja gleich noch den TCPIP Stack neu wenn ich grad dabei bin :thumb:

Ich hab aber den JCP in vielen meiner Tools verwendet und müsste ihn wieder rausnehmen wenn ich Ursache nicht finde...

Delphi-Quellcode:

procedure TForm1.button_3Click(Sender: TObject);
var
  freq,time1,time2: int64;
  i,a : Integer;
begin
  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(time1);

  for I := 0 to 10000000 do
      Inc(a);

  QueryPerformanceCounter(time2);
  ShowMessage(FloatToStr((time2-time1)/freq));
end;

"Message = 0,0102"

creality 14. Jun 2007 14:11

Re: JCLCounter - High Performance Counter
 
@ Robert: Getestet

Freq := 0;
if not QueryPerformanceFrequency(Freq) then

wird übersprungen...also keine Ausgabe.

Robert Marquardt 14. Jun 2007 14:15

Re: JCLCounter - High Performance Counter
 
Das heisst mein Testprogramm gibt nichts aus.
Ruf doch mal den Installer der JCL auf und installiere einfach erneut. Vielleicht hilft das ja.
Der Installer hat auf jeden Fall kein Problem damit immer wieder aufgerufen zu werden.

creality 14. Jun 2007 14:18

Re: JCLCounter - High Performance Counter
 
@ Robert:

Jo dein Programm gibt nix aus. Die QueryPerformanceFrequency(Freq) ist nicht NULL und auch QueryPerformanceCounter(time) gibt ein INT64 zurück.

JCL hab ich bereits mehrfach installiert, deinstalliert und manuell installiert. immer das gleiche. furchtbar :stupid:

Bernhard Geyer 14. Jun 2007 14:27

Re: JCLCounter - High Performance Counter
 
Neueste Version? Evtl. haben ja ältere JCL-Versionen hier eine Wanze eingebaut?

Robert Marquardt 14. Jun 2007 14:33

Re: JCLCounter - High Performance Counter
 
Kopier doch mal JclCounter.pas, fuege es in dein Projekt ein, builde dein Programm und geh mit dem Debugger in den Konstruktor und schaue nach was dort passiert.

MagicAndre1981 14. Jun 2007 16:00

Re: JCLCounter - High Performance Counter
 
An dem Update für Windows liegt es nicht, bei mir geht alles. Mach dein Windows mal platt.

Bernhard Geyer 14. Jun 2007 16:26

Re: JCLCounter - High Performance Counter
 
Zitat:

Zitat von MagicAndre1981
An dem Update für Windows liegt es nicht, bei mir geht alles. Mach dein Windows mal platt.

Und was sagst du dem Kunden wenn sowas dort auftritt? Das gleiche?
Wir sollten die Ursache schon finden. Windows-Update ändern teilweise Systemeinstellung (wurde bei mir für die Internetzone "Trusted Sides" auch wieder gemacht und das auch nicht bei jedem Anwender.

creality 15. Jun 2007 06:58

Re: JCLCounter - High Performance Counter
 
Zusammenfassung bisheriger Ergebnisse

Funktioniert. Zeit kann gemessen werden ohne Probleme.

Delphi-Quellcode:
// Start
procedure HiPerfCounter.Start;
begin
     try
     QueryPerformanceFrequency(freq);
     QueryPerformanceCounter(time1);

     except
          on E:Exception do begin
             ShowMessage('HiPerfCounter reported an Error. QueryPerformanceCounter is not supported.');
          end;              
     end;
end;
Auszug aus dem JCL Counter:

Funktioniert nicht, obwohl hier genau das gleiche passiert: QueryPerformanceFrequency(FFrequency) liefert NULL zurück. WIESO?

Delphi-Quellcode:

constructor TJclCounter.Create(const Compensate: Boolean);
const
  Iterations: Integer = 10000;
var
  Count: Integer;
  TmpOverhead: Int64;
begin
  inherited Create;

  {$IFDEF MSWINDOWS}
  if not QueryPerformanceFrequency(FFrequency) then
    raise EJclCounterError.CreateRes(@RsNoCounter);
  {$ENDIF MSWINDOWS}
  {$IFDEF LINUX}
  FFrequency := 100000; // 1 sec = 10E6 microseconds, therefore we have to divide by 10E5
  {$ENDIF LINUX}

  FCounting := False;
  FOverhead := 0;
......................
..........

Robert Marquardt 15. Jun 2007 07:21

Re: JCLCounter - High Performance Counter
 
Mal den PEViewer der JCL uebersetzen und auf die EXEs ansetzen, aber eigentlich sollten genau die gleichen Funktionen eingelinkt werden.
Alternativ die JVCL und JCL deinstallieren und loeschen und dann wirkich alle Files aus dem Delphi-Verzeichnisbaum loeschen die mit Jcl oder Jv beginnen.
Danach die Festplatte absuchen ob nicht noch andere Files mit diesen Prefixen rumliegen. Moeglichst auch loeschen.
Nun JVL und JVCL von http://jvcl.sf.net/daily bzw. http://jcl.sf.net/daily besorgen und installieren.

creality 15. Jun 2007 07:41

Re: JCLCounter - High Performance Counter
 
@ Robert:

Ich habe soeben die JCLCounter.pas n bisschen editiert. Vor dem call: if not QueryPerformanceCounter(FStart) then
habe ich ne Testvariable eingefügt: Test : bool.

Und jetzt kommts: test := QueryPerformanceCounter(FStart); gibt NICHT null zurück und siehe da...der Counter geht wieder. Ich verstehs aber nicht. Nach dem entfernen der Var geths trotzdem. Ich vermute aber...das es nicht daran lag sondern an irgendwas anderem.

So kanns nicht weitergehen...ich werde mal deine Schrittliste abarbeiten und den ganzen Kram entfernen.


Delphi-Quellcode:
procedure TJclCounter.Start;
var
test : Boolean;
begin
  test := QueryPerformanceCounter(FStart);
  FCounting := True;
  FElapsedTime := 0;
  FOverallElapsedTime := 0;
  {$IFDEF MSWINDOWS}
  if not QueryPerformanceCounter(FStart) then
    raise EJclCounterError.CreateRes(@RsNoCounter);
  {$ENDIF MSWINDOWS}
  {$IFDEF LINUX}
  GetTimeOfDay(FTimeval, nil);
  FStart := FTimeval.tv_sec * 100000 + (FTimeval.tv_usec);
  {$ENDIF LINUX}
end;

cryo123 26. Jun 2007 09:12

Re: JCLCounter - High Performance Counter
 
I think we've met the same problem some days ago with delphi 2006 and JCL and we just found a simple way to solve it : you have to change your compiler settings to align record data on 4 bytes.

For Delphi 2006, Go to Project => Options => Compiler => Code generation and look for the "Field Record Alignment" with a combobox with possible values : "0,1,2,4,8". You have to choose 4 (8 also seems to work) and recompile all your project
I do not know for other Delphi versions but it should be quite similar IMHO

PS : Sorry for writing in english on a german forum :(. I hope someone could translate it to others people here

Robert Marquardt 26. Jun 2007 09:21

Re: JCLCounter - High Performance Counter
 
Thanks for this hint! We will check the JCL if we can find a problem there. It may be a compiler bug though.

Der Hinweis ist das Projekt auf record alignment 4 bzw. 8 einzustellen und komplett neu zu erstellen.
creality, kannst du mal {$ALIGN 4} in JclCounter.pas einfuegen und die JCL neu erstellen (einfach install.bat erneut ausfuehren).
Am besten zwischen das erste uses und der Deklaration von TJclCounter.
Alternativ

{$IFDEF MSWINDOWS}
function QueryPerformanceCounter(var lpPerformanceCount: Int64): BOOL; stdcall; external kernel32 name 'QueryPerformanceCounter';
function QueryPerformanceFrequency(var lpFrequency: Int64): BOOL; stdcall; external kernel32 name 'QueryPerformanceCounter';
{$ENDIF MSWINDOWS}

In der implementation section von JclCounter.pas platzieren. Das Original in Windows.pas ist mit TLargeInteger deklariert und daher koennten die Probleme kommen.
Wenn das nicht hilft, dann

{$IFDEF MSWINDOWS}
function QueryPerformanceCounter(lpPerformanceCount: Pointer): BOOL; stdcall; external kernel32 name 'QueryPerformanceCounter';
function QueryPerformanceFrequency(lpFrequency: Pointer): BOOL; stdcall; external kernel32 name 'QueryPerformanceCounter';
{$ENDIF MSWINDOWS}

ausprobieren und die Aufrufe um ein @ vor dem Parameter ergaenzen.

Bitte alle Varianten ausprobieren. Sollte die zweite Variante funktionieren, dann wird sie in die JCL uebernommen.

creality 26. Jun 2007 10:03

Re: JCLCounter - High Performance Counter
 
Ok, ich werds ausprobieren. Heut Nachmittag sitz ich wieder am Rechner. Ich lasses Euch wissen!

In diesem Sinne, bis später.

MrOuzo 13. Jul 2007 13:01

Re: JCLCounter - High Performance Counter
 
Hi, :wall: :wall: :wall:

auch ich habe hier das Problem mit dem Timer. Es gibt dazu bei MS einen Artikel in der Knowledge Base :896256

und

http://support.microsoft.com/?scid=kb;en-us;895980

http://support.microsoft.com/kb/327809/de

Ich glaube in Zukunft können wir uns auf den Timer nicht mehr verlassen.

Hier ist auch noch was zu den Thema

http://channel9.msdn.com/ShowPost.aspx?PostID=156175


Gruß
MrOuzo


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:06 Uhr.

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