Là System.nanoTime () hoàn toàn vô dụng?


153

Như tài liệu trong bài đăng trên blog Cảnh giác với System.nanoTime () trong Java , trên các hệ thống x86, System.nanoTime () của Java trả về giá trị thời gian bằng cách sử dụng bộ đếm cụ thể của CPU . Bây giờ hãy xem xét trường hợp sau đây tôi sử dụng để đo thời gian của một cuộc gọi:

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

Bây giờ trong một hệ thống đa lõi, có thể là sau khi đo thời gian1, luồng được lên lịch tới một bộ xử lý khác có bộ đếm nhỏ hơn CPU trước đó. Do đó, chúng ta có thể nhận được một giá trị trong time2 nhỏ hơn time1. Do đó, chúng tôi sẽ nhận được một giá trị âm trong timeSpent.

Xem xét trường hợp này, phải chăng System.nanotime bây giờ khá vô dụng?

Tôi biết rằng việc thay đổi thời gian hệ thống không ảnh hưởng đến nano. Đó không phải là vấn đề tôi mô tả ở trên. Vấn đề là mỗi CPU sẽ giữ một bộ đếm khác nhau kể từ khi nó được bật. Bộ đếm này có thể thấp hơn trên CPU thứ hai so với CPU thứ nhất. Vì luồng có thể được HĐH lên lịch tới CPU thứ hai sau khi nhận time1, giá trị của timeSpent có thể không chính xác và thậm chí âm.


2
Tôi không có câu trả lời nhưng tôi đồng ý với bạn. Có lẽ nó nên được coi là một lỗi trong JVM.
Aaron Digulla

2
bài đăng đó không chính xác và không sử dụng TSC thì chậm nhưng bạn phải sống với: bug.sun.com/bugdatabase/view_orms.do?orms_id=6440250 Ngoài ra TSC có thể được sử dụng thông qua hypanneror nhưng sau đó nó lại chậm.
bestsss

1
Và tất nhiên, bạn có thể chạy trong một máy ảo trong đó CPU có thể hiển thị giữa chừng thông qua một phiên: D
Giới hạn trong

Câu trả lời:


206

Câu trả lời này được viết vào năm 2011 theo quan điểm của Sun JDK thời đó chạy trên các hệ điều hành thời đó thực sự đã làm gì. Đó là một thời gian dài trước đây! Câu trả lời của leventov cung cấp một viễn cảnh cập nhật hơn.

Bài đăng đó là sai, và nanoTimean toàn. Có một bình luận về bài đăng liên kết đến một bài đăng trên blog của David Holmes , một anh chàng thời gian thực và đồng thời tại Sun. Nó nói rằng:

System.nanoTime () được triển khai bằng API QueryPerformanceCorer / QueryPerformanceFrequency [...] Cơ chế mặc định được QPC sử dụng được xác định bởi lớp Trừu tượng phần cứng (HAL) [...] Mặc định này thay đổi không chỉ trên phần cứng mà còn trên cả hệ điều hành phiên bản. Ví dụ: Windows XP Service Pack 2 đã thay đổi mọi thứ để sử dụng bộ hẹn giờ quản lý năng lượng (PMTimer) thay vì bộ đếm thời gian của bộ xử lý (TSC) do các vấn đề với TSC không được đồng bộ hóa trên các bộ xử lý khác nhau trong các hệ thống SMP và do thực tế tần số của nó có thể thay đổi (và do đó mối quan hệ của nó với thời gian trôi qua) dựa trên các cài đặt quản lý năng lượng.

Vì vậy, trên Windows, đây một vấn đề cho đến WinXP SP2, nhưng bây giờ thì không.

Tôi không thể tìm thấy phần II (hoặc nhiều hơn) nói về các nền tảng khác, nhưng bài viết đó bao gồm một nhận xét mà Linux đã gặp phải và giải quyết vấn đề tương tự theo cách tương tự, với liên kết đến Câu hỏi thường gặp cho clock_gettime (CLOCK_REALTIME) , mà nói:

  1. Clock_gettime (CLOCK_REALTIME) có nhất quán trên tất cả các bộ xử lý / lõi không? (Có vấn đề vòm không? Ví dụ: ppc, arm, x86, amd64, sparc).

