Đo thời gian trong Linux - thời gian so với đồng hồ vs getrusage so với clock_gettime vs gettimeofday so với timespec_get?


148

Trong số các chức năng thời gian, time, clock getrusage, clock_gettime, gettimeofdaytimespec_get, tôi muốn hiểu rõ cách thức chúng được thực hiện và giá trị trả về của họ là gì để biết trong đó tình hình tôi phải sử dụng chúng.

Trước tiên, chúng ta cần phân loại các hàm trả về giá trị đồng hồ treo tường so với các hàm trả về giá trị của tiến trình hoặc luồng . gettimeofdaytrả về giá trị đồng hồ treo tường, clock_gettimetrả về giá trị đồng hồ treo tường hoặc giá trị xử lý hoặc luồng tùy thuộc vào Clocktham số được truyền cho nó. getrusageclocktrả về các giá trị quá trình.

Sau đó, câu hỏi thứ hai liên quan đến việc thực hiện các chức năng này và kết quả là tính chính xác của chúng. Những cơ chế phần cứng hoặc phần mềm nào sử dụng các chức năng này.

Có vẻ như getrusagechỉ sử dụng tick kernel (thường dài 1ms) và kết quả là không thể chính xác hơn ms. Đúng không? Sau đó, getimeofdaychức năng dường như sử dụng phần cứng cơ bản chính xác nhất có sẵn. Do đó, độ chính xác của nó thường là micro giây (không thể nhiều hơn do API) trên phần cứng gần đây. Thế còn clock, trang người đàn ông nói về "xấp xỉ", nó có nghĩa là gì? Thế còn clock_gettime, API tính bằng nano giây, điều đó có nghĩa là nó có thể chính xác đến vậy nếu phần cứng cơ bản cho phép nó? Còn sự đơn điệu thì sao?

Có chức năng nào khác không?

Câu trả lời:


198

Vấn đề là có một số hàm thời gian khác nhau có sẵn trong C và C ++, và một số trong số chúng khác nhau về hành vi giữa các lần triển khai. Ngoài ra còn có rất nhiều câu trả lời nửa nổi xung quanh. Tổng hợp danh sách các chức năng đồng hồ cùng với các thuộc tính của chúng sẽ trả lời đúng câu hỏi. Để bắt đầu, hãy hỏi những thuộc tính có liên quan mà chúng tôi đang tìm kiếm. Nhìn vào bài viết của bạn, tôi đề nghị:

  • Thời gian được đo bằng đồng hồ? (thực tế, người dùng, hệ thống, hoặc, hy vọng là không, đồng hồ treo tường?)
  • Độ chính xác của đồng hồ là gì? (s, ms, cụm, hoặc nhanh hơn?)
  • Sau bao nhiêu thời gian đồng hồ quấn quanh? Hoặc có một số cơ chế để tránh điều này?
  • Là đồng hồ đơn điệu, hoặc nó sẽ thay đổi theo thời gian của hệ thống (thông qua NTP, múi giờ, thời gian tiết kiệm ánh sáng ban ngày, bởi người dùng, v.v.)?
  • Làm thế nào để thay đổi ở trên giữa các thực hiện?
  • Là chức năng cụ thể đã lỗi thời, không chuẩn, vv?

Trước khi bắt đầu danh sách, tôi muốn chỉ ra rằng thời gian đồng hồ treo tường hiếm khi là thời điểm thích hợp để sử dụng, trong khi nó thay đổi theo thay đổi múi giờ, thay đổi thời gian tiết kiệm ánh sáng ban ngày hoặc nếu đồng hồ treo tường được đồng bộ hóa bởi NTP. Không có điều nào trong số này là tốt nếu bạn đang sử dụng thời gian để lên lịch các sự kiện hoặc để thực hiện điểm chuẩn. Nó chỉ thực sự tốt cho những gì tên gọi, một chiếc đồng hồ trên tường (hoặc máy tính để bàn).

