क्या System.nanoTime () पूरी तरह से बेकार है?


153

जैसा कि x86 सिस्टम पर जावा में System.nanoTime () के ब्लॉग पोस्ट में प्रलेखित है , Java का System.nanoTime () CPU विशिष्ट काउंटर का उपयोग करके समय मान लौटाता है । अब कॉल के समय को मापने के लिए मेरे द्वारा उपयोग किए जाने वाले निम्नलिखित मामले पर विचार करें:

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

अब मल्टी-कोर सिस्टम में, यह हो सकता है कि समय 1 को मापने के बाद, थ्रेड एक अलग प्रोसेसर के लिए निर्धारित किया जाता है, जिसका काउंटर पिछले सीपीयू से कम है। इस प्रकार हम time2 में एक मान प्राप्त कर सकते हैं जो time1 से कम है। इस प्रकार हमें टाइमस्पेंट में एक नकारात्मक मूल्य मिलेगा।

इस मामले को ध्यान में रखते हुए, क्या यह नहीं है कि System.nanotime अब के लिए बहुत बेकार है?

मुझे पता है कि सिस्टम का समय बदलना नैनोटाइम को प्रभावित नहीं करता है। मैं ऊपर वर्णित समस्या नहीं है। समस्या यह है कि प्रत्येक CPU चालू होने के बाद एक अलग काउंटर रखेगा। यह सीपीयू पहले सीपीयू की तुलना में दूसरे सीपीयू पर कम हो सकता है। चूंकि टाइम 1 प्राप्त करने के बाद थ्रेड को ओएस द्वारा दूसरे सीपीयू में शेड्यूल किया जा सकता है, टाइमस्पेंट का मान गलत भी हो सकता है और नकारात्मक भी।


2
मेरे पास कोई जवाब नहीं है लेकिन मैं आपसे सहमत हूं। शायद इसे जेवीएम में बग माना जाए।
एरोन डिगुल्ला

2
वह पोस्ट गलत है और TSC का उपयोग धीमा नहीं है लेकिन आपको इसके साथ रहना है: Bugs.sun.com/bugdatabase/view_bug.do?bug_id=6440250 इसके अलावा TSC को हाइपरविजर के माध्यम से उपयोगी बनाया जा सकता है लेकिन यह फिर से धीमा है।
bestsss

1
और हां, आप एक वर्चुअल मशीन में चला सकते हैं जहां एक सीपीयू एक सत्र के माध्यम से मध्य-मार्ग दिखा सकता है: डी
लिमिटेड प्रायश्चित

जवाबों:


206

यह उत्तर 2011 में इस बात के दृष्टिकोण से लिखा गया था कि वास्तव में उस समय के ऑपरेटिंग सिस्टम पर चलने वाले समय का सूर्य JDK क्या करता है। वैसा बहुत समय पहले था! लेवेंटोव का जवाब एक अधिक अद्यतित परिप्रेक्ष्य प्रदान करता है।

वह पोस्ट गलत है, और nanoTimeसुरक्षित है। पोस्ट पर एक टिप्पणी है जो डेविड होम्स के एक ब्लॉग पोस्ट से लिंक करती है , जो सन में एक रियलटाइम और कंसीडर आदमी है। इसे कहते हैं:

System.nanoTime () QueryPerformanceCounter / QueryPerformanceFrequency API [...] का उपयोग करते हुए कार्यान्वित किया जाता है क्यूपीसी द्वारा उपयोग किया जाने वाला डिफ़ॉल्ट तंत्र हार्डवेयर एब्स्ट्रक्शन लेयर (एचएएल) द्वारा निर्धारित किया जाता है [...] यह डिफ़ॉल्ट परिवर्तन न केवल हार्डवेयर बल्कि ओएस पर भी होता है। संस्करणों। उदाहरण के लिए, Windows XP सर्विस पैक 2 ने प्रोसेसर टाइमस्टैम्प-काउंटर (TSC) के बजाय पावर मैनेजमेंट टाइमर (PMTimer) का उपयोग करने के लिए चीजों को बदल दिया क्योंकि TSC के साथ SMP सिस्टम में अलग-अलग प्रोसेसर पर सिंक्रनाइज़ नहीं होने के कारण समस्याएं हैं, और इस तथ्य के कारण आवृत्ति अलग-अलग हो सकते हैं (और इसलिए समय बीतने के साथ इसका संबंध) शक्ति-प्रबंधन सेटिंग्स के आधार पर।

