Czy System.nanoTime () jest całkowicie bezużyteczny?

153

Jak udokumentowano w poście na blogu Beware of System.nanoTime () w Javie , w systemach x86 Java's System.nanoTime () zwraca wartość czasu przy użyciu licznika specyficznego dla procesora . Rozważmy teraz następujący przypadek, którego używam do mierzenia czasu połączenia:

long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;

Teraz w systemie wielordzeniowym może się zdarzyć, że po pomiarze czasu1 wątek zostanie zaplanowany dla innego procesora, którego licznik jest mniejszy niż poprzedni procesor. W ten sposób moglibyśmy otrzymać wartość w time2, która jest mniejsza niż time1. W ten sposób otrzymalibyśmy ujemną wartość czasu spędzonego.

Biorąc pod uwagę ten przypadek, czy nie jest tak, że System.nanotime jest obecnie prawie bezużyteczny?

Wiem, że zmiana czasu systemowego nie wpływa na nanotime. To nie jest problem, który opisałem powyżej. Problem polega na tym, że każdy procesor od momentu włączenia będzie utrzymywał inny licznik. Ten licznik może być niższy na drugim procesorze w porównaniu z pierwszym procesorem. Ponieważ wątek może zostać zaplanowany przez system operacyjny do drugiego procesora po uzyskaniu time1, wartość timeSpent może być niepoprawna, a nawet ujemna.

pdeva
źródło
2
Nie mam odpowiedzi, ale zgadzam się z tobą. Może należy to uznać za błąd w JVM.
Aaron Digulla
2
ten post jest niepoprawny i nieużywanie TSC jest powolne, ale musisz żyć z: bugs.sun.com/bugdatabase/view_bug.do?bug_id=6440250 Również TSC może być przydatne przez hiperwizor, ale potem znowu jest wolne.
bestsss
1
I oczywiście możesz uruchomić na maszynie wirtualnej, w której procesor może pojawić się w połowie sesji: D
Limited Atonement,

Odpowiedzi:

206

Ta odpowiedź została napisana w 2011 roku z punktu widzenia tego, co faktycznie robił Sun JDK tamtego czasu działający na systemach operacyjnych w tamtym czasie. To było bardzo dawno temu! Odpowiedź Leventova oferuje bardziej aktualną perspektywę.

Ten post jest zły i nanoTimejest bezpieczny. Istnieje komentarz do posta, który zawiera odsyłacze do posta na blogu Davida Holmesa , specjalisty ds. Czasu rzeczywistego i współbieżności w firmie Sun. To mówi:

System.nanoTime () jest implementowany przy użyciu interfejsu API QueryPerformanceCounter / QueryPerformanceFrequency [...] Domyślny mechanizm używany przez QPC jest określany przez warstwę abstrakcji sprzętu (HAL) [...] Ta wartość domyślna zmienia się nie tylko w przypadku sprzętu, ale także systemu operacyjnego wersje. Na przykład dodatek Service Pack 2 dla systemu Windows XP zmienił rzeczy, aby używać licznika czasu zarządzania energią (PMTimer) zamiast licznika znacznika czasu procesora (TSC) z powodu problemów z niezsynchronizowaniem TSC na różnych procesorach w systemach SMP oraz z powodu jego częstotliwości może się różnić (a tym samym jego związek z upływem czasu) w zależności od ustawień zarządzania energią.

Tak więc w systemie Windows był to problem aż do WinXP SP2, ale teraz nie jest.

Nie mogę znaleźć części II (lub więcej), która mówi o innych platformach, ale ten artykuł zawiera uwagę, że Linux napotkał i rozwiązał ten sam problem w ten sam sposób, z linkiem do FAQ dla clock_gettime (CLOCK_REALTIME) , który mówi:

  1. Czy clock_gettime (CLOCK_REALTIME) jest spójny dla wszystkich procesorów / rdzeni? (Czy arch ma znaczenie? Np. Ppc, arm, x86, amd64, sparc).

To powinien albo uważany buggy.

Jednak na x86 / x86_64 można zobaczyć, że niezsynchronizowane lub zmienne TSC częstotliwości powodują niespójności czasowe. Jądra 2.4 tak naprawdę nie miały ochrony przed tym, a wczesne jądra 2.6 również nie radziły sobie tutaj zbyt dobrze. Od 2.6.18 i nowszych logika wykrywania tego jest lepsza i zwykle wracamy do bezpiecznego źródła zegara.

