Linux'ta zamanı ölçün - saat vs getrusage, clock_gettime, gettimeofday ve timespec_get?


149

Zamanlama fonksiyonları arasında, time, clock getrusage, clock_gettime, gettimeofdayve timespec_get, onlar nasıl uygulandığını açıkça anlamak istiyorum ve hangi durumlarda bunları kullanmak zorunda bilmek için onların dönüş değerleri nelerdir.

Öncelikle, duvar saati değerlerini döndüren işlevleri, süreç veya iş parçacığı değerlerini döndüren işlevlerle karşılaştırmalıyız . kendisine geçirilen parametreye göre duvar gettimeofdaysaati değerini clock_gettimedöndürür, duvar saati değerini veya işlem veya iş parçacığı değerlerini döndürür Clock. getrusageve clocksüreç değerlerini döndürür.

Daha sonra ikinci soru, bu işlevlerin uygulanması ve sonuç olarak bunların doğruluğu ile ilgilidir. Bu işlevler hangi donanım veya yazılım mekanizmasını kullanır.

Görünüşe göre getrusagesadece çekirdek onayını kullanıyor (genellikle 1ms uzunluğunda) ve sonuç olarak ms'den daha doğru olamaz. Doğru mu? Daha sonra getimeofdayişlev, mevcut en doğru temel donanımı kullanıyor gibi görünüyor. Sonuç olarak, son donanımda doğruluğu genellikle mikrosaniyedir (API nedeniyle daha fazla olamaz). Peki ya clock, man sayfası "yaklaşım" hakkında konuşuyor, bu ne anlama geliyor? Peki ya clock_gettimeAPI nanosaniye cinsinden, temelde yatan donanım buna izin veriyorsa bu kadar doğru olabileceği anlamına mı geliyor? Ya monotonluk?

Başka işlevler var mı?

Yanıtlar:


199

Sorun, C ve C ++ 'da birkaç farklı zaman işlevi bulunması ve bunların bazılarının uygulamalar arasında davranış açısından farklılık göstermesidir. Ayrıca etrafta dolaşan birçok yarım cevap var. Saat işlevlerinin bir listesini özellikleriyle birlikte derlemek soruyu doğru yanıtlayacaktır. Başlangıç ​​olarak, aradığımız ilgili mülklerin neler olduğunu soralım. Gönderinize baktığınızda şunları öneririm:

  • Saat kaçta ölçülür? (gerçek, kullanıcı, sistem veya umarım duvar saati değil mi?)
  • Saatin hassasiyeti nedir? (s, ms, µs veya daha hızlı mı?)
  • Saat ne kadar zaman sonra dönüyor? Yoksa bundan kaçınmak için bir mekanizma var mı?
  • Saat monoton mu, yoksa sistem saatindeki değişikliklerle (NTP aracılığıyla, saat dilimi aracılığıyla, gün ışığından yararlanma saati aracılığıyla, kullanıcı tarafından vb.) Değişecek mi?
  • Yukarıdakiler uygulamalar arasında nasıl değişiklik gösterir?
  • Spesifik işlev eski mi, standart değil mi?

Listeye başlamadan önce, duvar saati zamanının nadiren kullanmak için doğru zaman olduğunu, ancak zaman dilimi değişiklikleri, gün ışığından yararlanma saati değişiklikleri veya duvar saati NTP ile senkronize edildikçe değiştiğini belirtmek isterim. Olayları planlamak veya performansı karşılaştırmak için zamanı kullanıyorsanız, bunların hiçbiri iyi değildir. Sadece ismin söylediği şey için gerçekten iyi, duvardaki (veya masaüstündeki) bir saat.

Linux ve OS X'teki saatler için şimdiye kadar bulduklarım:

  • time() İşletim Sisteminden duvar saati zamanını saniye cinsinden hassasiyetle döndürür.
  • clock()kullanıcı ve sistem süresinin toplamını döndürüyor gibi görünüyor. C89 ve sonrasında mevcuttur. Bir zamanlar bunun, döngülerde CPU zamanı olması gerekiyordu, ancak POSIX gibi modern standartlar , CLOCKS_PER_SEC'nin 1000000 olmasını gerektiriyor ve bu da 1 µs'lik maksimum bir hassasiyet sağlıyor. Sistemimdeki hassasiyet gerçekten 1 µs. Bu saat, bir kez bittiğinde etrafını sarar (bu genellikle ~ 2 ^ 32 tıklamadan sonra olur, bu 1 MHz saat için çok uzun değildir). man clockglibc 2.18'den beri clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)Linux'ta uygulandığını söylüyor .
  • clock_gettime(CLOCK_MONOTONIC, ...)nanosaniye çözünürlük sağlar, monotondur. Sanırım 'saniye' ve 'nanosaniye'nin her biri 32 bitlik sayaçlarda ayrı ayrı saklandığına inanıyorum. Bu nedenle, herhangi bir geri dönüş, düzinelerce yıllık çalışma süresinden sonra meydana gelir. Bu çok iyi bir saate benziyor, ancak ne yazık ki henüz OS X'te mevcut değil. POSIX 7 isteğe bağlı bir uzantı olarak tanımlıyorCLOCK_MONOTONIC .
  • getrusage()durumum için en iyi seçim olduğu ortaya çıktı. Kullanıcı ve sistem zamanlarını ayrı ayrı rapor eder ve etrafı sarmaz. Sistemimdeki hassasiyet 1 µs, ancak bunu bir Linux sisteminde de test ettim (GCC 4.1.2 ile Red Hat 4.1.2-48) ve orada hassasiyet sadece 1 ms idi.
  • gettimeofday()duvar saati zamanını (nominal olarak) µs hassasiyetle döndürür. Benim sistemimde bu saatin µs hassasiyete sahip olduğu görülüyor, ancak bu garanti edilmiyor, çünkü "sistem saatinin çözünürlüğü donanıma bağlıdır" . POSIX.1-2008 bunu söylüyor . "Uygulamalar clock_gettime()eskimiş işlev yerine işlevi kullanmalıdır gettimeofday()", bu nedenle ondan uzak durmalısınız. Linux x86 ve bunu bir sistem çağrısı olarak uygular .
  • mach_absolute_time()OS X'de çok yüksek çözünürlüklü (ns) zamanlama için bir seçenektir. Benim sistemimde bu gerçekten ns çözünürlüğü veriyor. Prensipte bu saat etrafını sarar, ancak ns'yi 64 bitlik işaretsiz bir tamsayı kullanarak depolar, bu nedenle etrafını sarmak pratikte bir sorun olmamalıdır. Taşınabilirlik sorgulanabilir.
  • Bu parçacığa dayalı olarak Linux'ta derlendiğinde clock_gettime kullanan hibrit bir işlev veya hem Linux hem de OS X'te ns hassasiyeti elde etmek için OS X'te derlendiğinde Mach timer yazdım.

