睡眠命令延遲嚴重不准確 (VM)
我需要
sleep
在 shell 腳本中使用,所以我在終端中試用了它,但它產生的延遲不一致且非常不准確。例如sleep 3
產生接近 20 秒的延遲。當指定相同的時間時,這些延遲也會波動。一般來說,延遲似乎隨著值的增加呈指數增長。在 Ubuntu 和 Debian VM 上都進行了嘗試,結果同樣糟糕。我不認為 VM 組件在起作用(
timeout 10
在 Windows VM 上執行 a 很好)。通過對每個命令進行計時,系統時鐘認為它執行正常,但實際上並非如此。請參閱下面的幾個範例。
括號中的時間是實際經過的時間(近似值):
$ time sleep 1 (7 secs) real 0m1.040s user 0m0.003s sys 0m0.016s $ time sleep 1 (5 secs) real 0m1.028s user 0m0.009s sys 0m0.013s $ time sleep 1 (5 secs) real 0m1.027s user 0m0.013s sys 0m0.007s $ time sleep 1 (5 secs) real 0m1.029s user 0m0.007s sys 0m0.016s $ time sleep 3 (17 secs) real 0m3.036s user 0m0.000s sys 0m0.021s $ time sleep 5 (29.5 secs) real 0m5.026s user 0m0.007s sys 0m0.013s
預設值顯然以秒為單位,但
s
在時間上添加一個並沒有任何區別。主機上沒有執行其他可能佔用磁碟或 CPU 的設備。
在最初的幾次嘗試中,重新啟動 VM 似乎可以改善這種情況,但在那之後,準確性變得越來越差。
關於問題可能是什麼的任何想法?
編輯:
- 跑步
declare -p PS1
回報declare -- PS1="\${debian_chroot:+(\$debian_chroot)}\\u@\\h:\\w\\\$ "
- 跑步
command -V sleep
回報sleep is hashed (/usr/bin/sleep)
- 跑步
declare -p PATH
回報declare -x PATH="/home/debwp/mycmds:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
- Paul_Pedant 文章的結果:
~$ date '+%T.%N'; time sleep 5; date '+%T.%N' 22:47:49.679497552 ^[[A ^[[A ^[[A ^[[A real 0m5.033s user 0m0.005s sys 0m0.014s 22:47:54.788302324 ~$ date '+%T.%N'; time sleep 5; date '+%T.%N' 22:47:54.830674809 real 0m5.043s user 0m0.008s sys 0m0.012s 22:47:59.934542825 ~$ date '+%T.%N'; time sleep 5; date '+%T.%N' 22:47:59.994006022 real 0m5.057s user 0m0.004s sys 0m0.018s 22:48:05.159303996 ~$ date '+%T.%N'; time sleep 5; date '+%T.%N' 22:48:05.241043114 real 0m5.099s user 0m0.004s sys 0m0.021s 22:48:10.383158635 ~$ date '+%T.%N'; time sleep 5; date '+%T.%N' 22:48:10.435520982 real 0m5.028s user 0m0.004s sys 0m0.012s 22:48:15.497877219 ~$
date
以每秒〜一次的速度進入終端導致$ date Mon 31 Aug 20:42:25 CEST 2020 $ date Mon 31 Aug 20:42:25 CEST 2020 $ date Mon 31 Aug 20:42:25 CEST 2020 $ date Mon 31 Aug 20:42:26 CEST 2020
在 VirtualBox guest的時鐘漂移中找到了這個答案:
在 Virtualbox Manager 中,將準虛擬化值(系統設置 –> 加速選項卡)從
Default
更改為Minimal
更正問題。
該行為肯定與您的管理程序有關。
time(7)
說:實時定義為從某個固定點測量的時間,或者從過去的標準點(參見下面的紀元和日曆時間的描述),或者從流程生命中的某個點(例如,開始)(經過的時間)。
程序時間定義為程序使用的 CPU 時間量。這有時分為使用者和系統組件。使用者 CPU 時間是在使用者模式下執行程式碼所花費的時間。系統 CPU 時間是核心在系統模式下代表程序執行(例如,執行系統呼叫)所花費的時間。time(1) 命令可用於確定程序執行期間消耗的 CPU 時間量。
基於此,我們可以得出結論,當我們編寫時:
$ time sleep 1 real 0m1.002s user 0m0.002s sys 0m0.000s
real
是實時時間,表示過程中花費的實際時間(有時稱為掛鐘時間)。user
是在使用者模式下執行程式碼sys
所花費的 CPU 時間(CPU 週期 * 頻率),並且是核心代表程序在系統模式下執行所花費的 CPU 時間(CPU 週期 * 頻率)。解釋你的問題:
為什麼我的手錶不
real
報告時間?time(1)
當您在裸機上執行作業系統時,通常會有一個以恆定頻率執行的電池供電的晶體振盪器。該硬體時鐘將跟踪自紀元以來的時間。可以調整每秒的振盪次數以校正漂移(請參閱
hwclock(8)
)。
time(7)
還說:設置超時的各種系統呼叫(例如 select(2)、sigtimedwait(2))和測量 CPU 時間(例如 getrusage(2))的準確性受到軟體時鐘的解析度的限制,該時鐘由以 jiffies 為單位測量時間的核心。jiffy 的大小由核心常數 HZ 的值決定。
硬體時鐘用於初始化系統時鐘(否則它只會知道自啟動以來的時間)。我懷疑您的管理程序(虛擬機)使用一些 hwclock 來初始化時間。之後,軟體時鐘接管。
rtc(4)
說:$$ hardware clocks $$不應與系統時鐘混淆,系統時鐘是由核心維護的軟體時鐘,用於實現 gettimeofday(2) 和 time(2),以及設置文件的時間戳等。
我們剛剛在這裡學到的是
time(2)
(這是實用程序使用的庫呼叫time(1)
)實際上是從系統時鐘而不是硬體時鐘獲取資訊。軟體時鐘由測量時間的核心維護
jiffies
。這是由核心常數確定的時間單位。據我了解,一定數量的 CPU 週期會增加一個 jiffie。因此,如果作業系統認為 CPU 執行在 2.0 GHz,但 CPU 實際上執行在 1.0 GHz,那麼與掛鐘相比,一個 jiffie 實際上需要 2 毫秒,而不是預期的 1 毫秒。當使用物理硬體執行時,我們告訴 CPU 我們希望它執行多快(為了省電而執行更慢,性能更快),然後我們假設硬體實現了它所承諾的,因為物理硬體確實做到了。訣竅在於,當“硬體”是虛擬的時,管理程序決定如何控制虛擬 CPU,而不是物理定律。
在使用者空間(如虛擬盒)中執行的管理程序將受主機核心的支配,以為其提供所需的周期。如果主機系統執行 1000 個虛擬機,您可以想像每個來賓 VM 將只能獲得其預期的一部分 CPU 週期,從而導致猜測系統時鐘以較慢的速率增加。即使管理程序獲得了它需要的所有資源,它也可以選擇在它認為合適的時候限制資源,讓客戶作業系統執行得比它預期的要慢,而不知道為什麼。