Ukur waktu di Linux - waktu vs jam vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?

148

Di antara fungsi waktu, time, clock getrusage, clock_gettime, gettimeofdaydan timespec_get, saya ingin memahami dengan jelas bagaimana mereka diimplementasikan dan apa nilai-nilai mereka kembali untuk mengetahui di mana situasi saya harus menggunakannya.

Pertama, kita perlu mengklasifikasikan fungsi yang mengembalikan nilai jam dinding dibandingkan dengan fungsi yang mengembalikan nilai proses atau nilai ulir . gettimeofdaymengembalikan nilai jam dinding, clock_gettimemengembalikan nilai jam dinding atau proses atau nilai untaian tergantung pada Clockparameter yang diteruskan ke sana. getrusagedan clockmengembalikan nilai proses.

Kemudian pertanyaan kedua berkaitan dengan implementasi fungsi-fungsi ini dan sebagai konsekuensinya, keakuratannya. Mekanisme perangkat keras atau perangkat lunak mana yang digunakan fungsi-fungsi ini.

Tampaknya getrusagehanya menggunakan centang kernel (biasanya 1 ms panjang) dan sebagai akibatnya tidak bisa lebih akurat daripada ms. Apakah tepat? Maka getimeofdayfungsi tersebut tampaknya menggunakan perangkat keras yang paling akurat yang tersedia. Akibatnya akurasinya biasanya mikrodetik (tidak bisa lebih karena API) pada perangkat keras terbaru. Bagaimana dengan clock, halaman manual berbicara tentang "aproksimasi", apa artinya? Bagaimana dengan clock_gettime, API dalam nanosecond, apakah ini berarti ia bisa sangat akurat jika perangkat keras yang mendasarinya memungkinkannya? Bagaimana dengan monotonitas?

Apakah ada fungsi lain?

Manuel Selva
sumber

Jawaban:

198

Masalahnya adalah bahwa ada beberapa fungsi waktu yang berbeda tersedia di C dan C ++, dan beberapa dari mereka berbeda dalam perilaku antara implementasi. Ada juga banyak jawaban setengah melayang. Mengompilasi daftar fungsi jam bersama dengan propertinya akan menjawab pertanyaan dengan benar. Sebagai permulaan mari kita tanyakan properti apa yang relevan yang kita cari. Melihat posting Anda, saya sarankan:

  • Jam berapa diukur dengan jam? (nyata, pengguna, sistem, atau, semoga tidak, jam dinding?)
  • Apa ketepatan jam? (s, ms, µs, atau lebih cepat?)
  • Setelah berapa lama waktu berlalu? Atau adakah mekanisme untuk menghindari ini?
  • Apakah jam monoton, atau akankah itu berubah dengan perubahan dalam waktu sistem (melalui NTP, zona waktu, waktu musim panas, oleh pengguna, dll.)?
  • Bagaimana perbedaan di atas di antara implementasi?
  • Apakah fungsi spesifik sudah usang, tidak standar, dll.?

Sebelum memulai daftar, saya ingin menunjukkan bahwa waktu jam dinding jarang waktu yang tepat untuk digunakan, sedangkan itu berubah dengan perubahan zona waktu, perubahan waktu musim panas, atau jika jam dinding disinkronkan oleh NTP. Tidak satu pun dari hal-hal ini baik jika Anda menggunakan waktu untuk menjadwalkan acara atau untuk mengukur kinerja. Itu hanya sangat bagus untuk apa yang dikatakan namanya, jam di dinding (atau desktop).

Inilah yang saya temukan sejauh ini untuk jam di Linux dan OS X:

  • time() mengembalikan waktu jam dinding dari OS, dengan ketepatan dalam hitungan detik.
  • clock()tampaknya mengembalikan jumlah waktu pengguna dan sistem. Ini hadir di C89 dan yang lebih baru. Pada suatu waktu ini seharusnya menjadi waktu CPU dalam siklus, tetapi standar modern seperti POSIX membutuhkan CLOCKS_PER_SEC menjadi 1000000, memberikan kemungkinan presisi maksimum 1 μs. Ketepatan pada sistem saya memang 1 μs. Jam ini membungkus setelah puncak (ini biasanya terjadi setelah ~ 2 ^ 32 ticks, yang tidak terlalu lama untuk jam 1 MHz). man clockmengatakan bahwa sejak glibc 2.18 diimplementasikan dengan clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)di Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...)memberikan resolusi nanosecond, bersifat monoton. Saya percaya 'detik' dan 'nanodetik' disimpan secara terpisah, masing-masing dalam penghitung 32-bit. Dengan demikian, setiap penyelesaian akan terjadi setelah belasan tahun uptime. Ini terlihat seperti jam yang sangat bagus, tetapi sayangnya itu belum tersedia pada OS X. POSIX 7 menggambarkan CLOCK_MONOTONICsebagai ekstensi opsional .
  • getrusage()ternyata menjadi pilihan terbaik untuk situasi saya. Ini melaporkan pengguna dan waktu sistem secara terpisah dan tidak membungkus. Presisi pada sistem saya adalah 1 μs, tetapi saya juga mengujinya pada sistem Linux (Red Hat 4.1.2-48 dengan GCC 4.1.2) dan di sana presisi hanya 1 ms.
  • gettimeofday()mengembalikan waktu jam dinding dengan presisi (nominal) µs. Pada sistem saya, jam ini tampaknya memiliki presisi μs, tetapi ini tidak dijamin, karena "resolusi jam sistem bergantung pada perangkat keras" . POSIX.1-2008 mengatakan itu . "Aplikasi harus menggunakan clock_gettime()fungsi alih-alih fungsi yang usang gettimeofday()", jadi Anda harus menjauh darinya. Linux x86 dan mengimplementasikannya sebagai panggilan sistem .
  • mach_absolute_time()adalah pilihan untuk pengaturan resolusi sangat tinggi (ns) pada OS X. Pada sistem saya, ini memang memberikan resolusi ns. Pada prinsipnya jam ini membungkus, namun menyimpan ns menggunakan integer 64-bit unsigned, sehingga membungkus sekitar seharusnya tidak menjadi masalah dalam praktiknya. Portabilitas dipertanyakan.
  • Saya menulis fungsi hibrida berdasarkan cuplikan ini yang menggunakan clock_gettime saat dikompilasi di Linux, atau pengatur waktu Mach saat dikompilasi pada OS X, untuk mendapatkan ketepatan ns di Linux dan OS X.