Yukarıdakilerin tümü, aksi belirtilmedikçe hem Linux hem de OS X'te mevcuttur. Yukarıdaki "Sistemim", MacPorts'tan GCC 4.7.2 ile OS X 10.8.3 çalıştıran bir Apple'dır.

Son olarak, yukarıdaki bağlantılara ek olarak faydalı bulduğum referansların bir listesi:


Güncelleme : OS X için, clock_gettime10.12 (Sierra) itibarıyla uygulanmıştır. Ayrıca, hem POSIX hem de BSD tabanlı platformlar (OS X gibi) rusage.ru_utimeyapı alanını paylaşır .


Mac OS X yoktur clock_gettime, dolayısıyla kullanımı gettimeofday()daha çok yönlü bir Littleclock_gettime()
bobobobo

1
times()1. Sayı'dan beri POSIX'te var olan (bir s ile) bahsetmediniz. GNU / Linux ile ilgili olarak: Clock (3) clock()kılavuz sayfasına göre, glibc 2.17 ve önceki sürümlerden bunun üzerine uygulandı, ancak iyileştirildi hassas, artık clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...)POSIX'te de belirtilen ancak isteğe bağlı olan üstüne uygulanmıştır .
vinc17

2
@starflyer Saatin hassasiyeti, saati yoklamak için gereken süre ile kısmen sınırlıdır. Bunun nedeni, saati ararsam ve geri dönmesi 1 µs sürerse, arayanın perspektifinden saat raporları 1 µs kadar "kapalı" olacaktır. Bu, oldukça hassas bir saatin aynı zamanda düşük gecikmeli olması gerektiği anlamına gelir. Bu nedenle, tipik olarak, bahsettiğiniz değiş tokuşa sahip olmayacaksınız: en ucuz saatler aynı zamanda en doğru olanı olacaktır.
Douglas B. Staple

3
Ayrıca çoğu saat, duvar saati olarak kabul edilse bile, yaz saati / saat dilimlerini önemsemez . İkisi de timeve gettimeofdayen azından günümüzde, epoch'tan saniyeler sonra dönün (aka unix-zaman damgaları). Bu, saat dilimlerinden / DST'den bağımsızdır. Artık saniyeler başka bir hikaye ...
Zulan

2
Android kullanıcıları için CLOCK_MONOTONIC kullanmak sorunlu olabilir çünkü uygulama saatle birlikte askıya alınabilir. Bunun için Android, ioctl aracılığıyla erişilebilen ANDROID_ALARM_ELAPSED_REALTIME zamanlayıcıyı ekledi. bunlarla ilgili bazı bilgiler ve askıya alma ile ilgili diğer bilgiler burada
Itay Bianco

17

C11 timespec_get

Kullanım örneği: https://stackoverflow.com/a/36095407/895245

Döndürülen olası maksimum hassasiyet nanosaniyedir, ancak gerçek hassasiyet uygulama tanımlıdır ve daha küçük olabilir.

CPU kullanımını değil duvar zamanını döndürür.

glibc 2.21 bunu altında uygular sysdeps/posix/timespec_get.cve doğrudan şu adrese iletir:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimeve CLOCK_REALTIMEPOSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html'dir ve man clock_gettimeprogramınız çalışırken bazı sistem zamanı ayarını değiştirirseniz bu önlemin süreksizliklerinin olabileceğini söyler.

C ++ 11 krono

Biz oradayız, onları da ele alalım: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C ++ stdlib, GCC kaynağının içindedir):

  • high_resolution_clock için bir takma addır system_clock
  • system_clock mevcut olanlardan ilkine iletir:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock mevcut olanlardan ilkine iletir:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

: En Sorulan std :: system_clock ve std :: steady_clock arasındaki Fark?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: CLOCK_REALTIME ve CLOCK_MONOTONIC arasındaki fark?


1
Tipik uygulamaları açıklığa kavuşturan harika yanıt. İnsanların gerçekten bilmesi gereken şey bu.
Celess
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.