इसलिए, विंडोज पर, यह WinXP SP2 तक एक समस्या थी , लेकिन यह अब नहीं है।

मैं अन्य प्लेटफ़ॉर्म के बारे में बात करने वाला एक भाग II (या अधिक) नहीं पा सकता हूं, लेकिन उस लेख में एक टिप्पणी शामिल है जिसमें लिनक्स ने उसी तरह से समस्या का सामना किया है और हल किया है, जिसमें FAQ के लिए एक लिंक क्लॉक_गेटटाइम (CLOCK_REALTIME) है , जो कहते हैं:

  1. क्या घड़ी_गेटाइम (CLOCK_REALTIME) सभी प्रोसेसर / कोर के पार है? (आर्च मैटर क्या है? उदाहरण पीपीसी, आर्म, x86, amd64, स्पार्क)।

इसे छोटी गाड़ी माना जाना चाहिए

हालाँकि, x86 / x86_64 पर, असंबद्ध या परिवर्तनशील freq TSCs समय असंगतियों को देखने के लिए संभव है। 2.4 गुठली वास्तव में इस के खिलाफ कोई सुरक्षा नहीं थी, और जल्दी से 2.6 गुठली भी यहाँ अच्छा नहीं किया। 2.6.18 तक और इसका पता लगाने के लिए तर्क बेहतर है और हम आम तौर पर एक सुरक्षित घड़ियों में वापस आ जाएंगे।

पीपीसी में हमेशा एक सिंक किया हुआ टाइमबेस होता है, इसलिए यह मुद्दा नहीं होना चाहिए।

इसलिए, यदि होम्स के लिंक को उस nanoTimeकॉल clock_gettime(CLOCK_REALTIME)को लगाने के रूप में पढ़ा जा सकता है , तो यह x86 पर कर्नेल 2.6.18 के रूप में सुरक्षित-ईश है, और हमेशा पावरपीसी (क्योंकि आईबीएम और मोटोरोला, इंटेल के विपरीत, वास्तव में माइक्रोप्रोसेसरों को डिज़ाइन करना जानते हैं)।

दुख की बात है कि स्‍पार्क या सोलारिस का कोई उल्‍लेख नहीं है। और निश्चित रूप से, हमें पता नहीं है कि आईबीएम जेवीएम क्या करते हैं। लेकिन आधुनिक विंडोज और लिनक्स पर सन जेवीएम को यह अधिकार मिलता है।

EDIT: यह उत्तर उन स्रोतों पर आधारित है जो यह उद्धृत करता है। लेकिन मुझे अभी भी चिंता है कि यह वास्तव में पूरी तरह से गलत हो सकता है। कुछ और अप-टू-डेट जानकारी वास्तव में मूल्यवान होगी। मैं अभी लिनक्स की घड़ियों के बारे में चार साल के नए लेख के लिंक पर आया था जो उपयोगी हो सकता है।


13
यहां तक ​​कि WinXP SP2 को नुकसान होता है। मूल कोड नमूने को चलाने के साथ, void foo() { Thread.sleep(40); }मुझे एक एकल Athlon 64 X2 4200+प्रोसेसर का उपयोग करके एक नकारात्मक समय (-380 एमएस!) मिला
ल्यूक उशरवुड

मुझे नहीं लगता कि इस पर अपडेट किया गया है, wrt। लिनक्स, बीएसडी या अन्य प्लेटफार्मों पर व्यवहार?
तोमर गाबेल

6
अच्छा जवाब, इस विषय के अधिक हाल के अन्वेषण के लिए एक लिंक जोड़ना चाहिए: shipilev.net/blog/2014/nanotrusting-nanotime
निट्सन वकार्ट

1
@SOFe: ओह, यह शर्म की बात है। यह सौभाग्य से वेब संग्रह में है। मैं देखूंगा कि क्या मैं एक मौजूदा संस्करण को ट्रैक कर सकता हूं।
टॉम एंडरसन

1
नोट: OpenJDK 8J192 OpenJDK तक कल्पना तक नहीं किया, बगसोपेनजडकJava.net/browse/JDK-8184271 देखें । OpenJDK 8, या OpenJDK 11+ के ताज़ा संस्करण का कम से कम उपयोग करना सुनिश्चित करें।
लेवेंटोव

35