nên hoặc nó được coi là lỗi.

Tuy nhiên, trên x86 / x86_64, có thể thấy các TSC freq không đồng bộ hoặc biến đổi gây ra sự không nhất quán về thời gian. Hạt nhân 2,4 thực sự không có sự bảo vệ chống lại điều này, và hạt nhân 2,6 đầu cũng không làm quá tốt ở đây. Kể từ 2.6,18 trở lên logic để phát hiện điều này là tốt hơn và chúng ta thường sẽ quay trở lại với nguồn đồng hồ an toàn.

ppc luôn có một cơ sở thời gian được đồng bộ hóa, vì vậy đó không phải là một vấn đề.

Vì vậy, nếu liên kết của Holmes có thể được đọc là ngụ ý nanoTimecác cuộc gọi clock_gettime(CLOCK_REALTIME)đó, thì đó là sự an toàn của kernel 2.6.18 trên x86 và luôn luôn trên PowerPC (vì IBM và Motorola, không giống như Intel, thực sự biết cách thiết kế bộ vi xử lý).

Đáng buồn thay, không có đề cập đến SPARC hay Solaris. Và tất nhiên, chúng tôi không biết IBM JVM làm gì. Nhưng Sun JVM trên Windows và Linux hiện đại đã hiểu điều này.

EDIT: Câu trả lời này dựa trên các nguồn mà nó trích dẫn. Nhưng tôi vẫn lo lắng rằng nó thực sự có thể sai hoàn toàn. Một số thông tin cập nhật hơn sẽ thực sự có giá trị. Tôi vừa bắt gặp một liên kết đến một bài báo mới hơn bốn năm về đồng hồ của Linux có thể hữu ích.


13
Ngay cả WinXP SP2 cũng bị ảnh hưởng. Chạy mẫu mã ban đầu, void foo() { Thread.sleep(40); }tôi có thời gian âm (-380 ms!) Bằng một Athlon 64 X2 4200+bộ xử lý duy nhất
Luke Usherwood

Tôi không cho rằng có cập nhật về điều này, wrt. hành vi trên Linux, BSD hoặc các nền tảng khác?
Tomer Gabel 11/12/13

6
Câu trả lời hay, nên thêm một liên kết đến khám phá gần đây hơn về chủ đề này: shipilev.net/blog/2014/nanotrusting-nanotime
Nitsan Wakart 10/03/2015

1
@SOFe: Ồ, thật là xấu hổ. Đó là trong kho lưu trữ web , may mắn thay. Tôi sẽ xem nếu tôi có thể theo dõi một phiên bản hiện tại.
Tom Anderson

1
Lưu ý: OpenJDK không duy trì thông số kỹ thuật cho đến khi OpenJDK 8u192, xem bug.openjdk.java.net/browse/JDK-8184271 . Đảm bảo sử dụng ít nhất là phiên bản mới của OpenJDK 8 hoặc OpenJDK 11+.
leventov

35

Tôi đã thực hiện một chút tìm kiếm và thấy rằng nếu một người đang bị phạm tội thì có thể nó được coi là vô dụng ... trong các tình huống cụ thể ... nó phụ thuộc vào mức độ nhạy cảm của các yêu cầu của bạn ...

Kiểm tra trích dẫn này từ trang web Java Sun:

Đồng hồ thời gian thực và System.nanoTime () đều dựa trên cùng một cuộc gọi hệ thống và do đó cùng một đồng hồ.

