วัดเวลาใน Linux - เวลาเทียบกับนาฬิกาเทียบกับ getrusage เทียบกับ clock_gettime เทียบกับ gettimeofday เทียบกับ timespec_get?


148

ท่ามกลางฟังก์ชั่นจับเวลา, time, clock getrusage, clock_gettime, gettimeofdayและtimespec_getผมต้องการที่จะเข้าใจอย่างชัดเจนว่าพวกเขาจะดำเนินการและสิ่งที่มีค่าที่พวกเขากลับมาเพื่อที่จะทราบซึ่งในสถานการณ์ที่ผมต้องใช้พวกเขา

แรกที่เราต้องฟังก์ชั่นประเภทกลับค่าผนังนาฬิกาเปรียบเทียบกับฟังก์ชั่นที่กลับมากระบวนการหรือหัวข้อค่า gettimeofdayส่งคืนค่านาฬิกาแขวนclock_gettimeส่งคืนค่านาฬิกาแขวนหรือค่ากระบวนการหรือเธรดขึ้นอยู่กับClockพารามิเตอร์ที่ส่งผ่านไป getrusageและclockคืนค่ากระบวนการ

จากนั้นคำถามที่สองเกี่ยวกับการใช้งานฟังก์ชั่นเหล่านี้และเป็นผลให้ความถูกต้องของพวกเขา ฟังก์ชันเหล่านี้ใช้กลไกฮาร์ดแวร์หรือซอฟต์แวร์ใด

ดูเหมือนว่าgetrusageจะใช้เฉพาะเคอร์เนลเห็บ (โดยทั่วไปจะมีความยาว 1 มิลลิวินาที) และด้วยเหตุนี้จึงไม่แม่นยำกว่า ms ถูกต้องหรือไม่ จากนั้นgetimeofdayฟังก์ชั่นการใช้งานดูเหมือนว่าจะถูกต้องมากที่สุดฮาร์ดแวร์พื้นฐานที่มีอยู่ ผลที่ตามมาคือความถูกต้องแม่นยำคือไมโครวินาที (ไม่สามารถมากไปกว่าเพราะ API) บนฮาร์ดแวร์ล่าสุด สิ่งที่เกี่ยวกับclockหน้าพูดคนเกี่ยวกับ "ประมาณ" มันหมายความว่าอะไร? สิ่งที่เกี่ยวกับclock_gettimeAPI อยู่ในระดับนาโนวินาทีหมายความว่าสามารถแม่นยำได้หรือไม่ถ้าฮาร์ดแวร์พื้นฐานอนุญาต? แล้วเรื่อง monotonicity ล่ะ?

มีฟังก์ชั่นอื่น ๆ อีกหรือไม่?

คำตอบ:


198

ปัญหาคือมีฟังก์ชั่นเวลาที่แตกต่างกันหลายอย่างใน C และ C ++ และบางฟังก์ชันแตกต่างกันไปในระหว่างการใช้งาน นอกจากนี้ยังมีคำตอบครึ่งคำถามมากมายที่ลอยอยู่รอบ ๆ รวบรวมรายการฟังก์ชั่นนาฬิกาพร้อมกับคุณสมบัติของพวกเขาจะตอบคำถามได้อย่างถูกต้อง สำหรับการเริ่มต้นลองถามคุณสมบัติที่เกี่ยวข้องที่เรากำลังมองหา ดูที่โพสต์ของคุณฉันแนะนำ:

  • นาฬิกาวัดเวลากี่โมง? (ของจริง, ผู้ใช้, ระบบ, หรือหวังว่าจะไม่เป็นนาฬิกาแขวนเหรอ?)
  • ความแม่นยำของนาฬิกาคืออะไร? (s, ms, µs หรือเร็วกว่า?)
  • หลังจากเวลาเท่าไหร่นาฬิกาห่อรอบ? หรือมีกลไกที่จะหลีกเลี่ยงสิ่งนี้หรือไม่?
  • เป็นสัญญาณนาฬิกาเดียวหรือเปลี่ยนแปลงกับการเปลี่ยนแปลงเวลาของระบบ (ผ่าน NTP, โซนเวลา, เวลาออมแสงตามฤดูกาลโดยผู้ใช้ ฯลฯ ) หรือไม่
  • ข้างต้นแตกต่างกันอย่างไรระหว่างการใช้งาน?
  • ฟังก์ชั่นเฉพาะล้าสมัยไม่ได้มาตรฐานหรือไม่?

ก่อนที่จะเริ่มรายการฉันต้องการชี้ให้เห็นว่าเวลานาฬิกาแขวนไม่ค่อยเหมาะกับการใช้งานในขณะที่มันเปลี่ยนไปตามการเปลี่ยนแปลงเขตเวลาการปรับเวลาออมแสงหรือ NTP ของนาฬิกาแขวนจะถูกซิงโครไนซ์ สิ่งเหล่านี้ไม่ดีเลยถ้าคุณใช้เวลาเพื่อกำหนดเวลาเหตุการณ์หรือเพื่อการวัดประสิทธิภาพ เป็นสิ่งที่ดีจริงๆสำหรับสิ่งที่ชื่อพูดนาฬิกาบนผนัง (หรือเดสก์ท็อป)

นี่คือสิ่งที่ฉันพบสำหรับนาฬิกาใน Linux และ OS X:

  • time() ส่งคืนเวลานาฬิกาแขวนจากระบบปฏิบัติการด้วยความแม่นยำในไม่กี่วินาที
  • clock()ดูเหมือนว่าจะส่งคืนผลรวมของผู้ใช้และเวลาของระบบ มันมีอยู่ใน C89 และต่อมา ในครั้งนี้ควรจะเป็นเวลา CPU ในรอบ แต่มาตรฐานที่ทันสมัยเช่น POSIXต้องการ CLOCKS_PER_SEC เป็น 1000000 ให้ความแม่นยำสูงสุดที่เป็นไปได้ 1 µs ความแม่นยำในระบบของฉันคือ 1 .s นาฬิกานี้ล้อมรอบเมื่อมันเต็ม (โดยปกติจะเกิดหลังจาก ~ 2 ^ 32 เห็บซึ่งไม่นานมากสำหรับนาฬิกา 1 MHz) man clockกล่าวว่าตั้งแต่ glibc 2.18 มันถูกนำมาใช้กับclock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)ใน Linux
  • clock_gettime(CLOCK_MONOTONIC, ...)ให้ความละเอียดระดับนาโนวินาทีเป็นแบบโมโนโพนิค ฉันเชื่อว่า 'วินาที' และ 'nanoseconds' จะถูกจัดเก็บแยกกันแต่ละตัวมี 32 บิต ดังนั้นการพันรอบจะเกิดขึ้นหลังจากเวลาผ่านไปหลายสิบปี ดูเหมือนว่าจะเป็นนาฬิกาที่ดีมาก แต่น่าเสียดายที่ยังไม่มีใน OS X POSIX 7 อธิบายCLOCK_MONOTONICว่าเป็นส่วนขยายเพิ่มเติม
  • getrusage()กลายเป็นตัวเลือกที่ดีที่สุดสำหรับสถานการณ์ของฉัน รายงานผู้ใช้และเวลาของระบบแยกจากกันและไม่ล้อมรอบ ความแม่นยำในระบบของฉันคือ 1 buts แต่ฉันยังทดสอบบนระบบ Linux (Red Hat 4.1.2-48 กับ GCC 4.1.2) และมีความแม่นยำเพียง 1 ms
  • gettimeofday()ส่งคืนนาฬิกาแขวนด้วยความแม่นยำ (ในนาม) ในระบบของฉันนาฬิกานี้ดูเหมือนจะมีความแม่นยำไมโครวินาที แต่ไม่รับประกันเพราะ"ความละเอียดของนาฬิการะบบคือขึ้นอยู่กับฮาร์ดแวร์" POSIX.1-2008 กล่าวว่า "แอปพลิเคชันควรใช้clock_gettime()ฟังก์ชั่นแทนฟังก์ชั่นล้าสมัยgettimeofday()" ดังนั้นคุณควรอยู่ห่างจากมัน ลินุกซ์ x86 และการดำเนินการมันเป็นสายระบบ
  • mach_absolute_time()เป็นตัวเลือกสำหรับการกำหนดเวลาความละเอียดสูง (ns) บน OS X สำหรับระบบของฉันสิ่งนี้จะให้ความละเอียด ns ตามหลักการแล้วนาฬิกาเรือนนี้ล้อมรอบอย่างไรก็ตามมันกำลังเก็บ ns โดยใช้จำนวนเต็ม 64 บิตที่ไม่ได้ลงชื่อดังนั้นการล้อมรอบไม่น่าจะเป็นปัญหาในทางปฏิบัติ การพกพาเป็นที่น่าสงสัย
  • ฉันเขียนฟังก์ชันไฮบริดตามตัวอย่างนี้ที่ใช้ clock_gettime เมื่อรวบรวมบน Linux หรือ Mach timer เมื่อรวบรวมบน OS X เพื่อให้แม่นยำ ns ทั้ง Linux และ OS X

ทั้งหมดข้างต้นมีอยู่ในทั้ง Linux และ OS X ยกเว้นที่ระบุไว้เป็นอย่างอื่น "ระบบของฉัน" ด้านบนเป็น Apple ที่ใช้ OS X 10.8.3 พร้อม GCC 4.7.2 จาก MacPorts

สุดท้ายนี่คือรายการของข้อมูลอ้างอิงที่ฉันพบว่ามีประโยชน์นอกเหนือจากลิงก์ด้านบน:


