# System.currentTimeMillis() recht ungenau?



## Serge (1. Feb 2007)

kann es sein dass System.currentTimeMillis() recht ungenau ist?
Ich wenn ich eine schleife programmiere wo in einer Variable immer die Zeit der letzten Zeitabfrage gespeichert wird und dann beim nächsten durchgang mit println der Unterschied zur momentanen Zeit ausgegeben.
Wenn ich es ausführe, kommt bei mir dauernd "0" und dann zwischendurch immer mal "15" oder "16".
Was also heißt dass es 15/1000stel sekunden genau ist und nicht 1/1000?

Was mich dabei wundert, dass diese methode in einem Tutorial dazu empfohlen wurde um einen FPS counter zu programmieren. Ist das Systemspezifisch wie genau diese Funktion ist? Gibt es da eine genauere Funktion?


----------



## FatFire (2. Feb 2007)

Es gibt da noch die System.nanoTime(), aber die gibt keine wirkliche Zeitangabe, sondern ist wirklich nur zur Messung von Zeitdifferenzen gut, was für einen FPS-Counter natürlich ideal ist. Aber Vorsicht: das gibt es erst seit Java 1.5, also falls Du kompatibel mit älteren VMs bleiben willst, ist das natürlich Humbug.

EDIT: Die bessere Lösung (wenn man nanoTime nicht nutzen will) ist es, innerhalb einer Sekunde die Frames zu zählen, die wirklich gezeichnet werden und nach Ablauf der Sekunde (checken mit Calendar oder GregorianCalendar) die gezählten Frames auszugeben und den Zähler wieder auf null zu setzen.


----------



## SlaterB (2. Feb 2007)

ich habe auch diese Beobachtung,
aber ein Beweis wäre sie so für sich nicht,

wenn du zwischen jeder Messung println machst, dann ist das ja eine extrem aufwendige Operation,
vielleicht wird die für ein paar Aufrufe intern gespeichert (0 ms) und dann werden irgendwann mal alle Ausgaben an die Konsole weitergeleitet, was gerne 15 ms dauern kann..

oder irgendwelche Betriebssystem-Threads unterbrechen Java für diese Zeit (man ist ja nicht allleine) 
oder gar interne VM-Verwaltungsthreads/ Speichermanagement/ Garbage Collector,

es ist wohl so ungenau, das stimmt schon,
aber diese Messung alleine sagt nicht viel aus


----------



## FatFire (2. Feb 2007)

> es ist wohl so ungenau, das stimmt schon,
> aber diese Messung alleine sagt nicht viel aus


Nein, diese Messung alleine sagt nicht viel aus, hast Du Recht, aber spätestens beim direkten Vergleich der Funktionen fällt es einem genau auf:

```
import java.util.Calendar;

public class Genauigkeit {

	public static void main(String args[]){
		Calendar cal;
		while(true){
			cal = Calendar.getInstance();
			System.out.println("Nano: " + String.valueOf(System.nanoTime()));
			System.out.println("Millis: " + String.valueOf(System.currentTimeMillis()));
			System.out.println("Calendar: " + String.valueOf(cal.getTimeInMillis()));
		}
	}
}
```
Man beachte die ständige Änderung von Nano, was auch die Theorie mit der internen Speicherung verwirft.

P.S.: Weniger mutmaßen, mehr Coden.


----------



## SlaterB (2. Feb 2007)

nettes Programm, danke



aber auch bei Nano gibt es viele Sonderheiten,
die (noch) Platz für meine Spekulationen lassen 

mit verändertem Programm:

```
int i = 0;
long nanoAlt = 0;
long milliAlt = 0;
long nano = 0;
long milli = 0;
DecimalFormat d = new DecimalFormat("00000000");
while (i < 100)
{
    i++;

    milliAlt = milli;
    nanoAlt = nano;
    nano = System.nanoTime();
    milli = System.currentTimeMillis();

    System.out.println("Nano: " + String.valueOf(nano) + "  Millis: " + String.valueOf(milli) 
       + " Dif Milli: "+ d.format(milli - milliAlt) + "  Dif Nano: " + d.format(nano - nanoAlt));

}
```


kommt es durchaus ab und zu auch bei Nano zu Sprüngen:

Nano: 21084611266515  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00061739
Nano: 21084611355633  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00089118
Nano: 21084611907658  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00552025
Nano: 21084611978058  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00070400
Nano: 21084612038122  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00060064
Nano: 21084612098185  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00060063