Với Java RTS, tất cả các API dựa trên thời gian (ví dụ: Bộ hẹn giờ, Chủ đề định kỳ, Giám sát thời hạn, v.v.) đều dựa trên bộ định thời có độ phân giải cao. Và, cùng với các ưu tiên thời gian thực, họ có thể đảm bảo rằng mã phù hợp sẽ được thực thi vào đúng thời điểm cho các ràng buộc thời gian thực. Ngược lại, các API Java SE thông thường chỉ cung cấp một vài phương thức có khả năng xử lý thời gian có độ phân giải cao, không đảm bảo thực thi tại một thời điểm nhất định. Sử dụng System.nanoTime () giữa các điểm khác nhau trong mã để thực hiện các phép đo thời gian đã trôi qua phải luôn chính xác.

Java cũng có một cảnh báo cho phương thức nanoTime () :

Phương pháp này chỉ có thể được sử dụng để đo thời gian trôi qua và không liên quan đến bất kỳ khái niệm nào khác về thời gian hệ thống hoặc đồng hồ treo tường. Giá trị được trả về đại diện cho nano giây do một số thời gian cố định nhưng tùy ý (có thể trong tương lai, vì vậy giá trị có thể âm). Phương pháp này cung cấp độ chính xác nano giây, nhưng không nhất thiết là độ chính xác nano giây. Không có đảm bảo nào được thực hiện về tần suất thay đổi giá trị. Sự khác biệt trong các cuộc gọi liên tiếp kéo dài hơn khoảng 292,3 năm (2 63 nano giây) sẽ không tính toán chính xác thời gian đã trôi qua do tràn số.

Dường như kết luận duy nhất có thể được rút ra là nanoTime () không thể dựa vào như một giá trị chính xác. Như vậy, nếu bạn không cần đo thời gian chỉ cách nhau nano giây thì phương pháp này đủ tốt ngay cả khi giá trị trả về kết quả là âm. Tuy nhiên, nếu bạn cần độ chính xác cao hơn, họ dường như khuyên bạn nên sử dụng JAVA RTS.

Vì vậy, để trả lời câu hỏi của bạn ... không có nanoTime () không vô dụng .... nó chỉ không phải là phương pháp khôn ngoan nhất để sử dụng trong mọi tình huống.


3
> phương pháp này đủ tốt ngay cả khi giá trị trả về kết quả là âm. Tôi không nhận được điều này, nếu giá trị trong timespent là âm, thì nó hữu ích như thế nào trong việc đo thời gian thực hiện trong foo ()?
pdeva

3
Không sao vì tất cả những gì bạn lo lắng là giá trị tuyệt đối của sự khác biệt. tức là nếu phép đo của bạn là thời gian t trong đó t = t2 - t1 thì bạn muốn biết | t | .... vậy nếu giá trị là âm ... thì ngay cả với vấn đề đa lõi, tác động hiếm khi xảy ra nano giây nào.
mezoid

3
Để sao lưu @Aaron: cả t2 và t1 có thể âm nhưng (t2-t1) không được âm.
jfs

2
aaron: đó chính xác là quan điểm của tôi. t2-t1 không bao giờ nên âm nếu không chúng tôi có lỗi.
pdeva

12
@pdeva - nhưng bạn đang hiểu nhầm những gì tài liệu nói. Bạn đang đưa ra một vấn đề không. Có một số thời điểm được coi là "0". Các giá trị được trả về bởi nanoTime () chính xác so với thời điểm đó. Đó là một dòng thời gian tăng đơn điệu. Bạn chỉ có thể nhận được một loạt các số từ phần âm của dòng thời gian đó. -100, -99, -98(Giá trị rõ ràng là lớn hơn rất nhiều trong thực tế). Họ đang đi đúng hướng (tăng), vì vậy không có vấn đề gì ở đây.
ToolmakerSteve

18

Không cần phải tranh luận, chỉ cần sử dụng nguồn. Ở đây, SE 6 cho Linux, đưa ra kết luận của riêng bạn:

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
Điều đó chỉ hữu ích nếu bạn biết API đã sử dụng làm gì. API được sử dụng được triển khai bởi hệ điều hành; mã này là đúng wrt. đặc tả của API được sử dụng (clock_gettime / gettimeofday), nhưng như những người khác đã chỉ ra, một số hệ điều hành không cập nhật có lỗi triển khai.
Blaisorblade