ppc zawsze ma zsynchronizowaną podstawę czasu, więc nie powinno to stanowić problemu.

Tak więc, jeśli link Holmesa można odczytać jako sugerujący, że nanoTimewywołuje clock_gettime(CLOCK_REALTIME), to jest bezpieczny od jądra 2.6.18 na x86 i zawsze na PowerPC (ponieważ IBM i Motorola, w przeciwieństwie do Intela, faktycznie wiedzą, jak projektować mikroprocesory).

Niestety nie ma wzmianki o SPARC czy Solarisie. I oczywiście nie mamy pojęcia, co robią maszyny JVM IBM. Jednak maszyny JVM firmy Sun w nowoczesnych systemach Windows i Linux radzą sobie dobrze.

EDYCJA: Ta odpowiedź jest oparta na źródłach, które cytuje. Ale nadal martwię się, że może to być całkowicie błędne. Niektóre bardziej aktualne informacje byłyby naprawdę cenne. Właśnie trafiłem na link do nowszego o cztery lata artykułu o zegarach Linuksa, który może być przydatny.

Tom Anderson
źródło
13
Nawet WinXP SP2 wydaje się cierpieć. Uruchomienie oryginalnej próbki kodu, ze void foo() { Thread.sleep(40); }mam czas ujemny (-380 ms!) Za pomocą jednego Athlon 64 X2 4200+procesora
Luke Usherwood
Nie przypuszczam, że istnieją aktualizacje w tej sprawie, wrt. zachowanie na platformach Linux, BSD lub innych?
Tomer Gabel,
6
Dobra odpowiedź, należy dodać link do nowszej eksploracji tego tematu: shipilev.net/blog/2014/nanotrusting-nanotime
Nitsan Wakart
1
@SOFe: Och, szkoda. Na szczęście jest w archiwum internetowym . Zobaczę, czy uda mi się znaleźć aktualną wersję.
Tom Anderson
1
Uwaga: OpenJDK nie spełniał specyfikacji aż do OpenJDK 8u192, zobacz bugs.openjdk.java.net/browse/JDK-8184271 . Upewnij się, że używasz co najmniej nowej wersji OpenJDK 8 lub OpenJDK 11+.
leventov
35

Poszukałem trochę i stwierdziłem, że jeśli ktoś jest pedantyczny, to tak, może to zostać uznane za bezużyteczne ... w określonych sytuacjach ... zależy to od tego, jak wrażliwe są twoje wymagania ...

Sprawdź ten cytat z witryny Java Sun:

Zegar czasu rzeczywistego i System.nanoTime () są oparte na tym samym wywołaniu systemowym, a zatem na tym samym zegarze.

W Java RTS wszystkie oparte na czasie interfejsy API (na przykład zegary, okresowe wątki, monitorowanie terminów itp.) Są oparte na zegarze o wysokiej rozdzielczości. Razem z priorytetami czasu rzeczywistego mogą zapewnić, że odpowiedni kod zostanie wykonany we właściwym czasie z uwzględnieniem ograniczeń czasu rzeczywistego. W przeciwieństwie do tego, zwykłe API Java SE oferują tylko kilka metod zdolnych do obsługi czasów o wysokiej rozdzielczości, bez gwarancji wykonania w określonym czasie. Używanie System.nanoTime () między różnymi punktami w kodzie do wykonywania pomiarów upływającego czasu powinno zawsze być dokładne.

Java ma również zastrzeżenie dotyczące metody nanoTime () :

Ta metoda może być stosowana tylko do pomiaru upływającego czasu i nie jest związana z żadnym innym pojęciem czasu systemowego lub zegarowego. Zwrócona wartość reprezentuje nanosekundy od pewnego ustalonego, ale arbitralnego czasu (być może w przyszłości, więc wartości mogą być ujemne). Ta metoda zapewnia nanosekundową precyzję, ale niekoniecznie nanosekundową dokładność. Nie ma gwarancji, jak często zmieniają się wartości. Różnice w kolejnych wywołaniach trwających dłużej niż około 292,3 lat (2 63 nanosekund) nie pozwolą dokładnie obliczyć upływającego czasu z powodu przepełnienia numerycznego.

Wydawałoby się, że jedynym wnioskiem, jaki można wyciągnąć, jest to, że nanoTime () nie może być traktowane jako dokładna wartość. W związku z tym, jeśli nie musisz mierzyć czasów, które są oddalone od siebie zaledwie o nano sekundy, ta metoda jest wystarczająco dobra, nawet jeśli wynikowa zwrócona wartość jest ujemna. Jeśli jednak potrzebujesz większej precyzji, wydaje się, że zalecają korzystanie z JAVA RTS.

