最近在使用time命令的时候,无意中发现了一些隐藏的秘密和强大的功能,今天分享给大家。time是Linux下常用的一个命令,可以帮助我们方便的计算程序的运行时间,比较使用不同方案时程序的运行性能。看似简单的命令,其实蕴含着很多细节和技巧,快来和肖邦一起学习吧。1基本用法详解先来看最基本的用法,也可能是最常见的用法。可以清楚的看到find命令的执行时间为0.174s。是不是很简单方便呢?但是time命令输出三个参数,我们只用第一个参数。另外两个参数是什么意思?这里解释一下:real:表示walltime,说白了其实就是程序从开始到结束所经过的时间;user:表示程序运行过程中CPU处于用户态的时间;sys:表示程序运行过程中cpu在内核态所花费的时间;细心的读者会发现上面案例中的user+sys并不等于real,这是怎么回事?其实上面解释的user和sys都是cpu执行指令消耗的时间,不包括:进程阻塞IO,调度排队,这些非cpu运行时间。这样的话,find在执行查找文件的过程中,就会有磁盘IO读取。这时候CPU就会被释放出来去做其他的事情。这些IO消耗的时间并没有包含在user和sys的统计中,所以显得真实。时间比user+sys长。下面用一个例子来验证和加强我们对root@chopin:~$timesleep2real0m2.001suser0m0.000ssys0m0.000s的理解。可以明显看出sleep命令基本不消耗cpu,程序真实运行时间为2秒。我们是对的吗?可以得出如下结论:real>=user+sys其实这个结论在单cpu的情况下是正确的。如果服务器有多个cpus,你的程序可以充分利用多个cpu,而且程序是多核并行运行的,那么user+sys统计的cpu时间可能比实际时间要大,所以这两者的区别三次之间的关系不是一成不变的,需要清楚服务器是否有多核。通过统计cpu的消耗时间,我们也可以大致知道程序运行过程中的cpu利用率。对于单核、计算密集型程序,真实时间将非常接近用户时间和系统时间的总和。Tips:部分同学可能对操作系统不熟悉。这里简单介绍一下内核态和用户态的基本概念。为了使系统更加稳定,Linux采取了隔离和保护措施。运行状态分为内核态和用户态:用户态:用户代码不具备直接访问底层资源的能力,需要使用内核提供的系统调用API。在这种隔离保护下,即使用户程序崩溃,也不会影响整个系统的功能。内核模式:内核代码拥有最大权限,可以不受任何限制地执行任何cpu指令。内核模式通常由操作系统提供的最低级和最可靠的代码运行。内核模式下的代码崩溃是灾难性的,会影响整个系统的正常运行。2你可能正在运行一个假的时间和其他功能?看看帮助文档是时候执行了,时间这么能干吗?好吧,我不打算大惊小怪,直接说出答案:你可能跑假跑了。你可能有点疑惑,为什么是假的。其实在linux系统上,使用time的时候,可能会遇到三个版本:#1.Bashtimeisashellkeyword#2.Zshtimeisareservedword#3.GNUtimetimeis/usr/bin/time我们现在的shell是Bash,可以使用type命令root@chopin:~$typetimeisashellkeyword可以看到我们刚才执行的时间是shell的内置命令。如果使用zsh,默认使用的时间也是对应的内置命令。GNUtime命令路径为/usr/bin/time,一般Linux发行版都有这个命令,就是我们今天的猪脚。3更强大的功能GNUtime命令提供了更强大的功能:更详细的统计信息和更丰富的格式输出支持将统计数据保存到下面的文件下面来学习如何编写GNUtime1.最简单的用法root@chopin:~$/usr/bin/timesleep20.00user0.00system0:02.00elapsed0%CPU(0avgtext+0avgdata1784maxresident)k0inputs+0outputs(0major+72minor)pagefaults0swaps使用GNUtime命令,直接使用绝对路径即可,可以看到输出信息比较多有很多,但是格式有点难看,后面会讲到如何自定义格式。2、保留内置时间的输出样式有同学会问,内置Shell的格式可以输出吗?是的,使用-p选项root@chopin:~$/usr/bin/time-psleep2real2.00user0.00sys0.003。输出更详细的信息您还可以输出更详细的信息,让您对程序运行信息一目了然。请使用-v选项root@chopin:~$/usr/bin/time-vsleep2Commandbeingtimed:"sleep2"Usertime(seconds):0.00Systemtime(seconds):0.00PercentofCPUthisjobgot:0%Elapsed(wallclock)time(h:mm:ssorm:ss):0:02.00Averagesharedtextsize(kbytes):0Averageunshareddatasize(kbytes):0Averagestacksize(kbytes):0Averagetotalsize(kbytes):0Maximumresidentsetsize(kbytes):1804Averageresidentsetsize(kbytes):0Major(requiringI/O)pagefaults:0Minor(reclaimingaframe)pagefaults:71Voluntarycontextswitches:1Involuntarycontextswitches:1Swaps:0Filesysteminputs:0Filesystemoutputs:0Socketmessagesent:0Socketmessagesreceived:0Signalsdelivered:0Pagesize(bytes):4096Exitstatus:0这里详细介绍time命令的输出指标(1)时间相关(2)内存相关(3)IO相关4.输出统计信息到文件如果想输出时间统计信息到文件,可以使用-o选项root@chopin:~$/usr/bin/time-v-oa。txtsleep2统计信息直接保存到a.txt,如果你想把统计信息追加到文件中,可以加上-a选项5.自定义格式输出如果命令中内置的输出格式不能满足你的需要,GNUtime可以支持自定义输出格式,通过选项-f各种索引参数/usr/bin/time-f"real%e\nuser%U\nsys%S\n"sleep1real1.00user0.00sys0.00具体支持的格式,贴心的肖邦已经为大家整理好了这些格式参数。这些格式的参数太多,大多数情况下用不到。您可以保存它们以备日后使用时快速参考。多系统参数指标,难免有些同学会觉得一头雾水。这些参数能做什么?其实这些指标对应的是操作系统的cpu、内存、IO。深入了解这些指标参数,可以帮助你从本质上把握程序的运行状态,甚至可以帮助你分析程序的性能瓶颈。下面我简单解释几个概念,希望能起到招玉作用。(1)CPU时间CPU时间包括:real、user、sys。当user+sys>=real时,表示程序计算量大;当user+sys比real小很多的时候,说明IO等待多了。(2)上下文切换通常所说的上下文是指进程的运行环境,包括当时的寄存器值、内存栈等信息。内核可以根据上下文完全恢复一个被中断的进程任务。在执行系统调用和进程切换时,会发生上下文切换。切换上下文时,操作系统需要为进程保存和恢复上下文信息。上下文切换分为主动和被动两种类型。更活跃的上下文切换表明有更多的阻塞调用;被动上下文切换表示高CPU使用率。当上下文切换过多时,意味着更多的cpu时间花在了上下文切换上,这就大大减少了cpu处理进程任务的有效时间。(3)二次缺页异常较多,说明程序内存布局比较合理,命中率较高;当primarypagefault异常较多时,说明程序对内存的访问跳动性很强,命中率很低。处理缺页异常和切换上下文的时间不计入user和sys。当发现user+sys比real小很多的时候,很可能大部分时间都花在了这些地方。有必要着重分析这两点。本文转载自微信公众号《编程修真》,可通过以下二维码关注。转载本文请联系编程实践公众号。