18

Kể từ Java 7, System.nanoTime()được đảm bảo an toàn bởi đặc tả JDK. System.nanoTime()Javadoc cho thấy rõ rằng tất cả các yêu cầu được quan sát trong một JVM (nghĩa là trên tất cả các luồng) đều đơn điệu:

Giá trị được trả về đại diện cho nano giây do một số thời gian gốc cố định nhưng tùy ý (có thể trong tương lai, vì vậy giá trị có thể âm). Cùng một nguồn gốc được sử dụng bởi tất cả các yêu cầu của phương thức này trong một thể hiện của máy ảo Java; các trường hợp máy ảo khác có thể sử dụng một nguồn gốc khác.

Việc triển khai JVM / JDK chịu trách nhiệm loại bỏ những mâu thuẫn có thể quan sát được khi các tiện ích hệ điều hành cơ bản được gọi (ví dụ: những tiện ích được đề cập trong câu trả lời của Tom Anderson ).

Phần lớn các câu trả lời cũ khác cho câu hỏi này (được viết vào năm 2009 2015) thể hiện FUD có thể phù hợp với Java 5 hoặc Java 6 nhưng không còn phù hợp với các phiên bản Java hiện đại.

Tuy nhiên, điều đáng nói là mặc dù có nanoTime()sự an toàn của JDK , nhưng đã có một số lỗi trong OpenJDK khiến nó không duy trì được sự bảo đảm này trên một số nền tảng nhất định hoặc trong một số trường hợp nhất định (ví dụ: JDK-8040140 , JDK-8184271 ). Hiện tại không có lỗi mở (đã biết) trong OpenJDK wrt nanoTime(), nhưng việc phát hiện ra một lỗi mới như vậy hoặc hồi quy trong bản phát hành mới hơn của OpenJDK không gây sốc cho bất kỳ ai.

Với ý nghĩ đó, mã sử dụng nanoTime()để chặn thời gian, chờ khoảng thời gian, hết thời gian, v.v. tốt nhất nên coi chênh lệch thời gian âm (thời gian chờ) là số không thay vì ném ngoại lệ. Thực hành này cũng là một lợi thế vì nó phù hợp với hành vi của tất cả các phương pháp chờ đợi đúng lúc trong mọi tầng lớp trong java.util.concurrent.*, ví dụ Semaphore.tryAcquire(), Lock.tryLock(), BlockingQueue.poll()vv

Tuy nhiên, nanoTime()vẫn nên được ưu tiên để thực hiện chặn thời gian, chờ khoảng thời gian, hết thời gian, v.v. currentTimeMillis()bởi vì sau này là đối tượng của hiện tượng "thời gian quay ngược" (ví dụ do điều chỉnh thời gian của máy chủ), tức currentTimeMillis()là không phù hợp để đo khoảng thời gian ở tất cả. Xem câu trả lời này để biết thêm thông tin.

Thay vì sử dụng nanoTime()trực tiếp cho các phép đo thời gian thực thi mã, tốt nhất nên sử dụng các khung và trình biên dịch điểm chuẩn chuyên dụng, ví dụ JMHasync-profiler trong chế độ định hình đồng hồ treo tường .


10

Tuyên bố miễn trừ trách nhiệm: Tôi là nhà phát triển của thư viện này

Bạn có thể thích điều này tốt hơn:

http://juliusdavies.ca/nanotime/

Nhưng nó sao chép tệp DLL hoặc Unix .so (đối tượng dùng chung) vào thư mục chính của người dùng hiện tại để có thể gọi JNI.

Một số thông tin cơ bản có trên trang web của tôi tại:

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


@Julius Bạn đã xóa thư viện khỏi trang web của mình chưa?
Nitin Dandriyal

6

Linux sửa lỗi cho sự khác biệt giữa các CPU, nhưng Windows thì không. Tôi đề nghị bạn giả sử System.nanoTime () chỉ chính xác trong khoảng 1 micro giây. Một cách đơn giản để có thời gian dài hơn là gọi foo () 1000 lần trở lên và chia thời gian cho 1000.