A więc odpowiadając na twoje pytanie ... żadna nanoTime () nie jest bezużyteczna ... po prostu nie jest to najrozsądniejsza metoda w każdej sytuacji.

mezoid
źródło
3
> ta metoda jest wystarczająco dobra, nawet jeśli wynikowa zwrócona wartość jest ujemna. Nie rozumiem tego, jeśli wartość w timespent jest ujemna, to jak jest to w ogóle przydatne w mierzeniu czasu w foo ()?
pdeva
3
jest w porządku, ponieważ martwisz się tylko wartością bezwzględną różnicy. tj. jeśli twoim pomiarem jest czas t, gdzie t = t2 - t1, to chcesz wiedzieć | t | .... więc co, jeśli wartość jest ujemna ... nawet w przypadku problemu wielordzeniowego wpływ rzadko będzie kilka w każdym razie nanosekundy.
mezoid
3
Aby wykonać kopię zapasową @Aaron: zarówno t2, jak i t1 mogą być ujemne, ale (t2-t1) nie mogą być ujemne.
jfs
2
aaron: dokładnie o to mi chodzi. t2-t1 nigdy nie powinno być ujemne, w przeciwnym razie mamy błąd.
pdeva
12
@pdeva - ale nie rozumiesz, co mówi dokument. Podnosisz nieistotny problem. W pewnym momencie uważa się, że wynosi „0”. Wartości zwracane przez nanoTime () są dokładne w stosunku do tego czasu. To monotonnie rosnąca oś czasu. Możesz po prostu otrzymać serię liczb z ujemnej części tej osi czasu. -100, -99, -98(Oczywiście znacznie większe wartości w praktyce). Idą we właściwym kierunku (rosną), więc nie ma tu problemu.
ToolmakerSteve
18

Nie ma potrzeby debatowania, po prostu użyj źródła. Tutaj, SE 6 dla Linuksa, wyciągnij własne wnioski:

jlong os::javaTimeMillis() {
  timeval time;
  int status = gettimeofday(&time, NULL);
  assert(status != -1, "linux error");
  return jlong(time.tv_sec) * 1000  +  jlong(time.tv_usec / 1000);
}


jlong os::javaTimeNanos() {
  if (Linux::supports_monotonic_clock()) {
    struct timespec tp;
    int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
    assert(status == 0, "gettime error");
    jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
    return result;
  } else {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);
    return 1000 * usecs;
  }
}
blais
źródło
7
Jest to przydatne tylko wtedy, gdy wiesz, do czego służy używany interfejs API. Używane API jest realizowane przez system operacyjny; ten kod jest poprawny wrt. specyfikację używanego API (clock_gettime / gettimeofday), ale jak zauważyli inni, niektóre nieaktualne systemy operacyjne mają błędne implementacje.
Blaisorblade
18

Od wersji Java 7, System.nanoTime()specyfikacja JDK gwarantuje bezpieczeństwo. System.nanoTime()Javadoc wyjaśnia, że ​​wszystkie obserwowane wywołania w JVM (to znaczy we wszystkich wątkach) są monotoniczne:

Zwrócona wartość reprezentuje nanosekundy od pewnego ustalonego, ale dowolnego czasu pochodzenia (być może w przyszłości, więc wartości mogą być ujemne). To samo źródło jest używane przez wszystkie wywołania tej metody w wystąpieniu wirtualnej maszyny języka Java; inne wystąpienia maszyn wirtualnych prawdopodobnie będą używać innego źródła.

Implementacja JVM / JDK jest odpowiedzialna za wyeliminowanie niespójności, które można zaobserwować, gdy wywoływane są podstawowe narzędzia systemu operacyjnego (np. Te wymienione w odpowiedzi Toma Andersona ).

Większość innych starych odpowiedzi na to pytanie (napisanych w latach 2009–2012) wyraża FUD, który prawdopodobnie był istotny dla Javy 5 lub Javy 6, ale nie ma już znaczenia dla nowoczesnych wersji Javy.

Warto jednak wspomnieć, że pomimo gwarancji nanoTime()bezpieczeństwa JDK , w OpenJDK było kilka błędów powodujących, że nie dotrzymuje on tej gwarancji na niektórych platformach lub w pewnych okolicznościach (np. JDK-8040140 , JDK-8184271 ). W tej chwili nie ma żadnych otwartych (znanych) błędów w OpenJDK wrt nanoTime(), ale odkrycie nowego takiego błędu lub regresja w nowszej wersji OpenJDK nie powinno nikogo zszokować.