Đây là những gì tôi đã tìm thấy cho đến nay cho các đồng hồ trong Linux và OS X:

  • time() trả về thời gian đồng hồ treo tường từ HĐH, với độ chính xác tính bằng giây.
  • clock()dường như trả về tổng thời gian của người dùng và hệ thống. Nó có mặt trong C89 và sau đó. Đã có lúc đây được coi là thời gian của CPU theo chu kỳ, nhưng các tiêu chuẩn hiện đại như POSIX yêu cầu CLOCKS_PER_SEC phải là 1000000, mang lại độ chính xác tối đa có thể là 1 Chú thích. Độ chính xác trên hệ thống của tôi thực sự là 1 Lời. Đồng hồ này kết thúc tốt đẹp khi nó bật ra (điều này thường xảy ra sau ~ 2 ^ 32 tick, không quá dài cho đồng hồ 1 MHz). man clocknói rằng kể từ glibc 2.18, nó được triển khai clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)trong Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...)cung cấp độ phân giải nano giây, là đơn điệu. Tôi tin rằng 'giây' và 'nano giây' được lưu trữ riêng biệt, mỗi giây trong các bộ đếm 32 bit. Do đó, bất kỳ sự bao bọc nào cũng sẽ xảy ra sau nhiều chục năm hoạt động. Đây trông giống như một chiếc đồng hồ rất tốt, nhưng thật không may, nó chưa có sẵn trên OS X. POSIX 7 mô tả CLOCK_MONOTONICnhư một phần mở rộng tùy chọn .
  • getrusage()hóa ra là sự lựa chọn tốt nhất cho tình huống của tôi Nó báo cáo người dùng và thời gian hệ thống riêng biệt và không bao quanh. Độ chính xác trên hệ thống của tôi là 1 Lời, nhưng tôi cũng đã thử nó trên hệ thống Linux (Red Hat 4.1.2-48 với GCC 4.1.2) và ở đó độ chính xác chỉ là 1 ms.
  • gettimeofday()trả về thời gian đồng hồ treo tường với độ chính xác (trên danh nghĩa). Trên hệ thống của tôi, chiếc đồng hồ này dường như có độ chính xác, nhưng điều này không được đảm bảo, vì "độ phân giải của đồng hồ hệ thống phụ thuộc vào phần cứng" . POSIX.1-2008 nói rằng . "Các ứng dụng nên sử dụng clock_gettime()chức năng thay vì chức năng lỗi thời gettimeofday()", vì vậy bạn nên tránh xa nó. Linux x86 và thực hiện nó như một cuộc gọi hệ thống .
  • mach_absolute_time()là một tùy chọn cho thời gian độ phân giải (ns) rất cao trên OS X. Trên hệ thống của tôi, điều này thực sự mang lại độ phân giải ns. Về nguyên tắc, đồng hồ này bao bọc xung quanh, tuy nhiên, nó đang lưu trữ ns bằng số nguyên không dấu 64 bit, do đó, việc bao quanh không nên là một vấn đề trong thực tế. Tính di động là nghi vấn.
  • Tôi đã viết một hàm lai dựa trên đoạn mã này sử dụng clock_gettime khi được biên dịch trên Linux hoặc bộ đếm thời gian Mach khi được biên dịch trên OS X, để có được độ chính xác ns trên cả Linux và OS X.

Tất cả những điều trên tồn tại trong cả Linux và OS X trừ khi có quy định khác. "Hệ thống của tôi" ở trên là một Apple chạy OS X 10.8.3 với GCC 4.7.2 từ MacPorts.

Cuối cùng, đây là danh sách các tài liệu tham khảo mà tôi thấy hữu ích ngoài các liên kết ở trên:


Cập nhật : cho OS X, clock_gettimeđã được triển khai kể từ ngày 10.12 (Sierra). Ngoài ra, cả hai nền tảng dựa trên POSIX và BSD (như OS X) đều chia sẻ trường rusage.ru_utimecấu trúc.


