簡體   English   中英

為什么 time.sleep() 准確性受 Chrome 影響?

[英]Why is time.sleep() accuracy influenced by Chrome?

我注意到一些奇怪的行為,這些行為可能特定於也可能不是特定於我的系統。 (運行 Windows 8 的聯想 t430)

使用這個腳本:

import time

now = time.time()
while True:
    then = now
    now = time.time()
    dif = now - then
    print(dif)
    time.sleep(0.01)

在瀏覽器打開的情況下,我得到以下輸出(我認為是名義上的)。

在此處輸入圖片說明

但是,如果沒有打開瀏覽器,我會觀察到嚴重的每個循環延遲。

在此處輸入圖片說明

顯然,這是違反直覺的,因為我認為當並發進程較少時,任何人都希望獲得更好的性能。

對這些結果的任何見解或簡單復制將不勝感激。

編輯:有趣的是,我觀察到與此代碼類似的延遲:

import time

now = time.time()

def newSleep(mark,duration):
    count = 0
    while time.time()-mark < duration:
        count+=1
    print(count)


while True:
    then = now
    now = time.time()
    dif = now - then
    print(dif)
    #time.sleep(0.01)
    newSleep(now,0.01)

雖然它確實提供了額外的洞察力 - 那是一些潛在循環的實例是由於缺乏處理器可用性(通過打印 0 的計數來表示) - 我仍然注意到 15ms 的行為,其中打印的計數將高達 70k.. . 和 10 毫秒的行為,計數約為 40k。

我額外啟動了 Windows 7 來復制你的發現,我可以確認。

它是Windows 的東西,使用的計時器類型和默認分辨率為 15.6 毫秒(最小 0.5 毫秒)。 應用程序可以更改當前分辨率(WinAPI 函數: timeBeginPeriod ),而 Chrome 會這樣做

此功能會影響全局 Windows 設置。 Windows 使用任何進程請求的最低值(即最高分辨率)。 設置更高的分辨率可以提高等待函數中超時間隔的准確性。 但是,它也會降低整體系統性能,因為線程調度程序更頻繁地切換任務。 高分辨率還可以防止 CPU 電源管理系統進入省電模式。 設置更高的分辨率不會提高高分辨率性能計數器的准確性。

福布斯2014 年的一篇文章介紹了 Chrome 中的一個錯誤,無論當前負載需要什么,該錯誤都會將分辨率永久設置為 1 毫秒——這是一個問題,因為它是一個系統范圍的影響,對能源消耗有影響。 從那篇文章:

在像 Windows 這樣的操作系統中,事件通常被設置為每隔一段時間運行一次。 為了省電,處理器在沒有任何需要注意的時候休眠,並在預定義的時間間隔喚醒。 這個間隔是 Chrome 在 Windows 中調整的,因此將其減少到 1.000 毫秒意味着系統喚醒的頻率遠高於 15.625 毫秒。 事實上,在 1.000 毫秒時,處理器每秒喚醒 1000 次。 默認值 15.625 毫秒意味着處理器每秒僅喚醒 64 次以檢查需要注意的事件。

微軟自己表示,1.000 毫秒的滴答率可能會使功耗增加“多達 25%”。

您可以使用time.get_clock_info()從 Python 獲取默認分辨率。

namespace = time.get_clock_info('time')
namespace.adjustable
# True
namespace.implementation
# 'GetSystemTimeAsFileTime()'
namespace.monotonic
# False
namespace.resolution
# 0.015600099999999999

您可以使用ClockRes小程序從cmd獲取實際分辨率。

我在 windows 和 ubuntu 服務器(virtualbox)(沒有瀏覽器)中嘗試了相同的方法,但結果是相同的,我得到的平均值是

在 Ubuntu 服務器中

    0.010122537612915039
    0.010426998138427734
    0.010067939758300781
    0.010767221450805664
    0.010728120803833008
    0.010106086730957031
    0.01068258285522461
    0.010105609893798828
    0.01118612289428711
    0.010136842727661133
    0.010585784912109375
    0.010425567626953125
    0.01014852523803711
    0.010422945022583008
    0.01010894775390625

在 Windows 中

    0.010767221450805664
    0.010751485824584961
    0.010716915130615234
    0.010229110717773438
    0.01016545295715332
    0.010195255279541016
    0.010723352432250977
    0.010744094848632812
    0.010716438293457031
    0.010564565658569336
    0.010889291763305664
    0.010728597640991211
    0.010579824447631836
    0.010889530181884766
    0.010567903518676758
    0.010717153549194336
    0.010735273361206055

所以,在我看來,打開的瀏覽器和 python 的性能之間沒有相關性

對這些結果的任何見解或簡單復制將不勝感激。

干得好:

使用您的代碼和最新版本的 Chrome,我可以用幾乎相同的結果確認這種行為。

我測量了平均花費的時間-

瀏覽器運行:0.01055538261329734

瀏覽器未運行:0.01563055389053695

我有大約 30 個打開的選項卡,但它們都空閑。 目前,我想不出任何原因會發生這種情況。

期待進一步的見解。

雖然我無法在我的機器上重現這種行為,但我懷疑它可能是由動態處理器時鍾(以及內存和系統總線時鍾)引起的,例如,當您沒有打開瀏覽器時,處理器以 1/ 2 最大時鍾,但是一旦您啟動瀏覽器,它就會達到最大時鍾。 您可以通過在高級電源選項中使用“最大\\最小處理器狀態\\頻率”來驗證這一點,或者通過運行另一個產生許多進程的應用程序(這就是 Chrome 所做的)而不是瀏覽器來驗證這一點,看看這是否會改變延遲。

我寫了一個類似的代碼並得到了類似的輸出,

for i in range(10):
    then = time.time()
    time.sleep(0.01)
    now = time.time()
    # print('+---------------------------+')
    print(now - then)
    # print(f"rounded: {round(now - then, 2)}")
    # print('+---------------------------+')

我首先懷疑是什么導致了這種情況,是浮點數學檢查這個的用法。

但后來我得到了這個輸出

輸出

0.01080012321472168
0.01015472412109375
0.010109186172485352
0.022491931915283203 # THIS ONE IS REALLY WEIRD
0.01163029670715332
0.010137796401977539
0.010179996490478516
0.01008749008178711
0.010132551193237305
0.010088443756103516

即使您假設在計算差異時存在誤差,也不應該有那么多

+---------------------------+
0.01080012321472168
rounded: 0.01
+---------------------------+
+---------------------------+
0.01015472412109375
rounded: 0.01
+---------------------------+
+---------------------------+
0.010109186172485352
rounded: 0.01
+---------------------------+
+---------------------------+
0.022491931915283203
rounded: 0.02                 
+---------------------------+
+---------------------------+
0.01163029670715332
rounded: 0.01
+---------------------------+
+---------------------------+
0.010137796401977539
rounded: 0.01
+---------------------------+
+---------------------------+
0.010179996490478516
rounded: 0.01
+---------------------------+
+---------------------------+
0.01008749008178711
rounded: 0.01
+---------------------------+
+---------------------------+
0.010132551193237305
rounded: 0.01
+---------------------------+
+---------------------------+
0.010088443756103516
rounded: 0.01
+---------------------------+

但是看了python官方的time.sleep方法文檔后,這些結果是有道理的check here ,我引用了文檔

由於系統中其他活動的調度,暫停時間可能比任意數量的請求長

所以作為對這里問題的有根據的猜測,

它是由多種因素造成的

  1. 操作系統的線程調度
  2. 睡眠前后的執行時間
  3. 並且,浮點計算。

我希望這有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM