python's time.sleep () แม่นยำแค่ไหน?


95

ฉันสามารถให้ตัวเลขทศนิยมได้เช่น

time.sleep(0.5)

แต่มันแม่นยำแค่ไหน? ถ้าฉันให้มัน

time.sleep(0.05)

มันจะนอนประมาณ 50 ms จริงหรือ?

คำตอบ:


79

ความแม่นยำของเวลาฟังก์ชันการนอนหลับขึ้นอยู่กับความแม่นยำในการนอนหลับของระบบปฏิบัติการของคุณ สำหรับระบบปฏิบัติการที่ไม่ใช่แบบเรียลไทม์เช่น Windows ในสต็อกช่วงเวลาที่น้อยที่สุดที่คุณสามารถนอนหลับได้คือประมาณ 10-13ms ฉันได้เห็นการนอนหลับที่แม่นยำภายในไม่กี่มิลลิวินาทีของเวลานั้นเมื่อสูงกว่าค่าต่ำสุด 10-13 มิลลิวินาที

อัปเดต: เช่นเดียวกับที่กล่าวไว้ในเอกสารที่อ้างถึงด้านล่างเป็นเรื่องปกติที่จะนอนหลับเป็นวงรอบซึ่งจะทำให้คุณกลับไปนอนหลับได้หากตื่น แต่เช้า

ฉันควรพูดถึงว่าหากคุณใช้ Ubuntu คุณสามารถลองใช้เคอร์เนลหลอกแบบเรียลไทม์ (ด้วยชุดแพทช์ RT_PREEMPT) โดยติดตั้งแพ็คเกจเคอร์เนล rt (อย่างน้อยใน Ubuntu 10.04 LTS)

แก้ไข: การแก้ไขเคอร์เนลลินุกซ์ที่ไม่ใช่เรียลไทม์มีช่วงเวลาการนอนหลับขั้นต่ำที่ใกล้ 1ms จากนั้น 10ms แต่จะแตกต่างกันไปในลักษณะที่ไม่ได้กำหนด


8
จริงๆแล้วเคอร์เนลของลินุกซ์มีค่าเริ่มต้นที่อัตราเห็บที่สูงขึ้นมาระยะหนึ่งแล้วดังนั้นการนอนหลับ "ขั้นต่ำ" จึงใกล้ 1 มิลลิวินาทีมากกว่า 10 มิลลิวินาที ไม่รับประกัน - กิจกรรมของระบบอื่น ๆ อาจทำให้เคอร์เนลไม่สามารถกำหนดเวลากระบวนการของคุณได้ทันทีที่คุณต้องการแม้ว่าจะไม่มีข้อโต้แย้งของ CPU ก็ตาม นั่นคือสิ่งที่เมล็ดแบบเรียลไทม์พยายามแก้ไขฉันคิดว่า แต่ถ้าคุณไม่ต้องการพฤติกรรมแบบเรียลไทม์เพียงแค่ใช้อัตราเห็บสูง (การตั้งค่าเคอร์เนล HZ) จะทำให้คุณไม่ได้รับการรับประกัน แต่มีความละเอียดสูงใน Linux โดยไม่ต้องใช้อะไรเป็นพิเศษ
Glenn Maynard

1
ใช่คุณพูดถูกฉันลองใช้ Linux 2.6.24-24 และสามารถรับอัตราการอัปเดตได้เกือบถึง 1,000 Hz ในขณะที่ฉันกำลังทำสิ่งนี้ฉันกำลังเรียกใช้รหัสบน Mac และ Windows ด้วยดังนั้นฉันอาจสับสน ฉันรู้ว่า windows XP อย่างน้อยมีอัตราเห็บประมาณ 10ms
Joseph Lisee

ใน Windows 8 ฉันใช้เวลาน้อยกว่า 2ms
markmnl