Mac OS X không có clock_gettime, do đó việc sử dụng gettimeofday()linh hoạt hơn một chút so vớiclock_gettime()
bobobobo

1
Bạn đã không đề cập times()(với một), đã tồn tại trong POSIX kể từ Vấn đề 1. Liên quan đến GNU / Linux: Theo trang man (3), clock()từ glibc 2.17 và trước đó đã được triển khai trên đầu trang, nhưng đã được cải thiện chính xác, hiện được triển khai trên đầu trang clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...), cũng được chỉ định trong POSIX nhưng là tùy chọn.
vinc17

2
@starflyer Độ chính xác của đồng hồ bị giới hạn một phần bởi thời gian cần thiết để thăm dò đồng hồ. Điều này là do, nếu tôi gọi đồng hồ và phải trả lại 1 Patrick, thì thời gian báo cáo đồng hồ sẽ bị "tắt" bởi 1 Lời từ góc nhìn của người gọi. Điều này có nghĩa là đồng hồ có độ chính xác cao cũng phải có độ trễ thấp. Vì vậy, thông thường người ta sẽ không đánh đổi mà bạn đang nói đến: đồng hồ rẻ nhất cũng sẽ chính xác nhất.
Douglas B. Staple

3
Ngoài ra, hầu hết các đồng hồ không quan tâm đến việc tiết kiệm thời gian / múi giờ ban ngày, ngay cả khi chúng được coi là đồng hồ treo tường . Cả hai timegettimeofdaytrở lại, ít nhất là ngày nay, vài giây kể từ epoch (còn gọi là dấu thời gian unix). Điều này là độc lập với múi giờ / DST. Leap giây là một câu chuyện khác ...
Zulan

2
Đối với người dùng Android, việc sử dụng CLOCK_MONOTONIC có thể gặp sự cố do ứng dụng có thể bị treo, cùng với đồng hồ. Vì thế, Android đã thêm bộ hẹn giờ ANDROID_ALARM_ELAPSED_REALTIME có thể truy cập thông qua ioctl. một số thông tin về những điều này và các thông tin liên quan đến đình chỉ khác có thể được tìm thấy ở đây
Itay Bianco

17

C11 timespec_get

Ví dụ sử dụng tại: https://stackoverflow.com/a/36095407/895245

Độ chính xác tối đa có thể được trả về là nano giây, nhưng độ chính xác thực tế được xác định và có thể nhỏ hơn.

Nó trả về thời gian treo tường, không sử dụng CPU.

glibc 2.21 thực hiện nó bên dưới sysdeps/posix/timespec_get.cvà nó chuyển trực tiếp tới:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimeCLOCK_REALTIMElà POSIX http://pub.opengroup.org/onlinepub/9699919799/fifts/clock_getres.htmlman clock_gettimenói rằng biện pháp này có thể có sự gián đoạn nếu bạn thay đổi một số cài đặt thời gian hệ thống trong khi chương trình của bạn chạy.

Đồng hồ bấm giờ C ++ 11

Vì chúng tôi đang ở đó, chúng tôi cũng bao gồm chúng: http://en.cppreference.com/w/cpp/ synco

GCC 5.3.0 (C ++ stdlib nằm trong nguồn GCC):

  • high_resolution_clock là bí danh cho system_clock
  • system_clock chuyển tiếp đến đầu tiên sau đây có sẵn:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock chuyển tiếp đến đầu tiên sau đây có sẵn:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Hỏi tại: Sự khác biệt giữa std :: system_clock và std :: ổn_clock?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: Sự khác biệt giữa CLOCK_REALTIME và CLOCK_MONOTONIC?


1
Câu trả lời tuyệt vời làm sáng tỏ các triển khai điển hình. Đó là những gì mọi người thực sự cần biết.
Không giới hạn
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.