मैंने थोड़ी खोज की और पाया कि यदि किसी को पांडित्य हो रहा है तो हाँ इसे बेकार माना जा सकता है ... विशेष स्थितियों में ... यह इस बात पर निर्भर करता है कि आपकी आवश्यकताएं कितनी संवेदनशील हैं ...

की जाँच करें इस उद्धरण जावा सूर्य साइट से:

वास्तविक समय की घड़ी और System.nanoTime () दोनों एक ही सिस्टम कॉल और इस प्रकार एक ही घड़ी पर आधारित हैं।

जावा आरटीएस के साथ, सभी समय-आधारित एपीआई (उदाहरण के लिए, टाइमर, आवधिक धागे, समय सीमा की निगरानी और आगे) उच्च-रिज़ॉल्यूशन टाइमर पर आधारित हैं। और, वास्तविक समय की प्राथमिकताओं के साथ, वे यह सुनिश्चित कर सकते हैं कि वास्तविक समय की बाधाओं के लिए उपयुक्त कोड को सही समय पर निष्पादित किया जाएगा। इसके विपरीत, साधारण जावा एसई एपीआई उच्च-रिज़ॉल्यूशन समय को संभालने में सक्षम कुछ तरीकों की पेशकश करते हैं, जिसमें किसी निश्चित समय पर निष्पादन की कोई गारंटी नहीं होती है। अलग-अलग समय मापन करने के लिए कोड में विभिन्न बिंदुओं के बीच System.nanoTime () का उपयोग करना हमेशा सटीक होना चाहिए।

जावा में नैनो टाइम () विधि के लिए एक चेतावनी भी है :

इस पद्धति का उपयोग केवल बीते हुए समय को मापने के लिए किया जा सकता है और सिस्टम या दीवार-घड़ी के समय की किसी अन्य धारणा से संबंधित नहीं है। लौटाया गया मान कुछ निश्चित लेकिन मनमाने समय (शायद भविष्य में नकारात्मक हो सकता है) के बाद से नैनोसेकंड का प्रतिनिधित्व करता है। यह विधि नैनोसेकंड सटीकता प्रदान करती है, लेकिन जरूरी नहीं कि नैनोसेकंड सटीकता। मान कितनी बार बदलते हैं, इसकी कोई गारंटी नहीं है। क्रमिक कॉल में अंतर जो लगभग 292.3 वर्ष (2 63 नैनोसेकंड) से अधिक है, संख्यात्मक अतिप्रवाह के कारण बीते हुए समय की सही गणना नहीं करेंगे।

ऐसा लगता है कि केवल निष्कर्ष निकाला जा सकता है कि नैनो टाइम () को एक सटीक मान के रूप में भरोसा नहीं किया जा सकता है। जैसे, यदि आपको अलग-अलग समय को मापने की आवश्यकता नहीं है जो केवल नैनो सेकंड अलग हैं तो यह विधि पर्याप्त है, भले ही परिणामी वापसी मान नकारात्मक हो। हालाँकि, यदि आपको उच्च परिशुद्धता की आवश्यकता है, तो वे अनुशंसा करते हैं कि आप JAVA RTS का उपयोग करें।

तो अपने प्रश्न का उत्तर देने के लिए ... कोई नैनो टाइम () बेकार नहीं है .... इसका हर स्थिति में उपयोग करने का सबसे विवेकपूर्ण तरीका नहीं है।


3
> यह विधि काफी अच्छी है, भले ही परिणामी रिटर्न नकारात्मक हो। मुझे यह नहीं मिलता है, अगर टाइम्स में मान नकारात्मक है, तो यह फू () में लिया गया समय मापने में कैसे उपयोगी है?
pdeva

3
यह ठीक है क्योंकि आप सभी के बारे में चिंतित हैं अंतर का पूर्ण मूल्य है। यदि आपका माप समय टी है जहां t = t2 - t1 है तो आप जानना चाहते हैं। t | .... तो क्या होगा यदि मान ऋणात्मक है ... मल्टी कोर समस्या के साथ भी प्रभाव शायद ही कुछ होने वाला है। वैसे भी नैनोसेकंड।
mezoid

3
@Aaron का बैकअप लेने के लिए: t2 और t1 दोनों नकारात्मक हो सकते हैं लेकिन (t2-t1) नकारात्मक नहीं होना चाहिए।
jfs