2
นอกจากนี้ความแม่นยำไม่ได้ขึ้นอยู่กับระบบปฏิบัติการเพียงอย่างเดียว แต่สิ่งที่ระบบปฏิบัติการกำลังทำบนทั้ง Windows และ Linux หากพวกเขายุ่งอยู่กับการทำสิ่งที่สำคัญกว่าsleep()จากเอกสาร "เวลาในการระงับอาจนานกว่าที่ร้องขอโดยพลการเนื่องจากการกำหนดเวลาของ กิจกรรมอื่น ๆ ในระบบ ".
markmnl

56

ผู้คนค่อนข้างถูกต้องเกี่ยวกับความแตกต่างระหว่างระบบปฏิบัติการและเมล็ด แต่ฉันไม่เห็นรายละเอียดใด ๆ ใน Ubuntu และฉันเห็นความละเอียด 1 มิลลิวินาทีใน MS7 แนะนำการใช้งานเวลานอนที่แตกต่างกันไม่ใช่แค่อัตราเห็บที่แตกต่างกัน การตรวจสอบอย่างใกล้ชิดแสดงให้เห็นถึงความละเอียด1μsใน Ubuntu แต่นั่นเป็นเพราะฟังก์ชัน time.time ที่ฉันใช้ในการวัดความแม่นยำ เวลาปกติของ Linux และ Windows พฤติกรรมการนอนหลับใน Python


6
เป็นเรื่องที่น่าสนใจว่า Linux เลือกที่จะเข้าสู่โหมดสลีปนานกว่าที่ร้องขอเล็กน้อยในขณะที่ Microsoft เลือกแนวทางตรงกันข้าม
jleahy

2
@jleahy - วิธีการของ linux มีความหมายสำหรับฉัน: การนอนหลับเป็นการปล่อยลำดับความสำคัญของการดำเนินการเป็นระยะเวลาหนึ่งหลังจากนั้นคุณจะส่งตัวเองไปตามความประสงค์ของตัวกำหนดตารางเวลาอีกครั้ง (ซึ่งอาจกำหนดหรือไม่กำหนดเวลาให้คุณดำเนินการทันที) .
การ

2
คุณได้ผลลัพธ์อย่างไร คุณสามารถให้ซอร์สโค้ดได้หรือไม่? กราฟดูเหมือนสิ่งประดิษฐ์ของการใช้ตัวจับเวลาที่แตกต่างกันในการวัดเวลาและการนอนหลับ (โดยหลักการแล้วคุณสามารถใช้การเลื่อนระหว่างตัวจับเวลาเป็นแหล่งที่มาของการสุ่ม )
jfs

2
@JF เซบาสเตียน - ฟังก์ชั่นที่ผมใช้อยู่ในsocsci.ru.nl/wilberth/computer/sleepAccuracy.html กราฟที่สามแสดงเอฟเฟกต์คล้ายกับสิ่งที่คุณเห็น แต่มีเพียง 1 ‰
Wilbert

1
@JF Sebastian ฉันใช้ time.clock () บน windows
Wilbert

26

จากเอกสารประกอบ :

บนมืออื่น ๆ , ความแม่นยำของ time()และsleep()จะดีกว่าเทียบเท่ายูนิกซ์ของพวกเขาครั้งจะแสดงเป็นตัวเลขทศนิยม, time()ส่งกลับเวลาที่ถูกต้องที่สุดที่มีอยู่ (โดยใช้ระบบปฏิบัติการยูนิกซ์gettimeofday มี) และsleep()จะยอมรับเวลากับส่วนที่ไม่ใช่ศูนย์ A (Unix selectถูกนำมาใช้ เพื่อใช้สิ่งนี้หากมี)

และโดยเฉพาะมากขึ้น wrt sleep():

