2013-09-27 134 views
55

Hôm nay tôi đã làm một chút Benchmark nhanh chóng để kiểm tra hiệu suất tốc độ của System.nanoTime()System.currentTimeMillis():Tại sao cách System.nanoTime() chậm hơn (hiệu suất) hơn System.currentTimeMillis()?

long startTime = System.nanoTime(); 

for(int i = 0; i < 1000000; i++) { 
    long test = System.nanoTime(); 
} 

long endTime = System.nanoTime(); 

System.out.println("Total time: "+(endTime-startTime)); 

Đây là kết quả:

System.currentTimeMillis(): average of 12.7836022/function call 
System.nanoTime():   average of 34.6395674/function call 

Tại sao sự khác biệt về tốc độ chạy quá lớn?

hệ thống Benchmark:

Java 1.7.0_25 
Windows 8 64-bit 
CPU: AMD FX-6100 
+0

bản sao có thể có của [Tại sao System.nanoTime() và System.currentTimeMillis() trôi dạt quá nhanh?] (Http://stackoverflow.com/questions/5839152/why-do-system-nanotime-and-system -currenttimemillis-drift-apart-so-nhanh) – chrylis

+0

Bài đăng này có thể trả lời câu hỏi của bạn: http://stackoverflow.com/a/5839267/658907 – matts

+0

'nanoTime' chính xác hơn' currentTimeMillis', đó có thể là lý do. – Thomas

Trả lời

61

Từ this Oracle blog:

System.currentTimeMillis() được thực hiện bằng cách sử dụng phương pháp GetSystemTimeAsFileTime, trong đó chủ yếu chỉ đọc thấp độ phân giải time-of-ngày giá trị rằng Windows duy trì. Đọc số biến toàn cục này tự nhiên rất nhanh - khoảng 6 chu kỳ theo thông tin báo cáo .

System.nanoTime() được thực hiện bằng cách sử dụng QueryPerformanceCounter/ QueryPerformanceFrequency API (nếu có, khác nó trả currentTimeMillis*10^6). QueryPerformanceCounter(QPC) được thực hiện theo những cách khác nhau tùy thuộc vào phần cứng nó đang chạy trên. Thông thường nó sẽ sử dụng hoặc là lập trình-khoảng thời gian hẹn giờ (PIT), hoặc nguồn ACPI bộ đếm thời gian quản lý (PMT) hoặc bộ đếm thời gian cấp CPU (TSC) Truy cập PIT/PMT yêu cầu thực hiện các lệnh cổng I/O chậm và kết quả là thời gian thực hiện QPC theo thứ tự của micro giây. Ngược lại, việc đọc TSC theo thứ tự của 100 đồng hồ chu kỳ (để đọc TSC từ chip và chuyển đổi nó thành giá trị thời gian dựa trên tần suất hoạt động).

Có lẽ câu trả lời này là câu hỏi. Hai phương pháp sử dụng số chu kỳ đồng hồ khác nhau, do đó dẫn đến tốc độ chậm của chu kỳ sau.

Tiếp tục trong rằng blog trong phần kết luận:

Nếu bạn quan tâm đến đo/tính toán thời gian trôi qua, sau đó luôn luôn sử dụng System.nanoTime(). Trên hầu hết các hệ thống, nó sẽ cho độ phân giải theo thứ tự micro giây. Tuy nhiên, hãy lưu ý rằng, cuộc gọi này cũng có thể mất một phần triệu giây để thực thi trên một số nền tảng.

+10

Câu trả lời hay. Ngoài ra trang web này: http://stas-blogspot.blogspot.nl/2012/02/what-is-behind-systemnanotime.html Ai đó đã làm một ít nghiên cứu và cũng cho thấy mã nguồn đằng sau System.nanoTime trên các hệ điều hành khác nhau. – MystyxMac

23

Hầu hết các hệ điều hành (bạn không đề cập đến cái nào bạn đang sử dụng) có trong bộ nhớ truy cập/đồng hồ cung cấp chính xác phần nghìn giây (hoặc gần đó). Đối với độ chính xác nano giây nhất phải đọc một bộ đếm phần cứng. Giao tiếp với phần cứng chậm hơn sau đó đọc một số giá trị đã có trong bộ nhớ.

3

Nó chỉ có thể xảy ra trên Windows. Xem this answer cho một câu hỏi tương tự.

Về cơ bản, System.currentTimeMillis() chỉ đọc biến toàn cầu được Windows duy trì (đó là những gì nó có độ chi tiết thấp), trong khi System.nanoTime() thực sự phải thực hiện các thao tác IO.

0

Bạn đang đo lường điều đó trên Windows, đúng không. Tôi đã đi qua bài tập này vào năm 2008. nanoTime IS chậm hơn trên Windows so với currentTimeMillis. Khi tôi nhớ lại, trên Linux, nanotime nhanh hơn currentTimeMillis và chắc chắn nhanh hơn so với Windows. Điều quan trọng cần lưu ý là nếu bạn đang cố gắng đo tổng hợp của nhiều hoạt động phụ mili giây, bạn phải sử dụng nanotime như thể thao tác đã hoàn thành trong chưa đến 1/1000th của mã thứ hai, so sánh currentTimeMillis sẽ hiển thị hoạt động ngay lập tức, vì vậy 1.000 trong số này sẽ vẫn tức thời. Những gì bạn có thể muốn làm là sử dụng nanotime sau đó làm tròn đến mili giây gần nhất, vì vậy nếu một hoạt động mất 8000 nano giây, nó sẽ được tính là 1 mili giây, không phải 0,

0

Điều bạn có thể làm là sử dụng nanotime vòng trong vòng miligiây gần nhất, vì vậy nếu một hoạt động mất 8000 nano giây nó sẽ được tính là 1 mili giây, không phải 0.

Arithmetic lưu ý:

8000 nano giây là 8 micro là 0,008 mili giây. Làm tròn sẽ thực hiện điều đó đến 0 mili giây.