2
aaron: कि वास्तव में मेरी बात क्या है। t2-t1 कभी भी नकारात्मक नहीं होना चाहिए अन्यथा हमारे पास बग है।
pdeva

12
@pdeva - लेकिन आप गलत समझ रहे हैं कि डॉक्टर क्या कहते हैं। आप एक गैर-मुद्दा उठा रहे हैं। समय का कुछ बिंदु है जिसे "0" माना जाता है। नैनो टाइम () द्वारा लौटाए गए मान उस समय के सापेक्ष सटीक हैं। इसकी एक नीरस रूप से समयरेखा बढ़ रही है। आपको उस समय के नकारात्मक भाग से संख्याओं की एक श्रृंखला प्राप्त हो सकती है। -100, -99, -98(व्यवहार में स्पष्ट रूप से बहुत बड़ा मान)। वे सही दिशा में (बढ़ते) जा रहे हैं, इसलिए यहां कोई मुद्दा नहीं है।
ToolmakerSteve

18

बहस की जरूरत नहीं है, बस स्रोत का उपयोग करें। यहाँ, लिनक्स के लिए एसई 6, अपने स्वयं के निष्कर्ष बनाएं:

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;
  }
}

7
यह तभी उपयोगी है जब आप जानते हैं कि उपयोग किया गया एपीआई क्या करता है। प्रयुक्त एपीआई ऑपरेटिंग सिस्टम द्वारा कार्यान्वित किया जाता है; यह कोड सही wrt है। उपयोग किए गए एपीआई की विशिष्टता (घड़ी_गेटटाइम / गेटटाइमऑफडे), लेकिन जैसा कि अन्य ने बताया, कुछ गैर-अप-टू-डेट ऑपरेटिंग सिस्टमों में छोटी गाड़ी के कार्यान्वयन हैं।
ब्लेसरब्लैड

18

जावा 7 के बाद से, System.nanoTime()JDK विनिर्देश द्वारा सुरक्षित होने की गारंटी है। System.nanoTime()जावदोक यह स्पष्ट करता है कि एक JVM (जो सभी थ्रेड्स में है) के भीतर सभी अवलोकन किए गए इनवोकेशन हैं:

लौटाया गया मान कुछ निश्चित लेकिन मनमाना मूल समय (शायद भविष्य में, इसलिए मान नकारात्मक हो सकता है) के बाद से नैनोसेकंड का प्रतिनिधित्व करता है। जावा वर्चुअल मशीन की आवृत्ति में इस पद्धति के सभी इनवोकेशन द्वारा एक ही मूल का उपयोग किया जाता है; अन्य वर्चुअल मशीन इंस्टेंस एक अलग मूल का उपयोग करने की संभावना है।

JVM / JDK कार्यान्वयन उन विसंगतियों को दूर करने के लिए ज़िम्मेदार है, जो तब देखी जा सकती हैं जब अंतर्निहित OS उपयोगिताओं को बुलाया जाता है (जैसे कि टॉम एंडरसन के उत्तर में उल्लिखित )।

इस प्रश्न के अन्य पुराने उत्तर (2009-2012 में लिखे गए) के अधिकांश भाग FUD व्यक्त करते हैं जो संभवतः जावा 5 या जावा 6 के लिए प्रासंगिक थे, लेकिन अब जावा के आधुनिक संस्करणों के लिए प्रासंगिक नहीं हैं।

हालांकि, यह ध्यान देने योग्य है कि JDK की nanoTime()सुरक्षा की गारंटी के बावजूद , OpenJDK में कई कीड़े हैं जो कुछ प्लेटफार्मों पर या कुछ परिस्थितियों में इस गारंटी को बरकरार नहीं रखते हैं (जैसे JDK-8040140 , JDK-8184271 )। nanoTime()इस समय OpenJDK wrt में कोई खुला (ज्ञात) बग नहीं है , लेकिन OpenJDK की एक नई रिलीज में इस तरह के एक बग या एक प्रतिगमन की खोज किसी को भी झटका नहीं देना चाहिए।

इसे ध्यान में रखते हुए, समयबद्ध अवरोधन, अंतराल प्रतीक्षा, टाइमआउट आदि के लिए उपयोग किए जाने वाले कोड को nanoTime()अपवादों को फेंकने के बजाय शून्य काल के रूप में नकारात्मक समय के अंतर (टाइमआउट) का व्यवहार करना चाहिए। इस अभ्यास भी पसंद किया जाता है क्योंकि यह में सभी वर्गों में सभी समय इंतजार तरीकों के व्यवहार के साथ संगत है java.util.concurrent.*, उदाहरण के लिए Semaphore.tryAcquire(), Lock.tryLock(), BlockingQueue.poll(), आदि