ระงับการดำเนินการตามจำนวนวินาทีที่กำหนด อาร์กิวเมนต์อาจเป็นตัวเลขทศนิยมเพื่อระบุเวลานอนหลับที่แม่นยำยิ่งขึ้น เวลาระงับจริงอาจน้อยกว่าที่ร้องขอเนื่องจากสัญญาณที่จับได้จะยุติการsleep()ดำเนินการตามขั้นตอนการจับสัญญาณดังต่อไปนี้ นอกจากนี้เวลาระงับอาจนานกว่าที่ร้องขอโดยพลการเนื่องจากการจัดกำหนดการของกิจกรรมอื่น ๆ ในระบบ


1
ใครสามารถอธิบาย "เนื่องจากสัญญาณใด ๆ ที่จับได้จะยุติการนอนหลับ () หลังจากดำเนินการตามขั้นตอนการจับสัญญาณนั้น" มันหมายถึงสัญญาณใด ขอบคุณ!
Diego Herranz

1
สัญญาณเป็นเหมือนการแจ้งเตือนที่ระบบปฏิบัติการจัดการ ( en.wikipedia.org/wiki/Unix_signal ) หมายความว่าหากระบบปฏิบัติการจับสัญญาณได้การนอนหลับ () จะเสร็จสิ้นหลังจากปฏิบัติต่อสัญญาณนั้น
ArianJM

25

นี่คือการติดตามคำตอบของ Wilbert: เช่นเดียวกับ Mac OS X Yosemite เนื่องจากยังไม่ได้รับการกล่าวถึงมากนักพฤติกรรมการนอนหลับของ Mac OS X Yosemite

ดูเหมือนว่าส่วนมากจะนอนประมาณ 1.25 เท่าของเวลาที่คุณขอและบางครั้งก็นอนระหว่าง 1 ถึง 1.25 เท่าของเวลาที่คุณขอ แทบไม่เคยเลย (~ สองเท่าจาก 1,000 ตัวอย่าง) นอนหลับมากกว่า 1.25 เท่าของเวลาที่คุณร้องขออย่างมีนัยสำคัญ

นอกจากนี้ (ไม่ได้แสดงอย่างชัดเจน) ความสัมพันธ์ 1.25 ดูเหมือนจะค่อนข้างดีจนกว่าคุณจะได้ต่ำกว่า 0.2 ms หลังจากนั้นมันก็เริ่มเลือนลางเล็กน้อย นอกจากนี้เวลาจริงดูเหมือนว่าจะยาวกว่าที่คุณร้องขอประมาณ 5 มิลลิวินาทีหลังจากระยะเวลาที่ร้องขอสูงกว่า 20 มิลลิวินาที

อีกครั้งดูเหมือนว่าจะเป็นการใช้งานsleep()ใน OS X ที่แตกต่างอย่างสิ้นเชิงกับใน Windows หรือที่เคอร์เนลของลินุกซ์ที่ Wilbert ใช้อยู่


คุณสามารถอัปโหลดซอร์สโค้ดสำหรับเกณฑ์มาตรฐานไปยัง github / bitbucket ได้หรือไม่
jfs

3
ฉันได้ลองใช้กับเครื่องของฉันแล้ว ผลลัพธ์คล้ายกับคำตอบของ @ วิลเบิร์
jfs

ฉันเดาว่าการนอนหลับนั้นแม่นยำ แต่การตั้งเวลาของ Mac OS X นั้นไม่แม่นยำพอที่จะให้ CPU เร็วพอที่จะทำให้การปลุกจากโหมดสลีปล่าช้า หากเวลาตื่นที่ถูกต้องมีความสำคัญดูเหมือนว่าควรตั้งเวลานอนเป็น 0.75 เท่าของเวลาที่ร้องขอจริงและตรวจสอบเวลาหลังจากตื่นนอนและนอนซ้ำ ๆ ให้น้อยลงเรื่อย ๆ จนกว่าจะถึงเวลาที่ถูกต้อง
Mikko Rantalainen

17

ทำไมคุณไม่ค้นหา:

from datetime import datetime
import time

def check_sleep(amount):
    start = datetime.now()
    time.sleep(amount)
    end = datetime.now()
    delta = end-start
    return delta.seconds + delta.microseconds/1000000.