Mając to na uwadze, kod, który używa nanoTime()do blokowania czasowego, oczekiwania na interwał, przekroczenia limitu czasu itp. Powinien raczej traktować ujemne różnice czasu (limity czasu) jako zera, a nie zgłaszać wyjątki. Praktyka ta jest również korzystna, ponieważ jest zgodna z zachowaniem wszystkich zsynchronizowanych metod czekać w wszystkich klasach w java.util.concurrent.*, na przykład Semaphore.tryAcquire(), Lock.tryLock(), BlockingQueue.poll(), itd.

Niemniej jednak nanoTime()nadal powinno być preferowane do implementacji blokowania czasowego, oczekiwania interwałowego, przekroczenia limitów czasu itp., currentTimeMillis()Ponieważ to ostatnie podlega zjawisku „cofania się czasu” (np. Z powodu korekty czasu serwera), tj. currentTimeMillis()Nie nadaje się do pomiaru odstępów czasu w ogóle. Zobacz tę odpowiedź, aby uzyskać więcej informacji.

Zamiast używać nanoTime()do bezpośredniego pomiaru czasu wykonania kodu, najlepiej używać wyspecjalizowanych frameworków do benchmarkingu i profilerów, na przykład JMH i async-profiler w trybie profilowania zegara ściennego .

Leventov
źródło
6

Linux koryguje rozbieżności między procesorami, ale Windows nie. Sugeruję, abyś założył, że System.nanoTime () ma dokładność tylko do około 1 mikro-sekundy. Prostym sposobem na uzyskanie dłuższego czasu jest wywołanie funkcji foo () 1000 lub więcej razy i podzielenie czasu przez 1000.

Peter Lawrey
źródło
2
Czy możesz podać odniesienie (zachowanie w systemie Linux i Windows)?
jfs
Niestety, proponowana metoda będzie zwykle wysoce nieprecyzyjna, ponieważ każde zdarzenie przypadające w szczelinie aktualizacji zegara ściennego +/- 100 ms często zwraca zero dla operacji poniżej sekundy. Suma 9 operacji, z których każda ma czas trwania równy zero, wynosi zero, podzielone przez dziewięć, to ... zero. I odwrotnie, użycie System.nanoTime () zapewni stosunkowo dokładne (niezerowe) czasy trwania zdarzeń, które następnie zostaną zsumowane i podzielone przez liczbę zdarzeń, aby uzyskać bardzo dokładną średnią.
Darrell Teague
@DarrellTeague podsumowując 1000 wydarzeń i dodając je jest tym samym, co czas od końca do końca.
Peter Lawrey,
@DarrellTeague System.nanoTime () w większości systemów ma dokładność do 1 mikrosekundy lub lepszą (nie 100 000 mikrosekund). Uśrednianie wielu operacji ma znaczenie tylko wtedy, gdy sprowadzisz się do kilku mikrosekund i tylko w niektórych systemach.
Peter Lawrey,
1
Przepraszamy za pewne zamieszanie co do języka używanego podczas „podsumowywania” wydarzeń. Tak, jeśli czas jest zaznaczony na początku, powiedzmy, 1000 sub-sekundowych operacji, są one uruchamiane, a następnie czas jest ponownie oznaczany na końcu i dzielony - to zadziałałoby w przypadku niektórych rozwijanych systemów, aby uzyskać dobre przybliżenie czasu trwania dla danego zdarzenie.
Darrell Teague
5

Absolutnie nie bezużyteczne. Miłośnicy pomiaru czasu poprawnie wskazują na problem wielordzeniowy, ale w aplikacjach używających rzeczywistych słów często jest on radykalnie lepszy niż currentTimeMillis ().

Podczas obliczania pozycji grafiki w ramkach odświeżanie nanoTime () prowadzi do DUŻO płynniejszego ruchu w moim programie.

Testuję tylko na maszynach wielordzeniowych.

Yuvi Masory
źródło
5

Widziałem ujemny czas, który upłynął od użycia System.nanoTime (). Żeby było jasne, kod, o którym mowa, to:

    long startNanos = System.nanoTime();

    Object returnValue = joinPoint.proceed();

    long elapsedNanos = System.nanoTime() - startNanos;