Semua hal di atas ada di Linux dan OS X kecuali ditentukan sebaliknya. "Sistem saya" di atas adalah Apple yang menjalankan OS X 10.8.3 dengan GCC 4.7.2 dari MacPorts.

Akhirnya, berikut adalah daftar referensi yang menurut saya bermanfaat selain tautan di atas:


Pembaruan : untuk OS X, clock_gettimetelah diimplementasikan pada 10.12 (Sierra). Juga, kedua platform berbasis POSIX dan BSD (seperti OS X) berbagi rusage.ru_utimebidang struct.

Douglas B. Staple
sumber
Mac OS X tidak memiliki clock_gettime, karenanya penggunaan gettimeofday()menjadi sedikit lebih fleksibel daripadaclock_gettime()
bobobobo
1
Anda belum menyebutkan times()(dengan huruf s), yang telah ada di POSIX sejak Edisi 1. Mengenai GNU / Linux: Menurut halaman manual clock (3), clock()dari glibc 2.17 dan sebelumnya telah diterapkan di atasnya, tetapi untuk peningkatan presisi, sekarang diterapkan di atas clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...), yang juga ditentukan dalam POSIX tetapi opsional.
vinc17
2
@starflyer Ketepatan jam sebagian dibatasi oleh jumlah waktu yang diperlukan untuk polling jam. Ini karena, jika saya memanggil jam dan butuh 1 μs untuk kembali, maka waktu laporan jam akan "mati" oleh 1 μs dari perspektif pemanggil. Ini berarti bahwa jam yang sangat akurat juga harus memiliki latensi rendah. Jadi biasanya seseorang tidak akan memiliki pertukaran yang sedang Anda bicarakan: jam termurah juga akan menjadi yang paling akurat.
Douglas B. Staple
3
Juga sebagian besar jam tidak peduli dengan zona waktu / waktu penghematan siang hari, bahkan jika mereka dianggap sebagai jam dinding . Keduanya timedan gettimeofdaykembali, setidaknya saat ini, detik sejak zaman (alias unix-cap waktu). Ini tidak tergantung pada zona waktu / DST. Detik lompatan adalah cerita lain ...
Zulan
2
Untuk pengguna Android, menggunakan CLOCK_MONOTONIC mungkin bermasalah karena aplikasi mungkin ditangguhkan, bersamaan dengan waktu. Untuk itu, Android menambahkan timer ANDROID_ALARM_ELAPSED_REALTIME yang dapat diakses melalui ioctl. beberapa informasi tentang ini dan informasi terkait lainnya yang ditangguhkan dapat ditemukan di sini
Itay Bianco
17

C11 timespec_get

Contoh penggunaan di: https://stackoverflow.com/a/36095407/895245

Presisi maksimum yang mungkin dikembalikan adalah nanodetik, tetapi presisi sebenarnya adalah implementasi yang ditentukan dan bisa lebih kecil.

Ini mengembalikan waktu dinding, bukan penggunaan CPU.

glibc 2.21 mengimplementasikannya di bawah sysdeps/posix/timespec_get.cdan meneruskan langsung ke:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimedan CLOCK_REALTIMEPOSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html , dan man clock_gettimemengatakan bahwa ukuran ini mungkin memiliki diskontinuitas jika Anda mengubah pengaturan waktu sistem saat program Anda berjalan.

C ++ 11 chrono

Karena kita sudah siap, mari kita bahas juga: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C ++ stdlib ada di dalam sumber GCC):

  • high_resolution_clock adalah alias untuk system_clock
  • system_clock meneruskan ke yang pertama dari yang berikut ini yang tersedia:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock meneruskan ke yang pertama dari yang berikut ini yang tersedia:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Ditanyakan pada: Perbedaan antara std :: system_clock dan std :: stable_clock?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: Perbedaan antara CLOCK_REALTIME dan CLOCK_MONOTONIC?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
1
Jawaban yang bagus yang menggambarkan implementasi yang khas. Itulah yang benar-benar perlu diketahui orang.
Celess