2
Bạn có thể cung cấp một tài liệu tham khảo (hành vi trên Linux và Windows)?
jfs

Thật không may, phương pháp được đề xuất thường sẽ rất thiếu chính xác vì mỗi sự kiện rơi vào khe cập nhật đồng hồ treo tường +/- 100ms thường sẽ trả về 0 cho các hoạt động phụ thứ hai. Tổng của 9 phép toán, mỗi phép toán có thời lượng bằng 0, tốt, bằng 0, chia cho chín là ... không. Ngược lại, sử dụng System.nanoTime () sẽ cung cấp thời lượng sự kiện tương đối chính xác (khác không), sau đó tổng hợp và chia cho số lượng sự kiện sẽ cung cấp mức trung bình rất chính xác.
Darrell Teague

@DarrellTeague tổng hợp 1000 sự kiện và thêm chúng vào cũng giống như thời gian kết thúc.
Peter Lawrey

@DarrellTeague System.nanoTime () chính xác đến 1 micro giây hoặc tốt hơn (không phải 100.000 micro giây) trên hầu hết các hệ thống. Tính trung bình cho nhiều thao tác chỉ có liên quan khi bạn giảm xuống một vài giây và chỉ trên một số hệ thống nhất định.
Peter Lawrey

1
Xin lỗi vì có một số nhầm lẫn về ngôn ngữ được sử dụng trong các sự kiện "tổng kết". Có, nếu thời gian được đánh dấu khi bắt đầu 1000 thao tác phụ thứ hai, chúng sẽ chạy và sau đó thời gian được đánh dấu lại ở cuối và chia - điều đó sẽ hoạt động cho một số hệ thống đang được phát triển để có được khoảng thời gian xấp xỉ tốt cho một thời gian nhất định biến cố.
Darrell Teague

5

Tuyệt đối không vô dụng. Thời gian người hâm mộ chỉ ra chính xác vấn đề đa lõi, nhưng trong các ứng dụng thực sự, nó thường tốt hơn hoàn toàn so với currentTimeMillis ().

Khi tính toán các vị trí đồ họa trong khung làm mới nanoTime () dẫn đến chuyển động mượt mà hơn trong chương trình của tôi.

Và tôi chỉ thử nghiệm trên các máy đa lõi.


5

Tôi đã thấy thời gian trôi qua tiêu cực được báo cáo từ việc sử dụng System.nanoTime (). Để rõ ràng, mã trong câu hỏi là:

    long startNanos = System.nanoTime();

    Object returnValue = joinPoint.proceed();

    long elapsedNanos = System.nanoTime() - startNanos;

và biến 'elapsedNanos' có giá trị âm. (Tôi khẳng định rằng cuộc gọi trung gian cũng mất ít hơn 293 năm, đó là điểm tràn cho các nanos được lưu trữ trong thời gian dài :)

Điều này xảy ra khi sử dụng IBM v1.5 JRE 64bit trên phần cứng IBM P690 (đa lõi) chạy AIX. Tôi chỉ thấy lỗi này xảy ra một lần, nên có vẻ như rất hiếm. Tôi không biết nguyên nhân - đó có phải là sự cố cụ thể về phần cứng, lỗi JVM - tôi không biết. Tôi cũng không biết ý nghĩa của tính chính xác của nanoTime () nói chung.

Để trả lời câu hỏi ban đầu, tôi không nghĩ nanoTime là vô ích - nó cung cấp thời gian dưới một phần nghìn giây, nhưng có một rủi ro thực tế (không chỉ là lý thuyết) về việc nó không chính xác mà bạn cần phải tính đến.