फिर भी, nanoTime()समयबद्ध अवरोधन, अंतराल प्रतीक्षा, टाइमआउट इत्यादि को लागू करने के लिए अभी भी पसंद किया जाना चाहिए currentTimeMillis()क्योंकि उत्तरार्द्ध "समय जा रहा है पिछड़े" घटना के लिए एक विषय है (उदाहरण के लिए सर्वर समय सुधार), यानी currentTimeMillis()समय अंतराल को मापने के लिए उपयुक्त नहीं है बिल्कुल भी। अधिक जानकारी के लिए यह उत्तर देखें ।

nanoTime()सीधे कोड निष्पादन समय माप के लिए उपयोग करने के बजाय , विशेष बेंचमार्किंग फ्रेमवर्क और प्रोफाइलर्स को अधिमानतः उपयोग किया जाना चाहिए, उदाहरण के लिए दीवार-घड़ी प्रोफाइलिंग मोड में जेएमएच और एसिंक्स -प्रोफाइलर


10

अस्वीकरण: मैं इस पुस्तकालय का विकासक हूं

आपको यह बेहतर लग सकता है:

http://juliusdavies.ca/nanotime/

लेकिन यह एक DLL या Unix .so (साझा ऑब्जेक्ट) फ़ाइल को वर्तमान उपयोगकर्ता के होम डायरेक्टरी में कॉपी करता है ताकि इसे JNI कह सकें।

कुछ पृष्ठभूमि की जानकारी मेरी साइट पर है:

http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html


@ जूलियस क्या आपने अपनी साइट से लाइब्रेरी को हटा दिया है?
नितिन डंडरियाल

6

सीपीयू के बीच विसंगतियों के लिए लिनक्स सही है, लेकिन विंडोज नहीं करता है। मेरा सुझाव है कि आप मान लें। System.nanoTime () केवल 1 माइक्रो-सेकंड के आसपास ही सटीक है। एक लंबा समय प्राप्त करने का एक सरल तरीका फू () को 1000 या अधिक बार कॉल करना और समय को 1000 से विभाजित करना है।


2
क्या आप एक संदर्भ (लिनक्स और विंडोज पर व्यवहार) प्रदान कर सकते हैं?
17

दुर्भाग्य से प्रस्तावित विधि आम तौर पर अत्यधिक अप्रचलित होगी क्योंकि प्रत्येक घटना +/- 100ms की दीवार घड़ी अपडेट स्लॉट में गिरने से अक्सर उप-सेकंड संचालन के लिए शून्य वापस आ जाएगी। शून्य की अवधि के साथ प्रत्येक 9 संचालन का योग है, अच्छी तरह से, शून्य, नौ से विभाजित है ... शून्य। इसके विपरीत, System.nanoTime () का उपयोग करके अपेक्षाकृत सटीक (गैर-शून्य) ईवेंट अवधि प्रदान करेगा, जो तब घटनाओं की संख्या से विभाजित और विभाजित होता है जो एक अत्यधिक सटीक औसत प्रदान करेगा।
डेरेल टीग

@DarrellTeague में 1000 ईवेंट सम्‍मिलित हैं और उन्हें जोड़ना समय-समय पर समाप्ति के समान है।
पीटर लॉरी

अधिकांश प्रणालियों पर @DarrellTeague System.nanoTime () 1 माइक्रो-सेकंड या बेहतर (100,000 माइक्रोसेकंड नहीं) के लिए सटीक है। कई ऑपरेशनों का लाभ उठाना तब ही प्रासंगिक होता है जब आप कुछ माइक्रो-सेकंड्स में उतरते हैं, और केवल कुछ प्रणालियों पर।
पीटर लॉरी

1
क्षमायाचना क्योंकि "संक्षेप" घटनाओं में प्रयुक्त भाषा के बारे में कुछ भ्रम था। हां, यदि 1000 उप-सेकंड के संचालन की शुरुआत के समय को चिह्नित किया जाता है, तो वे चलते हैं और फिर समय को फिर से अंत में चिह्नित किया जाता है और विभाजित किया जाता है - जो कि विकास के तहत कुछ प्रणाली के लिए काम करेगा एक दिए गए अवधि के लिए एक अच्छा सन्निकटन प्राप्त करने के लिए। प्रतिस्पर्धा।
डेरेल टीग