a zmienna „elapsedNanos” miała wartość ujemną. (Jestem pewien, że połączenie pośrednie również zajęło mniej niż 293 lata, co jest punktem przepełnienia dla nanos przechowywanych w długich długościach :)

Nastąpiło to przy użyciu 64-bitowego środowiska IBM JRE 1.5 na sprzęcie IBM P690 (wielordzeniowym) z systemem AIX. Widziałem ten błąd tylko raz, więc wydaje się niezwykle rzadki. Nie znam przyczyny - czy jest to problem specyficzny dla sprzętu, wada JVM - nie wiem. Nie znam też ogólnych implikacji dla dokładności nanoTime ().

Odpowiadając na pierwotne pytanie, nie sądzę, że nanoTime jest bezużyteczny - zapewnia czas poniżej milisekundy, ale istnieje rzeczywiste (nie tylko teoretyczne) ryzyko, że będzie niedokładny, co należy wziąć pod uwagę.

Basil Vandegriend
źródło
Niestety, wydaje się, że jest to jakiś problem z systemem operacyjnym / sprzętem. Dokumentacja stwierdza, że ​​podstawowe wartości mogą być ujemne, ale (większy ujemny minus mniejszy ujemny) nadal powinny być wartością dodatnią. W istocie założenie jest takie, że w tym samym wątku wywołanie nanoTime () powinno zawsze zwracać wartość dodatnią lub ujemną. Nigdy nie widziałem tego w różnych systemach Unix i Windows przez wiele lat, ale wydaje się to możliwe, zwłaszcza jeśli sprzęt / system operacyjny dzieli tę pozornie atomową operację na procesory.
Darrell Teague
@BasilVandegriend nigdzie nie jest to błąd. Zgodnie z dokumentacją rzadko kiedy druga System.nanoTime () w twoim przykładzie może działać na innym CPU, a wartości nanoTime obliczone dla tego procesora mogą być po prostu niższe niż wartości obliczone na pierwszym procesorze. Tak więc możliwa jest wartość -ve dla elapsedNanos
niekończące się
2

Nie wydaje się to być problemem na Core 2 Duo z systemem Windows XP i JRE 1.5.0_06.

W teście z trzema wątkami nie widzę System.nanoTime () przechodzącego wstecz. Procesory są zajęte, a wątki czasami zasypiają, aby sprowokować poruszające się wątki.

[EDYCJA] Wydaje mi się, że dzieje się tak tylko na fizycznie oddzielnych procesorach, tj. Liczniki są zsynchronizowane dla wielu rdzeni na tej samej matrycy.

starblue
źródło
2
Prawdopodobnie nie będzie się to zdarzać cały czas, ale ze względu na sposób implementacji nanotime () taka możliwość jest zawsze dostępna.
pdeva
Domyślam się, że dzieje się to tylko na fizycznie oddzielnych procesorach, tj. Liczniki są zsynchronizowane dla wielu rdzeni na tej samej matrycy.
starblue
Nawet to zależy od konkretnej implementacji, IIRC. Ale to jest coś, czym powinien zająć się system operacyjny.
Blaisorblade
1
Liczniki RDTSC na wielu rdzeniach tego samego procesora x86 niekoniecznie są zsynchronizowane - niektóre nowoczesne systemy pozwalają różnym rdzeniom działać z różnymi prędkościami.
Jules
2

Nie, to nie jest ... To zależy tylko od twojego procesora, sprawdź High Precision Event Timer, aby dowiedzieć się, jak / dlaczego różne rzeczy są traktowane w zależności od procesora.

Zasadniczo przeczytaj źródło swojej Javy i sprawdź, co robi twoja wersja z funkcją i czy działa przeciwko procesorowi, na którym będziesz ją uruchamiać.

IBM sugeruje nawet użycie go do testów porównawczych wydajności (post z 2008 roku, ale zaktualizowany).

Ric Tokyo
źródło
Jak każda implementacja definiowała zachowanie, „caveat emptor!”
David Schmitt
2

Nawiązuję do tego, co zasadniczo jest tą samą dyskusją, w której Peter Lawrey udziela dobrej odpowiedzi. Dlaczego przy użyciu System.nanoTime () otrzymuję ujemny czas, który upłynął?