อัปเดต : สำหรับ OS X clock_gettimeมีการใช้งานตั้งแต่ 10.12 (เซีย) นอกจากนี้แพลตฟอร์มทั้ง POSIX และ BSD (เช่น OS X) จะแชร์rusage.ru_utimeฟิลด์ struct


Mac OS X ไม่มีclock_gettimeดังนั้นการใช้งานที่gettimeofday()หลากหลายกว่าclock_gettime()
นิดหน่อย

1
คุณยังไม่ได้พูดถึงtimes()(ที่มี) ซึ่งมีอยู่ใน POSIX ตั้งแต่รุ่นที่ 1 เกี่ยวกับ GNU / Linux: ตามหน้านาฬิกา (3) man page clock()จาก glibc 2.17 และก่อนหน้านี้ถูกนำมาใช้ด้านบน แต่ปรับปรุงให้ดีขึ้น ความแม่นยำตอนนี้มันถูกนำไปใช้ด้านบนของclock_gettime(CLOCK_PROCESS_CPUTIME_ID,...)ซึ่งยังระบุใน POSIX แต่เป็นตัวเลือก
vinc17

2
@ starflyer ความแม่นยำของนาฬิกาถูก จำกัด บางส่วนตามระยะเวลาที่ใช้ในการสำรวจนาฬิกา นี่เป็นเพราะถ้าฉันเรียกนาฬิกาและมันใช้เวลา 1 µs ในการส่งคืนดังนั้นเวลาที่นาฬิการายงานจะถูก "ปิด" โดย 1 froms จากมุมมองของผู้โทร ซึ่งหมายความว่านาฬิกาที่มีความแม่นยำสูงจะต้องมีความหน่วงต่ำ ดังนั้นโดยทั่วไปจะไม่มีการแลกเปลี่ยนที่คุณพูดถึง: นาฬิกาที่ถูกที่สุดจะแม่นยำที่สุดเช่นกัน
Douglas B. Staple

3
นาฬิกาส่วนใหญ่ไม่สนใจเกี่ยวกับการปรับเวลาตามฤดูกาล / โซนเวลาแม้ว่าจะถือว่าเป็นนาฬิกาติดผนังก็ตาม ทั้งสองอย่างtimeและgettimeofdayกลับมาอย่างน้อยทุกวันนี้มีวินาทีตั้งแต่ยุค (aka unix-timestamps) นี่เป็นอิสระจากโซนเวลา / DST Leap วินาทีเป็นอีกเรื่องหนึ่ง ...
Zulan

2
สำหรับผู้ใช้ Android การใช้ CLOCK_MONOTONIC อาจมีปัญหาเนื่องจากแอพอาจถูกระงับพร้อมกับนาฬิกา สำหรับสิ่งนั้น Android ได้เพิ่มตัวจับเวลา ANDROID_ALARM_ELAPSED_REALTIME ที่สามารถเข้าถึงได้ผ่าน ioctl ข้อมูลบางอย่างเกี่ยวกับข้อมูลเหล่านี้และข้อมูลอื่น ๆ ที่เกี่ยวข้องกับการระงับสามารถพบได้ที่นี่
Itay Bianco

17

C11 timespec_get

ตัวอย่างการใช้งานที่: https://stackoverflow.com/a/36095407/895245

ความแม่นยำที่เป็นไปได้สูงสุดที่ส่งคืนคือนาโนวินาที แต่ความแม่นยำที่แท้จริงถูกกำหนดไว้ในการติดตั้งและอาจมีขนาดเล็กลง

มันคืนค่าเวลากำแพงไม่ใช่การใช้ CPU

glibc 2.21 ใช้มันภายใต้sysdeps/posix/timespec_get.cและส่งต่อโดยตรงไปที่:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimeและCLOCK_REALTIMEเป็น POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.htmlและman clock_gettimeบอกว่ามาตรการนี้อาจไม่ต่อเนื่องหากคุณเปลี่ยนการตั้งค่าเวลาของระบบในขณะที่โปรแกรมของคุณทำงาน

C ++ 11 chrono

เนื่องจากเราอยู่ที่นี่เรามาครอบคลุมกันด้วย: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C ++ stdlib อยู่ในแหล่ง GCC):

  • high_resolution_clock เป็นชื่อแทน system_clock
  • system_clock ส่งต่อไปยังรายการแรกของรายการต่อไปนี้ที่มีอยู่:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock ส่งต่อไปยังรายการแรกของรายการต่อไปนี้ที่มีอยู่:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

ถามเมื่อ: ความแตกต่างระหว่าง std :: system_clock และ std :: steady_clock?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: ความแตกต่างระหว่าง CLOCK_REALTIME และ CLOCK_MONOTONIC หรือไม่


1
คำตอบที่ยอดเยี่ยมที่ให้ความเข้าใจอย่างลึกซึ้งถึงการนำไปปฏิบัติโดยทั่วไป นั่นคือสิ่งที่ผู้คนจำเป็นต้องรู้
ไม่มี
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.