Shell 是什么解释了macOS上“时间”的不精确性?
注意:我看到并理解时间不一定那么精确。然而,我看到报告的Shell 是什么解释了macOS上“时间”的不精确性?,shell,Shell,注意:我看到并理解时间不一定那么精确。然而,我看到报告的时间与实际花费的时间之间有4倍的差异,我想了解是什么导致macOS出现这种情况,这就是问题的关键所在 我试图比较两种运行二进制文件的方法,它们报告的时间非常相似: $ time ../../../node_modules/.bin/quicktype --version quicktype version 15.0.214 Visit quicktype.io for more info. ../../../node_modules/.b
时间与实际花费的时间之间有4倍的差异,我想了解是什么导致macOS出现这种情况,这就是问题的关键所在
我试图比较两种运行二进制文件的方法,它们报告的时间非常相似:
$ time ../../../node_modules/.bin/quicktype --version
quicktype version 15.0.214
Visit quicktype.io for more info.
../../../node_modules/.bin/quicktype --version 0.46s user 0.06s system 110% cpu 0.474 total
$ time $(yarn bin quicktype) --version
quicktype version 15.0.214
Visit quicktype.io for more info.
$(yarn bin quicktype) --version 0.44s user 0.06s system 110% cpu 0.449 total
然而,后者感觉要慢得多。因此,我在之前和之后添加了时间戳:
$ date +"%T.%3N" && time $(yarn bin quicktype) --version && date +"%T.%3N"
15:11:09.667
quicktype version 15.0.214
Visit quicktype.io for more info.
$(yarn bin quicktype) --version 0.49s user 0.06s system 108% cpu 0.513 total
15:11:11.400
实际上,15:11:09.667
和15:11:11.400
之间的差异几乎是两秒,但时间
报告的时间大约是0.5秒。是什么解释了这种巨大的差异呢?我把时间用错了
首先,time
与我的Mac电脑上的/usr/bin/time
不同:
time
是一个内置的shell(我使用Zsh)
/usr/bin/time
是BSD时间
这将产生预期的结果:
$ /usr/bin/time bash -c '../../../node_modules/.bin/quicktype --version'
quicktype version 15.0.214
Visit quicktype.io for more info.
0.49 real 0.47 user 0.06 sys
$ /usr/bin/time bash -c '$(yarn bin quicktype) --version'
quicktype version 15.0.214
Visit quicktype.io for more info.
2.02 real 1.92 user 0.27 sys
我把时间用错了
首先,time
与我的Mac电脑上的/usr/bin/time
不同:
time
是一个内置的shell(我使用Zsh)
/usr/bin/time
是BSD时间
这将产生预期的结果:
$ /usr/bin/time bash -c '../../../node_modules/.bin/quicktype --version'
quicktype version 15.0.214
Visit quicktype.io for more info.
0.49 real 0.47 user 0.06 sys
$ /usr/bin/time bash -c '$(yarn bin quicktype) --version'
quicktype version 15.0.214
Visit quicktype.io for more info.
2.02 real 1.92 user 0.27 sys
一般来说,对于外部命令cmd
,shell扩展是在cmd
启动之前由shell完成的。这包括命令替换cmd$(other_cmd)
、globbingcmd*.txt
、变量扩展cmd$FOO
,等等。因此,cmd
以扩展结果作为参数执行,并且从未看到用户键入的原始命令行
因此,如果time
是一个普通的外部命令,就像您使用/usr/bin/time
一样,那么warn-bin-quicktype
命令将在time
启动之前运行,就好像您已经运行了time…/quicktype--version
。它只测量执行../quicktype--version
所花费的时间,它不会(也不能)计算shell通过运行生成该命令行所花费的时间
这里的情况并不是那么简单,因为在许多shell中,time
实际上是一个内置命令,而不是一个外部命令。因此,它不一定要遵循上述行为。但是,在我的测试中,zsh
的内置时间
表现相同,并且不计算运行替换命令所花费的时间。另一方面,在bash
中,time
内置函数确实包含它
正如您所看到的,您可以通过对新shell的运行进行计时来避免该问题,该shell同时执行命令替换(运行warn
)和生成的。/quicktype
命令本身。然后您肯定会包括这两个步骤所花费的时间。一般来说,对于外部命令cmd
,shell扩展是在cmd
启动之前由shell完成的。这包括命令替换cmd$(other_cmd)
、globbingcmd*.txt
、变量扩展cmd$FOO
,等等。因此,cmd
以扩展结果作为参数执行,并且从未看到用户键入的原始命令行
因此,如果time
是一个普通的外部命令,就像您使用/usr/bin/time
一样,那么warn-bin-quicktype
命令将在time
启动之前运行,就好像您已经运行了time…/quicktype--version
。它只测量执行../quicktype--version
所花费的时间,它不会(也不能)计算shell通过运行生成该命令行所花费的时间
这里的情况并不是那么简单,因为在许多shell中,time
实际上是一个内置命令,而不是一个外部命令。因此,它不一定要遵循上述行为。但是,在我的测试中,zsh
的内置时间
表现相同,并且不计算运行替换命令所花费的时间。另一方面,在bash
中,time
内置函数确实包含它
正如您所看到的,您可以通过对新shell的运行进行计时来避免该问题,该shell同时执行命令替换(运行warn
)和生成的。/quicktype
命令本身。然后您肯定会包括这两个步骤所用的时间。作为测试,因为我不确定MacOS的time
命令是如何工作的,time echo$(sleep 3)
说了什么?这将有助于区分是否包括展开$(…)
所花费的时间。您是否也检查了time(1)
和/或shell的手册页,以查看total
数字是指CPU时间还是实时数?@NateEldredge有趣的是,time echo$(sleep 3)
根本不输出任何内容(只是一个额外的空行):。如果这很重要的话,我就在一个Zsh外壳中(time
在我的机器上是/usr/bin/time
)-man-time
说它是一个BSD实用程序,正如macOS上所期望的那样)。如果你想确保包含命令替换,请将整个东西封装在一个函数中,并对该函数进行时间计算。事实上,您不一定要计算warn
花费的时间,但可能只看到quicktype
使用的时间。通过像/usr/bin/time
这样的外部命令,shell通过在/usr/bin/time
之前运行warn
来扩展$(…)
命令替换