Than ôi, dường như là một số vấn đề hệ điều hành / phần cứng. Tài liệu nói rằng các giá trị cốt lõi có thể âm nhưng (âm lớn hơn trừ âm nhỏ hơn) vẫn phải là giá trị dương. Thật vậy, giả định là trong cùng một luồng, lệnh gọi nanoTime () phải luôn trả về giá trị dương hoặc âm. Chưa bao giờ thấy điều này trên các hệ thống Unix và Windows khác nhau trong nhiều năm nhưng âm thanh có thể xảy ra đặc biệt là nếu phần cứng / HĐH đang phân tách hoạt động dường như nguyên tử này trên các bộ xử lý.
Darrell Teague

@BasilVandegriend nó không phải là một lỗi ở bất cứ đâu. Theo tài liệu, hiếm khi System.nanoTime () trong ví dụ của bạn có thể chạy trên một CPU khác và các giá trị nanoTime được tính trên CPU đó có thể chỉ thấp hơn giá trị được tính trên CPU đầu tiên. Vì vậy, giá trị -ve cho elapsedNanos là có thể
vô tận

2

Đây dường như không phải là vấn đề đối với Core 2 Duo chạy Windows XP và JRE 1.5.0_06.

Trong một thử nghiệm với ba luồng tôi không thấy System.nanoTime () đi ngược lại. Các bộ xử lý đều bận rộn và thỉnh thoảng đi ngủ để kích thích các luồng di chuyển xung quanh.

[EDIT] Tôi đoán rằng điều đó chỉ xảy ra trên các bộ xử lý riêng biệt, tức là các bộ đếm được đồng bộ hóa cho nhiều lõi trên cùng một khuôn.


2
Nó có thể sẽ không xảy ra mọi lúc, nhưng do cách thức thực hiện nanotime (), khả năng luôn luôn có.
pdeva

Tôi đoán rằng nó chỉ xảy ra trên các bộ xử lý riêng biệt, tức là các bộ đếm được đồng bộ hóa cho nhiều lõi trên cùng một khuôn.
starblue

Ngay cả điều đó phụ thuộc vào việc thực hiện cụ thể, IIRC. Nhưng đó là điều mà HĐH cần phải quan tâm.
Blaisorblade

1
Bộ đếm RDTSC trên nhiều lõi của cùng một bộ xử lý x86 không nhất thiết phải được đồng bộ hóa - một số hệ thống hiện đại cho phép các lõi khác nhau chạy ở tốc độ khác nhau.
Jules

2

Không, không phải ... Nó chỉ phụ thuộc vào CPU của bạn, hãy kiểm tra Bộ đếm thời gian chính xác cao để biết cách / lý do mọi thứ được xử lý khác nhau theo CPU.

Về cơ bản, hãy đọc nguồn Java của bạn và kiểm tra xem phiên bản của bạn có chức năng gì và nếu nó hoạt động dựa trên CPU, bạn sẽ chạy nó trên đó.

IBM thậm chí còn đề nghị bạn sử dụng nó để đánh giá hiệu năng (một bài đăng năm 2008, nhưng được cập nhật).


Như tất cả các triển khai đã xác định bahaviour, "caveat emptor!"
David Schmitt

2

Tôi đang liên kết đến những gì về cơ bản là cùng một cuộc thảo luận nơi Peter Lawrey đang cung cấp một câu trả lời tốt. Tại sao tôi nhận được thời gian trôi qua tiêu cực bằng System.nanoTime ()?

Nhiều người đã đề cập rằng trong Java System.nanoTime () có thể trả về thời gian âm. Tôi đã xin lỗi vì đã lặp lại những gì người khác đã nói.

  1. nanoTime () không phải là đồng hồ mà là bộ đếm chu kỳ CPU.
  2. Giá trị trả về được chia theo tần số để trông giống như thời gian.
  3. Tần số CPU có thể dao động.
  4. Khi luồng của bạn được lên lịch trên CPU khác, có khả năng nhận nanoTime () dẫn đến sự khác biệt âm. Điều đó hợp lý. Bộ đếm trên CPU không được đồng bộ hóa.
  5. Trong nhiều trường hợp, bạn có thể nhận được kết quả khá sai lệch nhưng bạn sẽ không thể biết vì delta không âm. Hãy suy nghĩ về nó.
  6. (chưa được xác nhận) Tôi nghĩ rằng bạn có thể nhận được kết quả âm ngay cả trên cùng một CPU nếu các hướng dẫn được sắp xếp lại. Để ngăn chặn điều đó, bạn phải gọi một hàng rào bộ nhớ nối tiếp các hướng dẫn của bạn.

