Entschuldigt, wenn ich diesen alten Thread noch einmal aufwärme. Der Grund ist ganz einfach der, daß jeder, der nach Informationen über den EpikTimer googelt, zwangsläufig auf dieser Seite landet und das hier Besprochene als autoritative Beurteilung des Sachverhalts mitnehmen muß und so schlicht auf die falsche Fährte gesetzt wird.
Ich will im Folgenden zum einen beschreiben, was die verschiedenen Komponenten TTimer, TFPTimer und EpikTimer eigentlich darstellen und worin ihre Aufgaben und Unterschiede bestehen. Dann werde ich das Meßproblem diskutieren, auch hier lief die Diskussion in in eine völlig abstruse Richtung. Zunächst aber lassen sich ein paar Anmerkungen zum hier gepflegten Stil nicht vermeiden.
1) Stilfragen
mschnell hat geschrieben:Das kannst Du nicht beurteilen.
...
Völliger Unsinn !!!!
Wer sich mit Programmiersprachen herumschlägt, steht, egal ob Anfänger, Fortgeschrittener oder Profi, stets vor demselben Problem: Daß die Komplexität des Gegenstands die eigenen Fähigkeiten im Grunde übersteigt. Jedenfalls solange man sich mit mehr als Albernheiten beschäftigt.
Ausnahmslos jeder hat Verständnisprobleme, auf unterschiedlichstem Niveau, gewiß, aber egal auf welchem Niveau:
Jeder verfügt nur über ein begrenztes Wissen. Wenn das aber so ist, dann braucht sich hier doch keiner als Platzhirsch des Halbwissens aufzuspielen! Die Diskussion in diesem Thread ist von außen betrachtet wirklich frappierend:
Keiner hier hat sich den
EpikTimer genauer angesehen,
keiner hat das Thema "
Meßgenauigkeit" technisch angemessen diskutiert, aber jeder wußte - irgendwie - "
Bescheid". Am Ende hat Bora4D alle seine Postings (die offenbar nicht dem Mainstream der Platzhirsche entsprach) gelöscht und sich zurückgezogen, und auch Eva ward nie wieder gesehen - was man ihr nicht verdenken kann. Merkt Ihr sowas eigentlich noch?
Nun zum eigentlichen Thema.
2) TTimer - TFPTimer - EpikTimer
Timer ist nicht gleich Timer. Ein Timer kann nämlich zwei ganz unterschiedliche Aufgaben wahnehmen: Er kann eine Art
Wecker bzw.
Eieruhr darstellen, der sich nach einer festgelegten Zeit meldet und irgendwelche Aktionen ermöglicht. Eine Variante dessen ist das
Metronom: Der Timer kann sich in regelmäßigen Abständen immer wieder melden. Eine vollkommen andere Aufgabe stellt hingegen die
Stoppuhr dar: Sie mißt auf Abruf die Zeit zu einem bestimmten Zeitpunkt, legt den Wert als Variable ab, nimmt dann, wiederum auf Anforderung, eine zweite Zeitmessung vor und ermittelt die verstrichene Zeit zwischen diesen beiden Zeitpunkten. Mit einem Wecker kann man ohne weiteres keine Zeitabschnitte messen, eine Stoppuhr sagt einem nicht ohne weiteres, wann man los muß, um den Bus nicht zu verpassen.
So: Der
TTimer und der
TFPTimer sind
Eieruhren und
Metronome, sie verwalten Intervalle, aber sie messen keine beliebigen Intervalle. Sie sind zur Zeitmessung nicht geeignet, bzw. nur auf Umwegen. Der
EpikTimer hingegen ist eine
Stoppuhr, mit ihm lassen sich keine Weckfunktionen wahrnehmen (bzw. ebenfalls nur auf Umwegen z.B. über eine selbst programmierte wiederkehrenden Abfrage). Der Unterschied zwischen dem
TTimer und dem
TFPTimer besteht zum einen darin, daß der
TTimer eine LCL-Komponente ist, der
TFPTimer nicht, und zum anderen der
TTimer den jeweiligen Widgetset-Timer implementiert, während der
TFPTimer ein eigenständiges Widgetset-unabhängiges Freepascal-Modul ist. Beide lassen ihre Taktgebung in eigenen Threads laufen, keiner von beiden unterstützt die Zeitabnahme zu einem beliebigen Zeitpunkt und die Berechnung von Zeitdifferenzen.
Der EpikTimer hingegen ist eine
reine Stoppuhr ohne jedwede Event-Triggerfunktion. Das Grundprinzip ist denkbar einfach: Nehme die Zeit, speichere sie als Variable, nehme ein zweites Mal die Zeit und berchne die Differenz. Okay, er kann schon noch mehr, wie eine richtige Stoppuhr eben auch: Die Zeit weiterlaufen lassen, die Messung pausieren und wiederaufnehmen etc. Richtig ausgefuchst ist der EpikTimer dort, wo er selbständig ermittelt, welches die präziseste Methode der Zeitabnahme unter den gegebenen Umständen von Betriebssystem und Hardware darstellt. Zudem bietet er Schnittstellen, um weitere Zeitquellen flexibel einzubinden. Und er nimmt eine Kalibrierung der Systemzeit vor, um große Zeiträume sauber zu messen (das habe ich noch nicht wirklich verstanden). Im Gebrauch aber ist er denkbar einfach und komfortabel.
Eva hätte also für ihre Bildschirmdarstellung einen
TTimer gebraucht (warum der "
zu ungenau" sein sollte, hat sich mir nicht erschlossen, da ist sie wohl einem Denkfehler aufgesessen), und für die Messung des Tastendrucks einen
EpikTimer. Was auch kein Problem gewesen wäre, die Komponenten beißen sich nicht.
3) Meßgenauigkeit
mschnell hat geschrieben:
Das Betriebssystem kann aus internen Gründen jedes Programm jeder Zeit beliebig lange aufhalten.
Das ist nur insofern eine Halbwahrheit, als jedes Betriebssystem per definitionem die
Macht dazu hat. Aber die
Realität ist schlichtweg eine andere, denn es zählt zu den vornehmsten Aufgaben eines jeden multitaskingfähigen Betriebssystems, eben genau das
nicht zu tun! Um das angemessen zu diskutieren, hätte irgendjemand wenigstens einmal das Stichwort "
Latenzzeiten" aufs Tapet werfen müssen. Latenzzeiten sind aber statistische Größen, also hätte man über
Wahrscheinlichkeiten diskutieren müssen.
Vom Prinzip her haben einige das Grundproblem schon ganz richtig dargestellt: Eva startet ihr Programm, der Timer triggert, ihr Programm reagiert darauf mit einer Anzeige, der Timer triggert erneut, ihr Programm löscht die Bildschirmdarstellung, startet die Stoppuhr, die Tastatur meldet sich, ihr Programm stoppt die Stoppuhr und speichert das Ergebnis. Das Problem daran ist nun in der Tat nicht, daß die Zeiten nicht zuverlässig und hinreichend genau ausgelesen werden könnten oder gar die Systemuhr gestolpert wäre. Das Problem ist vielmehr, daß das Triggern der Timer-Events, das Durchdringen der Benachrichtigung, das Drücken der Stoppuhr immer erst dann geschehen kann, wenn ihrem Programm gerade mal wieder vom Betriebssystem Prozessorzeit zugewiesen wurde. Es vergeht also zwangsläufig bei jedem dieser Ereignisse eine gewisse Zeit, bis andere, gerade laufende Hintergrundprozesse unterbrochen und aufgeräumt werden und die Rechenkapazität wieder ihrem Programm zugeordnet wird (u.U. fügt es sich dann auch so, daß ihr Programm ohnehin gerade dem Prozessor zugeteilt ist, dann sind die Zeitverluste veschwindend gering).
Aber wie groß sind diese Verluste? Sind sie in einer solchen Größenordnung, daß Evas Experiment dadurch beeinträchtigt oder gar verunmöglicht worden wäre? Der Einzelfall ist in der Tat nicht vorhersagbar, die statistische Verteilung der vielen Einzelfälle aber schon. Wie gesagt, man spricht hier von der "
Latenzzeit". Die modernen Betriebssysteme haben ausgefeilte Stategien entwickelt, diese Latenzeiten niedrig zu halten - starre Zeitscheiben, die bürokratisch unbeeindruckt Stück für Stück durchgereicht werden, gibt es schon lange nicht mehr. So erhalten Programme, die offenkundig auf eine Benutzereingabe warten, eine höhere Priorität als Rechenknechtprozesse im Hintergrund. Und wenn ein Thread seine Zeitzuteilung nicht wirklich benötigt, wird sie ihm auch schnell wieder entzogen. Da sind äußerst ausgefuchste Algorithmen am Werk. Wer mehr darüber erfahren möchte, wird im Internet unter dem Stichwort "
Scheduler" reichlich fündig.
Ich wollte das jetzt einfach mal genau wissen, und deshalb ich habe ein kleines Testprogramm geschrieben. Es startet einen TTimer mit einer zufälligen Intervallzeit zwischen 0,25 und 1,25 Sekunden (um auf jeden Fall sicherzugehen, daß zwischen Start und Stop ein Threadwechsel stattfindet). Zugleich startet eine EpikTimer-Stoppuhr. Wenn der Timer triggert, wird ein kleines TShape auf enabled:= false gesetzt, was wiederum ein OnPaint-Event anstößt. Dort dann wird der EpikTimer gestoppt, die Intervallzeit des TTimers vom Ergebnis des EpikTimers abgezogen und so die Latenzzeit (beim Durchlauf zweier Ereignisse, was auch Evas Design entspricht) gemessen. Danach geht alles wieder von vorne los. Dies habe ich einmal unter CPU-Vollast durchgeführt (mit einer ffmpeg-Umcodierung und einem Download im Hintergrund), und dann unter normalen Bedingungen. Eine bestmögliche Idle-Situation wollte ich auch noch, aber das erwies sich dann als unnötig. Die Ergebnisse sind wie folgt:


