Warum weicht FPS von eingestelltem Timer ab?
Übersicht

![]() |
Rick_72Betreff: Warum weicht FPS von eingestelltem Timer ab? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo Comm.!
Evtl. wurde diese Frage so oder so ähnlich schon mal gestellt, gefunden habe ich allerdings nichts darüber (das als vorgezogene Entschuldigung ![]() Code: [AUSKLAPPEN] Graphics 640,480,0,1
SetBuffer BackBuffer() Global Frames, Start, FPS# Frametimer=CreateTimer(60) Start=MilliSecs() Repeat Frames=Frames+1 If Start + 999 < MilliSecs() Then FPS# = Frames Frames = 0 Start = MilliSecs() EndIf Text 10, 10, "FPS="+FPS# WaitTimer(FrameTimer) Flip 1 Cls Until KeyHit(1) End .. und erhalte statt der zu erwartenden FPS=60 eine "FrameRate" von FPS=63. Diese Abweichung mag jetzt spezifisch von meinem System abhängen, wird aber so oder ähnlich wohl auch auf anderen Systemen abweichen (der Monitor läuft mit 85Hz). Woher diese Abweichung? Ich hätte das Verhalten des Progs so erwartet, dass er *hart* auf den Timer wartet und so auf jeden Fall bei 60Hz (also FPS=60) landet. Kann mir das jemand erklären und evtl. Tipps zur Abhilfe geben? Danke für Eure Hilfe! P.S.: ich teste die Blitz2D Demo V1.60 |
||
![]() |
Rick_72Betreff: Mal mit DebugLog gecheckt .. |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe den Code mal um einen schönen DebugLog erweitert, um mal die benötigte Zeit zum Schleifendurchlauf zu berechnen:
Code: [AUSKLAPPEN] Graphics 640,480,0,2
SetBuffer BackBuffer() Global Frames#, Start, FPS# Frametimer=CreateTimer(60) Start=MilliSecs() Repeat Frames#=Frames#+1 DebugLog(MilliSecs()-Start) ;Ein Durchlauf dauert 0.016 Sekunden! Entspricht 62.5 Hz If Start + 999 < MilliSecs() Then FPS# = Frames# Frames# = 0 Start = MilliSecs() EndIf Text 10, 10, "FPS="+FPS# WaitTimer(FrameTimer) Flip 0 Cls Until KeyHit(1) End Der Log spuckt aus, dass ein Durchlauf 16msec dauert. Das entspricht 62.5Hz, was sich mit meiner FPS=63 deckt. Bleibt nur die Frage, wo diese Abweichung herkommt! |
||
![]() |
Pummelie |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also eine Abweichung ist eigentlich normal, beim fps messen.
Folgendes Prinzip: er durchläuft die schleife, kommt auf if. die bedingung trifft nicht zu (um ein paar millisekunden) dann wartet er danach kommt er wieder auf if, und er hat schon weit mehr millisekunden. PS: Wenn du Timer verwendest immer flip 0 PSS: Verdammt tipp ich langsam |
||
- Zuletzt bearbeitet von Pummelie am Di, Aug 11, 2009 10:53, insgesamt einmal bearbeitet
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo.
Also, ich hätte da drei Vorschläge: 1. Stell den Timer mal an den Anfang der Schleife, dann wird vor der Rechnerei gewartet. Ich weiß nicht, ob das was bringt, bin grade erst aufgestanden. 2. Versuchs mal mit Flip 0 3. Setz den Timer mal als Global. Wenn alles Schwachsinn ist, tuts mir leid, bin wie gesagt grade erst aufgestanden. Lg, m0rgenstern |
||
![]() |
Rick_72Betreff: Morgähn! |
![]() Antworten mit Zitat ![]() |
---|---|---|
Danke für Deine schnelle Antwort. Habe das alles ausprobiert, aber keinerlei Änderungen festgestellt.
Einzig: wenn ich den Timer von 60 zB auf 80 verstelle, dann erhalte ich eine Schleifenzeit von 0.014sec, was ca. 83.4Hz entspricht. Ein Timer von 40 ergibt aber erstaunlicherweise eine Schleifenzeit von =0.025, was exakte den 40Hz entspricht. Ich habe offensichtlich, je schneller der Timer getaktet wird, eine Abweichung nach oben. ![]() Wenn ich mir den Log ansehe, so finde ich (bei Timer=60Hz) folgende Werte für die Schleifendurchläufe (Zeitpunkte in msec; im Code entspricht das der Zeile: Code: [AUSKLAPPEN] DebugLog(MilliSecs()-Start) ):
.. 976 992 1008 <-- hier greift die IF-Abfrage 16 32 .. Man erkennt, dass die IF-Abfrage um 8 msec zu spät erfolgt. Wenn man das aus den gemessenen FPS=63 rausrechnet, landet man immer noch bei FPS=62. Es kann also an der Code-Ausführungsdauer nicht liegen (spekuliere ich mal). Das ist doch irgendwie ominös, oder? |
||
![]() |
hamZtaAdministrator |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Rick_72: Bitte Doppelposts vermeiden, benutz den Edit-Button deiner Beiträge.
Grüße, hamZta ~EDITIERT~ Erledigtes entfernt, tut mir leid für die Umstände. hamZta |
||
Blog. |
- Zuletzt bearbeitet von hamZta am Di, Aug 11, 2009 13:49, insgesamt einmal bearbeitet
![]() |
Rick_72Betreff: Öh? |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Hamzta: welche Streitereien? Oder hast Du ein "böses" Postings bereits gelöscht, bevor ich es gesehen habe? Die beiden versuchen doch nur einen Lösungsansatz zu finden. ![]() @Pummelie: die Ticks(msec) der gesamten Schleife betragen 1008 msec. Mal 60Hz wären das FPS=60,5. Das Ding ist halt, das die gemessenen FPS=63 einer Durchlaufzeit von 1050msec entspricht. Irgendwo müssen also 42msec verloren gehen. Da haben wir's ja: die Antwort auf alle Fragen: 42. ![]() Letztenendes tut das bei meinem Programm nichts zur Sache, es läuft auch mit FPS=63. Aber mich hätte dann doch schon mal interessiert, warum der Timer nicht so recht das zu machen scheint, was man (ich) erwarten würde. Jedenfalls Danke für Eure Hilfe! |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Oh, Hamzta, vielen Dank, dass du meinen Beitrag gelöscht hast, indem ein Lösungsvorschlag stand.
Ich wollte keine Streiterei anfangen, sondern ihn einfach drauf hinweisen. Aber mal im Ernst, ohne dir jetzt böse zu wollen: Warum hast du Meinen kompletten Beitrag gelöscht, anstatt uns nur per Pn zu benachrichtigen oder so? Ich mein, jetzt steht dein Beitrag einfach so im Raum (und ist noch dazu OffTopic) Hier nochmal der Lösungsvorschlag, nach Boardsuche: Versuche mal Start + 1000 anstatt + 999 zu rechnen. SChreib dann bitte mal das ERgebnis hier rein. Vllt siehts dann schon anders aus. Ansonsten könnte ich mir bloß vorstellen, dass Prozesse aus dem hintergrund irgendwie eingreifen (fragt mich nicht wie, war nur ein Geistesblitz) @ Hamzta, mein Beitrag soll auf keinen Fall als Provokation zu verstehen sein, nicht dass es falsch rüber kommt. Lg, m0rgenstern |
||
![]() |
Rick_72Betreff: Ich glaub ich hab's.. ? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn man sich mal ausrechnet, wie lange ein Schleifendurchlauf bei einem Timer=60 dauern sollte, kommt man auf 16,67msec. Der Timer liefert aber nur ganze Zahlen, also 16. Wenn man diese Abweichung als Faktor berücksichtigt, kommt man auf eine korrigierte FPS=60,5. Davon müssen noch die 8msec runtergerechnet werden (siehe oben) und schwupps .. landen wir exakt bei FPS=60.
Das müsste also bedeuten, dass sämtliche FPS-Counter, die die Nachkommastellen (des eigentlichen Timers) nciht berücksichtigen, solange falsche Ergebnisse liefern, wie die Division 1000[msec]/Timer[60] nichtganzzahlige Ergebnisse liefert. Deswegen funktionuckelt der Counter auch bei 50Hz und 40Hz, nicht aber bei 30Hz. Das müsste es eigentlich gewesen sein ![]() Ich habe das mal schnell in einen Kode gehackt, der nicht ganz richtig und elegant ist, aber einen Ansatz bietet: Code: [AUSKLAPPEN] Graphics 640,480,0,2
SetBuffer BackBuffer() Global Frames#, Start, FPS# Global Freq#=60 ;in Hz Global Diff#=0 ;in msec Global RunTime#=0 ;in msec Global LoopTime#=0 Frametimer=CreateTimer(Freq#) If 1000/Freq#-Int(1000/Freq#)>0 Then ;hier passiert das Wesentliche, nämlich Die Differenz zwischen Diff#=1000/Freq#-Int(1000/Freq#) ;der ganzzahligen (Timer-)Frequenz und der echten ausrechnen ElseIf 1000/Freq#-Int(1000/Freq#)<0 Then Diff#=-1*(Int(1000/Freq#-1)-1000/Freq#) EndIf Start=MilliSecs() LoopTime#=MilliSecs() Repeat LoopTime#=MilliSecs() WaitTimer(FrameTimer) Frames#=Frames#+1 If Start + 999 < MilliSecs() Then FPS# = Frames# * (RunTime# / (RunTime# + Diff#)) Frames# = 0 Start = MilliSecs() EndIf Text 10, 10, "FPS="+FPS#+" Diff="+Diff#+" RunTime="+Int(RunTime#)+" Faktor="+(RunTime# / (RunTime# + Diff#)) Flip Cls RunTime#=MilliSecs()-LoopTime# Until KeyHit(1) End Wenn man dann noch nachsieht, wieviele msec beim Eintritt in die IF-Schleife vergangen sind (also wie im obigen Beispiel 1008msec), dann kann man noch den Faktor 1000[msec]/1008[msec] einrechnen. Der Rest wird dann großzügig als Rundungsfehler ignoriert. |
||
![]() |
Rick_72Betreff: Lauffähig .. |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich weiss, Doppelpostings sind zu vermeiden .. aber ich habe jetzt und hier einen Code, der das exakte Ergebnis für FPS liefert (wenn man mal großzügig von evtl. Rundungsfehlern absieht. Hoffentlich ist es das damit auch:
Code: [AUSKLAPPEN] Graphics 640,480,0,2
SetBuffer BackBuffer() Global Frames#, Start, FPS# Global Freq#=60 ;in Hz Global Diff#=0 ;in msec Global RunTime#=0 ;in msec Global LoopTime#=0 Frametimer=CreateTimer(Freq#) If 1000/Freq#-Int(1000/Freq#)>0 Then Diff#=1000/Freq#-Int(1000/Freq#) ElseIf 1000/Freq#-Int(1000/Freq#)<0 Then Diff#=-1*(Int(1000/Freq#-1)-1000/Freq#) EndIf Start=MilliSecs() Repeat WaitTimer(FrameTimer) Frames#=Frames#+1 If Start + 999 < MilliSecs() Then RunTime#=MilliSecs() - Start FPS# = Frames# * (Test# / (Test# + Diff#)) * 1000 / RunTime# Frames# = 0 Start = MilliSecs() EndIf Test#= (MilliSecs()-Start)/Frames# Text 10, 10, "Test#="+Test# Text 10, 25, "Diff[msec]="+Diff#+" Faktor="+((Test# / (Test# + Diff#)) * 1000 / RunTime#) Text 10, 45, "FPS="+FPS# Flip Cls Until KeyHit(1) End Das Wesentliche: 1. die IF-Schleife berechnet die "fehlende" Nachkommastelle. Damit kann schon mal die Abweichung von Timer zu realer Schleifendauer korrigiert werden. Dazu muss man nur noch rausfinden, wie lange eine Schleife läuft (das steht in Test#). Es ergibt sich dann ein Faktor = Test# / (Test# + Diff#). Im obigen 60Hz-Beispiel ist das also Faktor = 16 / (16 + 0.66667). FPS = FPS * Faktor 2. in RunTime# stehen die msec, die die Schleife real auslöst (also zu spät;obiges 60Hz-Beispiel: 8msec = 1008msec - 1000msec). Die zweite Korrektur muss also lauten: FPS = FPS *1000 / RunTime# Die gezählte FPS wird also korrigiert zu FPS = FPS * Faktor *1000 / RunTime# Kompliziert, und irgendwie nutzlos. Aber interessant, wie ich finde. |
||
![]() |
Rick_72Betreff: Oh weia! |
![]() Antworten mit Zitat ![]() |
---|---|---|
Lieber Admin, mich bitte jetzt wegen des Trippelpostings abmahnen. Aber ich muss meine Aussagen doch schnell korrigieren, weil ich natürlich Unfug geredet habe.
Die gemessenen FPS bei einem Timer von 60Hz sind FPS=63. Das liegt schlicht daran, dass der Timer keine Nachkommastellen beherrscht. 60Hz würden ja normalerweise 16,67 msec pro Frame bedeuten. Der Timer macht daraus aber 16 msec. Wir landen damit bei realen 63 Frames pro Sekunde. Bei Timer-Werten von zB 50Hz geht das natürlich ganzzahlig, weswegen die gemessene FPS dann mit der gewünschten (eingestellten) übereinstimmt. Die tollen Rechnungen oben sind also für die Katz. Erst Denken, dann Tippen. Mea culpa maxima. |
||
![]() |
BtbN |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zum einen: Der Timer arbeitet doch mit Ticks pro sekunde? Wo tritt da solch eine ungenauigkeit auf? Oder meinst du beim umrechnen intern?
Zum anderen: Die Edit-Funktion ist dir schon bekannt? |
||
![]() |
hamZtaAdministrator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Okay Rick_72, nochmal langsam zum Mitschreiben: Doppelposts sind NICHT in Ordnung, Dreifachposts schon gar nicht. Da hilfts auch nicht, als ersten Satz eine Entschuldigung zu bringen.
Benutz' ab sofort den Editbutton (diesen hier: ![]() Grüße, hamZta |
||
Blog. |
![]() |
Rick_72 |
![]() Antworten mit Zitat ![]() |
---|---|---|
BtbN hat Folgendes geschrieben: Zum einen: Der Timer arbeitet doch mit Ticks pro sekunde? Wo tritt da solch eine ungenauigkeit auf? Oder meinst du beim umrechnen intern?
Zum anderen: Die Edit-Funktion ist dir schon bekannt? Ja, die Edit-Funktion ist mir bekannt. Am liebsten hätte ich die Postings auch gelöscht, bin aber entweder nicht dazu berechtigt oder zu doof die Lösch-Funktion zu finden. Zu Deiner Frage: Der Timer arbeitet zwar mit "Ticks" pro sek., arbeitet selbst aber als Integer. Bei 60 Ticks/sek. müsste der Timer alle 16,67msec auslösen. Er kann aber nur ganzzahlig auslösen und macht das dann schon nach 16msec. Die Different von 0,67msec führt dann zu einer Beschleunigung von 3 FPS. Real werden also 63 "Ticks" statt nur 60 ausgelöst. In dem Sinne "saubere Ticks" gibt's nur, wenn 1000/Frequenz ganzzahlig ist, zB bei Frequenz=50Hz. @Admin: kann man eigene Postings irgendwie löschen? Ich könnte dann die obigen Listings rausschmeissen, die verwirren nur unnötig. Ausserdem könnte man (Du ![]() |
||
da_poller |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
vermeide in zukunft einfach doppel oder trippel posts..
nein, du kannst posts nciht löschen.. und das gelöst markieren ist unnötig.. irgendwann verschwindet der hread halt in der versenkung.. |
||
![]() |
Snade |
![]() Antworten mit Zitat ![]() |
---|---|---|
achja und das geloest kann man auch einfach selber dazu editieren einfach den ersten Post bearbeiten... | ||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Rick_72 hat Folgendes geschrieben: Er kann aber nur ganzzahlig auslösen und macht das dann schon nach 16msec.
Die Systemuhr des Betriebssystems ist nur auf ganze Millisekunden genau. Ist also nicht unbedingt ein Problem des Timers, sondern des OS ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
oder der hardware dahinter, die teilweise nicht mal auf ms genau is... | ||
Gewinner der 6. und der 68. BlitzCodeCompo |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group