Wiele osób wspomniało, że w Java System.nanoTime () może zwracać czas ujemny. Przepraszam za powtórzenie tego, co powiedzieli już inni.

  1. nanoTime () nie jest zegarem, ale licznikiem cykli procesora.
  2. Wartość zwracana jest dzielona przez częstotliwość, aby wyglądała jak czas.
  3. Częstotliwość procesora może się zmieniać.
  4. Kiedy twój wątek jest zaplanowany na innym procesorze, istnieje szansa na uzyskanie nanoTime (), co skutkuje ujemną różnicą. To logiczne. Liczniki między procesorami nie są synchronizowane.
  5. W wielu przypadkach możesz uzyskać dość mylące wyniki, ale nie będziesz w stanie tego stwierdzić, ponieważ delta nie jest ujemna. Pomyśl o tym.
  6. (niepotwierdzone) Myślę, że możesz otrzymać negatywny wynik nawet na tym samym procesorze, jeśli instrukcje zostaną zmienione. Aby temu zapobiec, musiałbyś wywołać barierę pamięci serializującą twoje instrukcje.

Byłoby fajnie, gdyby System.nanoTime () zwrócił coreID tam, gdzie został wykonany.

Wir
źródło
1
Wszystkie punkty poza 3. i 5. są błędne. 1. nanoTime () nie jest licznikiem cykli procesora, jest to nano czas . 2. Sposób tworzenia wartości nanoTime zależy od platformy. 4. Nie, różnica nie może być ujemna, zgodnie ze specyfikacją nanoTime (). Zakładając, że OpenJDK nie ma błędów wrt nanoTime () i obecnie nie ma żadnych znanych nierozwiązanych błędów. 6. Wywołań nanoTime nie można zmieniać w ramach wątku, ponieważ jest to metoda natywna, a JVM szanuje kolejność programów. JVM nigdy nie zmienia kolejności wywołań metod natywnych, ponieważ nie wie, co się w nich dzieje i dlatego nie może udowodnić, że takie zmiany kolejności byłyby bezpieczne.
leventov
W odniesieniu do 5. wyników nanoTime () różnice mogą być rzeczywiście mylące, ale nie z powodów przedstawionych w innych punktach odpowiedzi. Ale raczej z powodów przedstawionych tutaj: shipilev.net/blog/2014/nanotrusting-nanotime
leventov
Jak na ironię, jeśli chodzi o 6. wystąpił błąd w OpenJDK, szczególnie z powodu ponownych zamówień : bugs.openjdk.java.net/browse/JDK-8184271 . W OpenJDK nanoTime () jest nieodłącznym elementem i pozwolono na jego zmianę, to był błąd.
leventov
@leventov, więc czy nanotime () jest bezpieczne w użyciu? co oznacza, że ​​nie może zwracać wartości ujemnych i jest ~ dokładna na miarę upływu czasu. Nie widzę sensu ujawniania funkcji API, która jest pełna problemów. Ten post jest dowodem, rozpoczęła się w 2009 roku i nadal skomentował w roku 2019. Na misji krytycznej rzeczy, wyobrażam sobie ludzie polegać na kartach czasowych jak Symmetricom
Vortex
1
Twój numer 4 mówi o ujemnej różnicy , a nie o wartościach: „istnieje szansa na uzyskanie nanoTime (), co skutkuje ujemną różnicą”.
leventov
1

Java jest wieloplatformowa, a nanoTime jest zależna od platformy. Jeśli używasz Javy - kiedy nie używaj nanoTime. Znalazłem prawdziwe błędy w różnych implementacjach jvm z tą funkcją.

knave kilork
źródło
0

Dokumentacja Java 5 również zaleca użycie tej metody w tym samym celu.

Ta metoda może być stosowana tylko do pomiaru upływającego czasu i nie jest związana z żadnym innym pojęciem czasu systemowego lub zegarowego.

Dokumentacja API Java 5


źródło
0

Ponadto System.currentTimeMillies()zmienia się po zmianie zegara systemy, a System.nanoTime()nie, więc ten ostatni jest bezpieczniej zmierzyć czas trwania.

RobAu
źródło
-3

nanoTimejest wyjątkowo niepewny czas. Wypróbowałem to na moich podstawowych algorytmach testowania pierwotności i dało odpowiedzi, które były dosłownie o jedną sekundę oddalone dla tego samego wejścia. Nie używaj tej śmiesznej metody. Potrzebuję czegoś, co jest dokładniejsze i dokładniejsze niż mierzenie milisekund czasu, ale nie tak złe jak nanoTime.

sarvesh
źródło
bez źródła lub lepszego wyjaśnienia ten komentarz jest bezużyteczny
ic3