5

बिल्कुल बेकार नहीं। टाइमिंग aficionados मल्टी-कोर समस्या को सही ढंग से इंगित करता है, लेकिन वास्तविक-शब्द अनुप्रयोगों में यह अक्सर मौलिक रूप से वर्तमान समय की तुलना में बेहतर है ()।

फ्रेम रिफ्रेश में ग्राफिक्स पोजीशन की गणना करते समय नैनो टाइम () मेरे प्रोग्राम में बहुत चिकनी गति की ओर जाता है।

और मैं केवल मल्टी-कोर मशीनों पर परीक्षण करता हूं।


5

मैंने System.nanoTime () के उपयोग से रिपोर्ट किए गए नकारात्मक समय को देखा है । स्पष्ट होने के लिए, प्रश्न में कोड है:

    long startNanos = System.nanoTime();

    Object returnValue = joinPoint.proceed();

    long elapsedNanos = System.nanoTime() - startNanos;

और वैरिएबल 'बीता हुआ' नैनो का नकारात्मक मान था। (मैं सकारात्मक हूं कि इंटरमीडिएट कॉल में 293 साल से भी कम समय लगा, जो कि लंबे समय तक संग्रहीत नैनो के लिए अतिप्रवाह बिंदु है :)

यह आईबीएम P690 (मल्टी-कोर) हार्डवेयर AIX पर आईबीएम v1.5 JRE 64 बिट का उपयोग करके हुआ। मैंने केवल एक बार यह त्रुटि देखी है, इसलिए यह अत्यंत दुर्लभ प्रतीत होता है। मुझे इसका कारण नहीं पता है - क्या यह हार्डवेयर-विशिष्ट समस्या है, जेवीएम दोष - मुझे नहीं पता। मैं भी नैनो () की सटीकता के लिए निहितार्थ नहीं जानता हूं।

मूल प्रश्न का उत्तर देने के लिए, मुझे नहीं लगता कि नैनो टाइम बेकार है - यह उप-मिलीसेकंड समय प्रदान करता है, लेकिन इसमें एक वास्तविक (सिर्फ सैद्धांतिक नहीं) जोखिम है जो गलत है जिसे आपको ध्यान में रखना चाहिए।


काश, कुछ OS / हार्डवेयर समस्या प्रतीत होती है। प्रलेखन में कहा गया है कि मुख्य मूल्य नकारात्मक हो सकते हैं लेकिन (बड़े ऋणात्मक ऋणात्मक छोटे ऋणात्मक) अभी भी सकारात्मक मूल्य होना चाहिए। वास्तव में धारणा यह है कि एक ही धागे में, नैनो टाइम () कॉल को हमेशा सकारात्मक या नकारात्मक मान वापस करना चाहिए। कई वर्षों से विभिन्न यूनिक्स और विंडोज सिस्टम पर इसे कभी नहीं देखा गया है, लेकिन विशेष रूप से संभव है कि अगर हार्डवेयर / ओएस प्रोसेसर में इस प्रतीत होता है कि परमाणु ऑपरेशन को विभाजित कर रहे हैं।
डेरेल टीग

@BasilVandegriend यह एक बग कहीं भी नहीं है। दस्तावेज़ीकरण के अनुसार, शायद ही कभी आपके उदाहरण में दूसरा System.nanoTime () एक अलग CPU पर चल सकता है और उस CPU पर गणना की गई नैनोटाइम मान केवल CPU पर गणना किए गए मानों से कम हो सकती है। तो, बीते समय के लिए ave मान संभव है
अंतहीन

2

ऐसा प्रतीत नहीं होता है कि Windows XP और JRE 1.5.0_06 चलने वाले Core 2 Duo पर कोई समस्या है।

तीन धागे के साथ एक परीक्षण में मैं System.nanoTime () को पीछे की ओर नहीं देखता। प्रोसेसर दोनों व्यस्त हैं, और थ्रेड्स कभी-कभी सो जाते हैं ताकि आसपास के धागे को उत्तेजित किया जा सके।