und wenn Milli mal plötzlich springt, dann reagiert Nano ganz unterschiedlich,
mal passiert nix, oft springt aber auch Nano um bedeutende Größen:


Nano: 21026541843446  Millis: 1170423677345 Dif Milli: 00000000  Dif Nano: 00108114
Nano: 21026541951002  Millis: 1170423677345 Dif Milli: 00000000  Dif Nano: 00107556
Nano: 21026542061351  Millis: 1170423677345 Dif Milli: 00000000  Dif Nano: 00110349
Nano: 21026556012286  Millis: 1170423677360 Dif Milli: 00000015  Dif Nano: 13950935
Nano: 21026556150013  Millis: 1170423677360 Dif Milli: 00000000  Dif Nano: 00137727
Nano: 21026556267067  Millis: 1170423677360 Dif Milli: 00000000  Dif Nano: 00117054
Nano: 21026556376299  Millis: 1170423677360 Dif Milli: 00000000  Dif Nano: 00109232


Nano: 21084607799874  Millis: 1170423735405 Dif Milli: 00000000  Dif Nano: 00070121
Nano: 21084607870832  Millis: 1170423735405 Dif Milli: 00000000  Dif Nano: 00070958
Nano: 21084607937321  Millis: 1170423735405 Dif Milli: 00000000  Dif Nano: 00066489
Nano: 21084608022528  Millis: 1170423735421 Dif Milli: 00000016  Dif Nano: 00085207
Nano: 21084608092369  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00069841
Nano: 21084608158578  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00066209
Nano: 21084608244343  Millis: 1170423735421 Dif Milli: 00000000  Dif Nano: 00085765


also meiner Meinung nach durchaus möglich,
dass ein Java-Programm da eine bedeutende Zeit unterbrochen wird,
oder meinst du, dass dies ausgeschlossen ist?

dass die Strings nicht intern gecacht werden mag ich gerne glauben, aber wie soll das Programm dies beweisen?
so schnell kann man ja gar nicht schauen, ob nun der Output nun zum Zeitpunt x oder erst 15ms später ausgegeben wird


----------



## FatFire (2. Feb 2007)

Erstmal auch Danke von mir für das Programm, für die Differenzberechnung war ich gerad zu faul  :applaus: 



> also meiner Meinung nach durchaus möglich,
> dass ein Java-Programm da eine bedeutende Zeit unterbrochen wird,
> oder meinst du, dass dies ausgeschlossen ist?


Nein, das hab ich ja auch nicht bezweifelt, das ist sogar de Facto so (wir haben ja nunmal eine Umgebung mit mehreren parallel laufenden Threads, wenn Nano mehr als normal springt, hatte zwischendurch ein anderes Programm die CPU-Zeit). Die Ungenauigkeit von currentTimeMillis ist damit de Facto sogar bewiesen, weil der Sprung der currentTimeMillis völlig getrennt von der Zuteilung der Rechnerzeit und damit vom Sprung von nanoTime sein kann (der Wahrscheinlichkeit nach liegen die Sprünge aber natürlich häufiger parallel). Die Auflösung von currentTimeMillis liegt damit (offensichtlich) wirklich bei 16, minimal 15ms.


> dass die Strings nicht intern gecacht werden mag ich gerne glauben, aber wie soll das Programm dies beweisen?


Hm, ich kann nicht mit 100%iger Sicherheit sagen, ob da ein internes Caching durchgeführt wird oder nicht, aber wenn, dann kein Caching der Inhalte, die dann in mehreren aufeinanderfolgenden Out's ersetzt werden, sondern höchstens Sammelausgaben der unterschiedlichen Inhalte (sonst würde er nicht nur currentTimeMillis cachen, sondern auch die nanoTime). Das Ausgeben auf der Konsole müßte ja eigentlich von Betriebssystemseite erfolgen, die VM wird das wohl direkt durchleiten...wäre schön, wenn man vielleicht ein paar Vergleichswerte verschiedener Betriebssysteme und Rechnerstärken hätte, dann könnte man mal schauen, ob z.B. unter Linux die "Uhren anders ticken" und ob es was mit der Betriebssystemseite zu tun hat.

P.S.: Kann man sich aber drauf einigen, daß nanoTime für den angesprochenen Einsatzzweck wesentlich besser geeignet ist als currentTimeMillis?


----------



## SlaterB (2. Feb 2007)

klar


----------