Sẽ thật tuyệt nếu System.nanoTime () trả về coreID nơi nó được thực thi.


1
Tất cả các điểm trừ 3. và 5. đều sai. 1. nanoTime () không phải là bộ đếm chu kỳ CPU, nó là thời gian nano . 2. Cách giá trị nanoTime được tạo ra là dành riêng cho nền tảng. 4. Không, sự khác biệt không thể âm, theo thông số nanoTime (). Giả sử OpenJDK không có lỗi wrt nanoTime () và hiện tại không có lỗi nào chưa được giải quyết. 6. Các cuộc gọi nanoTime không thể được sắp xếp lại trong một luồng vì đó là phương thức gốc và JVM tôn trọng thứ tự chương trình. JVM không bao giờ sắp xếp lại các cuộc gọi phương thức gốc bởi vì nó không biết điều gì xảy ra bên trong chúng và do đó không thể chứng minh rằng việc sắp xếp lại như vậy sẽ an toàn.
leventov

Về 5. kết quả khác biệt của nanoTime () có thể gây hiểu nhầm thực sự, nhưng không phải vì những lý do được trình bày ở những điểm khác trong tài khoản này. Nhưng thay vì các lý do được trình bày ở đây: shipilev.net/blog/2014/nanotrusting-nanotime
leventov

Trớ trêu thay, liên quan đến 6. đã có một lỗi trong OpenJDK đặc biệt là do sắp xếp lại: bug.openjdk.java.net/browse/JDK-8184271 . Trong OpenJDK, nanoTime () là một nội tại và nó được phép sắp xếp lại, đó là một lỗi.
leventov

@leventov, vậy nanotime () có an toàn để sử dụng không? có nghĩa là, nó không thể trả về các giá trị âm và ~ chính xác theo thời gian. Tôi không thấy điểm phơi bày một hàm API có vấn đề. Bài đăng này là một bằng chứng, bắt đầu vào năm 2009 và vẫn bình luận vào năm 2019. Đối với các nhiệm vụ quan trọng, tôi tưởng tượng mọi người dựa vào các thẻ thời gian như Symmetricom
Vortex

1
Số 4 của bạn nói về tiêu cực sự khác biệt , không phải giá trị: "có cơ hội nhận được nanoTime () dẫn đến sự khác biệt tiêu cực."
leventov

1

Java là nền tảng chéo và nanoTime phụ thuộc vào nền tảng. Nếu bạn sử dụng Java - khi không sử dụng nanoTime. Tôi tìm thấy các lỗi thực sự trên các triển khai jvm khác nhau với chức năng này.


0

Tài liệu Java 5 cũng khuyến nghị sử dụng phương thức này cho cùng mục đích.

Phương pháp này chỉ có thể được sử dụng để đo thời gian trôi qua và không liên quan đến bất kỳ khái niệm nào khác về thời gian hệ thống hoặc đồng hồ treo tường.

Tài liệu API Java 5


0

Ngoài ra, System.currentTimeMillies()thay đổi khi bạn thay đổi đồng hồ hệ thống, trong khi System.nanoTime()không, vì vậy, cái sau sẽ an toàn hơn để đo thời lượng.


-3

nanoTimelà vô cùng không an toàn cho thời gian. Tôi đã thử nó trên các thuật toán kiểm tra tính nguyên thủy cơ bản của mình và nó đã đưa ra các câu trả lời cách nhau đúng một giây cho cùng một đầu vào. Đừng sử dụng phương pháp lố bịch đó. Tôi cần một cái gì đó chính xác và chính xác hơn là có được mili thời gian, nhưng không tệ như nanoTime.


không có nguồn hoặc giải thích tốt hơn bình luận này là vô ích
ic3
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.