[संपादित करें] मुझे लगता है कि यह केवल शारीरिक रूप से अलग-अलग प्रोसेसर पर होता है, यानी कि काउंटर एक ही मरने पर कई कोर के लिए सिंक्रनाइज़ किए जाते हैं।


2
यह शायद हर समय नहीं होगा, लेकिन जिस तरह से नैनोटाइम () लागू होने के कारण संभावना हमेशा रहती है।
pdeva

मुझे लगता है कि यह केवल शारीरिक रूप से अलग-अलग प्रोसेसर पर होता है, अर्थात काउंटरर्स को एक ही मरने पर कई कोर के लिए सिंक्रनाइज़ किया जाता है।
स्टारब्लू

यहां तक ​​कि विशिष्ट कार्यान्वयन पर निर्भर करता है, IIRC। लेकिन यह कुछ ऐसा है जिस पर ओएस को ध्यान रखना चाहिए।
ब्लेसरॉब्लेड

1
एक ही x 86 प्रोसेसर के कई कोर पर आरडीटीसीटी काउंटरों को आवश्यक रूप से सिंक्रनाइज़ नहीं किया जाता है - कुछ आधुनिक सिस्टम अलग-अलग कोर को अलग-अलग गति से चलाते हैं।
जूल्स

2

नहीं, यह नहीं है ... यह सिर्फ आपके सीपीयू पर निर्भर करता है, उच्च परिशुद्धता घटना टाइमर की जांच करें कि कैसे / क्यों चीजों को सीपीयू के अनुसार अलग-अलग व्यवहार किया जाता है।

मूल रूप से, अपने जावा के स्रोत को पढ़ें और जांचें कि आपका संस्करण फ़ंक्शन के साथ क्या करता है, और यदि यह सीपीयू के खिलाफ काम करता है तो आप इसे चालू करेंगे।

आईबीएम आपको यह भी सुझाव देता है कि आप इसे प्रदर्शन बेंचमार्किंग (2008 की पोस्ट, लेकिन अद्यतन) के लिए उपयोग करें।


के रूप में सभी कार्यान्वयन bahaviour परिभाषित, "चेतावनी emptor!"
डेविड श्मिट

2

मैं इस बात से जोड़ रहा हूं कि अनिवार्य रूप से वही चर्चा है जहां पीटर लॉरी एक अच्छा जवाब दे रहा है। मुझे System.nanoTime () का उपयोग करते हुए एक नकारात्मक समय क्यों मिलता है?

कई लोगों ने उल्लेख किया कि Java System.nanoTime () में नकारात्मक समय लौट सकता है। मैं अन्य लोगों द्वारा पहले ही कही गई बातों को दोहराने के लिए माफी माँगता हूँ।

  1. नैनो टाइम () एक घड़ी नहीं बल्कि सीपीयू साइकिल काउंटर है।
  2. रिटर्न वैल्यू को समय की तरह देखने के लिए आवृत्ति से विभाजित किया जाता है।
  3. सीपीयू फ्रीक्वेंसी में उतार-चढ़ाव हो सकता है।
  4. जब आपका धागा किसी अन्य सीपीयू पर निर्धारित होता है, तो नैनो टाइम () प्राप्त करने का मौका होता है, जिसके परिणामस्वरूप नकारात्मक अंतर होता है। यह तार्किक है। सीपीयू में काउंटरों को सिंक्रनाइज़ नहीं किया जाता है।
  5. कई मामलों में, आप काफी भ्रामक परिणाम प्राप्त कर सकते हैं, लेकिन आप यह नहीं बता पाएंगे क्योंकि डेल्टा नकारात्मक नहीं है। इसके बारे में सोचो।
  6. (अपुष्ट) मुझे लगता है कि यदि निर्देश पुन: व्यवस्थित किए जाते हैं तो आप उसी सीपीयू पर भी नकारात्मक परिणाम प्राप्त कर सकते हैं। इसे रोकने के लिए, आपको अपने निर्देशों को क्रमबद्ध करते हुए एक मेमोरी बैरियर लगाना होगा।

यह शांत हो जाएगा अगर System.nanoTime () ने इसे निष्पादित किया है, जहां मूल राशि लौटा दी है।