error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error

สำหรับบันทึกฉันพบข้อผิดพลาดประมาณ 0.1ms ใน HTPC และ 2ms บนแล็ปท็อปของฉันทั้งเครื่อง linux


10
การทดสอบเชิงประจักษ์จะทำให้คุณมีมุมมองที่แคบมาก มีหลายเคอร์เนลระบบปฏิบัติการและการกำหนดค่าเคอร์เนลที่มีผลต่อสิ่งนี้ เคอร์เนล Linux รุ่นเก่าจะมีอัตราติ๊กต่ำกว่าซึ่งส่งผลให้มีความละเอียดมากขึ้น ในการใช้งาน Unix สัญญาณภายนอกระหว่างโหมดสลีปจะยกเลิกเมื่อใดก็ได้และการใช้งานอื่น ๆ อาจมีการหยุดชะงักที่คล้ายกัน
Glenn Maynard

6
แน่นอนว่าการสังเกตเชิงประจักษ์นั้นไม่สามารถถ่ายโอนได้ นอกเหนือจากระบบปฏิบัติการและเคอร์เนลแล้วยังมีปัญหาชั่วคราวอีกมากมายที่ส่งผลกระทบต่อสิ่งนี้ หากจำเป็นต้องมีการรับประกันแบบ Hard Real Time การออกแบบระบบทั้งหมดตั้งแต่ฮาร์ดแวร์ขึ้นไปจะต้องนำมาพิจารณาด้วย ฉันเพิ่งพบผลลัพธ์ที่เกี่ยวข้องเมื่อพิจารณาจากข้อความที่ 10ms เป็นความแม่นยำขั้นต่ำ ฉันไม่ได้อยู่ที่บ้านในโลกของ Windows แต่ linux distros ส่วนใหญ่ใช้เมล็ดพันธุ์แบบไม่ต้องใช้น้ำมันมาระยะหนึ่งแล้ว ด้วยมัลติคอร์ที่แพร่หลายในขณะนี้มีแนวโน้มที่จะได้รับการกำหนดเวลาไว้ใกล้กับการหมดเวลา
Ants Aasma

4

การแก้ไขเล็กน้อยหลายคนพูดถึงว่าการนอนหลับสามารถยุติได้เร็วด้วยสัญญาณ ใน3.6 เอกสารระบุว่า

การเปลี่ยนแปลงในเวอร์ชัน 3.5: ขณะนี้ฟังก์ชันจะเข้าสู่โหมดสลีปอย่างน้อยวินาทีแม้ว่าการสลีปจะถูกขัดจังหวะด้วยสัญญาณยกเว้นว่าตัวจัดการสัญญาณจะยกข้อยกเว้น (ดูPEP 475สำหรับเหตุผล)


3

คุณไม่สามารถรับประกันอะไรเกี่ยวกับการนอนหลับได้จริงๆ () ยกเว้นว่าอย่างน้อยก็จะพยายามอย่างเต็มที่ที่จะนอนหลับให้นานที่สุดเท่าที่คุณบอกไว้ (สัญญาณสามารถฆ่าการนอนหลับของคุณก่อนเวลาจะหมดและสิ่งอื่น ๆ อีกมากมายที่สามารถทำให้มันทำงานได้ ยาว).

แน่นอนว่าขั้นต่ำที่คุณจะได้รับบนระบบปฏิบัติการเดสก์ท็อปมาตรฐานจะอยู่ที่ประมาณ 16ms (ความละเอียดของตัวจับเวลาบวกเวลาในการสลับบริบท) แต่โอกาสที่ค่าเบี่ยงเบน% จากอาร์กิวเมนต์ที่ให้มาจะมีความสำคัญเมื่อคุณพยายาม เข้านอนเป็นเวลา 10 วินาทีของมิลลิวินาที

สัญญาณ, เธรดอื่น ๆ ที่ถือ GIL, ความสนุกสนานในการตั้งเวลาเคอร์เนล, การเพิ่มความเร็วของโปรเซสเซอร์ ฯลฯ ทั้งหมดสามารถสร้างความเสียหายได้ด้วยระยะเวลาที่เธรด / กระบวนการของคุณเข้าสู่โหมดสลีป


3
เอกสารระบุเป็นอย่างอื่น:> เวลาระงับจริงอาจน้อยกว่าที่ร้องขอเนื่องจากสัญญาณที่จับได้จะยุติการนอนหลับ () หลังจากดำเนินการตามขั้นตอนการจับสัญญาณนั้น
Glenn Maynard

อายุติธรรมแก้ไขโพสต์แม้ว่าการนอนหลับนานขึ้น () มีแนวโน้มมากกว่าคนที่สั้นกว่ามาก
Nick Bastin

1
สองปีครึ่งต่อมา ... เอกสารยังคงอยู่ บน Windows สัญญาณจะไม่ยุติการนอนหลับ () ทดสอบกับ Python 3.2, WinXP SP3
Dave

ใช่ แต่สัญญาณการล้างออกก่อนนอนผิดปกติเช่น KILL เอกสารยังระบุว่า: "นอกจากนี้เวลาระงับอาจนานกว่าที่ร้องขอโดยพลการเนื่องจากการจัดตารางกิจกรรมอื่น ๆ ในระบบ" ซึ่งเป็นเรื่องปกติมากขึ้น
markmnl

1
Singnals และ Windows นั้นโง่มาก ใน Windows Python time.sleep () จะรอบน ConsoleEvent เพื่อจับภาพสิ่งต่างๆเช่น Ctrl-C
schlenk

1

หากคุณต้องการความแม่นยำมากขึ้นหรือลดเวลาในการนอนให้ลองตัดสินใจด้วยตัวคุณเอง:

import time

def sleep(duration, get_now=time.perf_counter):
    now = get_now()
    end = now + duration
    while now < end:
        now = get_now()


0
def start(self):
    sec_arg = 10.0
    cptr = 0
    time_start = time.time()
    time_init = time.time()
    while True:
        cptr += 1
        time_start = time.time()
        time.sleep(((time_init + (sec_arg * cptr)) - time_start ))

        # AND YOUR CODE .......
        t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
        t00.start()

อย่าใช้ตัวแปรเพื่อส่งผ่านอาร์กิวเมนต์ของการนอนหลับ () คุณต้องแทรกการคำนวณลงในโหมดสลีปโดยตรง ()


และการกลับมาของขั้วของฉัน

1 นาที 17: 20: 16.891 ───────────────────

2 นาที 17: 20: 18.891 ───────────────────

3 นาที 17: 20: 20.891 ───────────────────

4 นาที 17: 20: 22.891 ───────────────────

5 นาที 17: 20: 24.891 ───────────────────

....

689 ─── 17: 43: 12.891 ────────────────────

690 ─── 17: 43: 14.890 ────────────────────

691 ─── 17: 43: 16.891 ────────────────────

692 ─── 17: 43: 18.890 ────────────────────

693 ─── 17: 43: 20.891 ────────────────────

...

727 ─── 17: 44: 28.891 ────────────────────

728 ─── 17: 44: 30.891 ────────────────────

729 ─── 17: 44: 32.891 ────────────────────

730 ─── 17: 44: 34.890 ────────────────────

731 ─── 17: 44: 36.891 ────────────────────


0
def test():
    then = time.time()  # get time at the moment
    x = 0
    while time.time() <= then+1:  # stop looping after 1 second
        x += 1
        time.sleep(0.001)  # sleep for 1 ms
    print(x)

บน windows 7 / Python 3.8 ส่งคืน1000สำหรับฉันแม้ว่าฉันจะตั้งค่าการนอนหลับเป็น0.0005

1 มิลลิวินาทีที่สมบูรณ์แบบ

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