Das Ergebnis ist in beiden Fällen eindeutig: In über 98 % der Fälle beträgt die Latenzzeit unter normalen Bedingungen weniger als 3 Millisekunden. Selbst unter Schwerlastbedingungen verschiebt sich das Ergebnis nicht wirklich gravierend. Erstaunlicherweise gibt es sogar einen leichen Bias zulasten der Hintergrundprozesse, der dem Testprogramm noch einen höheren Anteil sehr kurzer Reaktionszeiten verschafft hat. (Diese Werte entsprechen in etwa auch dem, was man darüber nachlesen kann).
Okay: Angemerkt werden muß unbedingt, daß das nur für Linux mit einem aktuellen Kernel gilt (auf einem Dual-Core AMD64). Wie sich das unter Windows darstellt, kann ich weder testen noch beurteilen - Linux steht allerdings im Ruf, in Hinblick auf Latenzzeiten deutlich besser zu zu sein als Windows. Man hätte Eva sicherlich mal fragen können, ob sie Zugriff auf einen Linux-Rechner hat, und ihr empfehlen können, das Experiment besser dort laufen zu lassen.
Jedenfalls bleibt von den hier vor zwei Jahren im Übermaß gepflegten Kassandrarufen nicht viel übrig!
4) Fazit
a) Eva hätte ihre Aufgabe völlig problemlos mit den von ihr gewählten Werkzeugen bewältigen können. Ich hoffe, sie hat es getan, anstatt sich von den Experten ins Bockshorn jagen zu lassen.
b) Die Latenzzeiten eines modernen Linux-Systems bewegen sich gut berechenbar in der Größenordnung von 1-3 ms, selbst unter Vollastbedingungen bleibt das System hervorragend reaktionsfähig.
c) Aller Glaubensstreit um die allerallergenaueste Zeitmessung (
GetTickCount, GettickCount64, Now, GetTimeOfDate etc.) ist ein Streit um des Kaisers Bart. Auf einem Linux-System beträgt die Meßgenauigkeit einige wenige Millisekunden, nicht weniger, aber auch nicht mehr. Und das liegt nicht an irgendwelchen Systemuhren oder supermodernen vs. veralteten Taktgebern, sondern ganz einfach an der Arbeitsweise des Systems.
d) Der
Epiktimer ist das Werkzeug der Wahl, wenn man sich das Selbstprogrammieren einer
Stoppuhr sparen will.
TTimer und
TFPTimer hingegen sind die Mittel der Wahl, wenn man eine
Eieruhr bzw. ein
Metronom braucht.
Gruß Rüdiger