1
3. और 5. को छोड़कर सभी बिंदु गलत हैं। 1. नैनो टाइम () सीपीयू साइकिल काउंटर नहीं है, यह नैनो टाइम है । 2. नैनो-टाइम का उत्पादन कैसे किया जाता है, यह प्लेटफॉर्म-विशिष्ट है। 4. नहीं, अंतर नैनो () कल्पना के अनुसार नकारात्मक नहीं हो सकता। OpenJDK के अनुसार बग्स wrt nanoTime () नहीं है, और इस समय कोई ज्ञात अनसुलझे कीड़े नहीं हैं। 6. नैनो टाइम कॉल्स को एक थ्रेड के भीतर फिर से रिकॉर्ड नहीं किया जा सकता क्योंकि यह एक देशी तरीका है और जेवीएम प्रोग्राम ऑर्डर का सम्मान करता है। जेवीएम ने कभी भी देशी तरीके की कॉल को फिर से शुरू नहीं किया क्योंकि यह नहीं जानता कि उनके अंदर क्या होता है और इसलिए यह साबित नहीं किया जा सकता है कि इस तरह के रिऑर्डिंग्स सुरक्षित होंगे।
लेवेंटोव

5. नैनोटाइम () अंतर परिणामों के संबंध में वास्तव में भ्रामक हो सकता है, लेकिन इस asnwer में अन्य बिंदुओं में प्रस्तुत कारणों के लिए नहीं। बल्कि यहाँ प्रस्तुत कारणों के लिए: shipilev.net/blog/2014/nanotrusting-nanotime
leventov

विडंबना यह है कि 6. के बारे में विशेष रूप से reorderings के कारण OpenJDK में एक बग हो गया था: Bugs.openjdk.java.net/browse/JDK-8184271 । OpenJDK में, नैनोटाइम () एक आंतरिक है और इसे फिर से चालू करने की अनुमति दी गई थी, यह एक बग था।
लेवेंटोव

@leventov, तो nanotime () का उपयोग करने के लिए सुरक्षित है? अर्थ, यह नकारात्मक मूल्यों को वापस नहीं कर सकता है और यह समय के अनुसार ~ सटीक है। मैं एक एपीआई फ़ंक्शन को उजागर करने का बिंदु नहीं देखता हूं जो मुद्दों से भरा हुआ है। यह पोस्ट एक प्रमाण है, जो 2009 में शुरू हुआ था और अभी भी 2019 में टिप्पणी की गई है। मिशन के महत्वपूर्ण सामान के लिए, मैं कल्पना करता हूं कि लोग टाइम कार्ड पर सिमेट्रिकॉम जैसे भरोसा करते हैं
भंवर

1
आपका # 4 नकारात्मक अंतर के बारे में कहता है , मूल्यों के बारे में नहीं: "नैनो टाइम () प्राप्त करने का एक मौका होता है जिसके परिणामस्वरूप नकारात्मक अंतर होता है।"
लेवेंटोव

1

Java crossplatform है और नैनो टाइम प्लेटफॉर्म पर निर्भर है। यदि आप जावा का उपयोग करते हैं - जब नैनो टाइम का उपयोग नहीं करते हैं। मुझे इस फ़ंक्शन के साथ अलग-अलग jvm कार्यान्वयन में वास्तविक बग मिले।


0

जावा 5 प्रलेखन भी इसी उद्देश्य के लिए इस पद्धति का उपयोग करने की सिफारिश करता है।

इस पद्धति का उपयोग केवल बीते हुए समय को मापने के लिए किया जा सकता है और सिस्टम या दीवार-घड़ी के समय की किसी अन्य धारणा से संबंधित नहीं है।

जावा 5 एपीआई डॉक्टर


0

इसके अलावा, System.currentTimeMillies()जब आप अपने सिस्टम की घड़ी को बदलते हैं, तो System.nanoTime()ऐसा नहीं होता है, इसलिए उत्तरार्द्ध अवधि को मापने के लिए सुरक्षित है।


-3

nanoTimeसमय के लिए बेहद असुरक्षित है। मैंने इसे अपने बुनियादी मौलिकता के परीक्षण एल्गोरिदम पर आज़माया और इसने उत्तर दिए जो शाब्दिक रूप से एक ही इनपुट के लिए एक सेकंड थे। उस हास्यास्पद विधि का उपयोग न करें। मुझे कुछ ऐसा चाहिए, जो समय मिलिस से अधिक सटीक और सटीक हो, लेकिन उतना बुरा नहीं nanoTime


एक स्रोत या एक बेहतर व्याख्या के बिना यह टिप्पणी बेकार है
ic3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.