标题: 【共同参与】批处理代码,算法的效率分析 [打印本页]
作者: plp626 时间: 2009-10-7 05:43 标题: 【共同参与】批处理代码,算法的效率分析
提前告知大家:发此帖子为了大家共同完成接力任务,【请看二楼的帖子】,
希望关注此帖的fans能继续接力任务
cmd基本命令耗时预备知识
测试方法:- set aa=%time%&for /l %%a in (1 1 10000)do echo .......
- call etime %aa% %time%
复制代码
和- set aa=%time%&for /l %%a in (1 1 10000)do set a=0
- call etime %aa% %time%
复制代码
将时间差进行比较,{etime代码看此帖http://bbs.bathome.net/thread-4701-1-1.html}
我们计最基本的set var=... ; [这里...一般不超过30字节]为一个时间单位
我初略试了试发现如下:
预处理耗时:【0.55】
一个if 判断语句 或者 for %%a 或for /f ... ("string") 相当于0.5~0.6个时间单位
set /a 耗时:【1.1~1.7】
set/a a=... 含一个等号,相当于1.1~1.7 时间单位
set/a a=... 多个等号,相当于 0.96*n个 时间单位
二次预处理算术运算赋值 耗时 【2】
一个call set/a ... 含一个等号 相当于 2 个时间单位
echo 命令耗时 【9.5】
echo ... [这里...一般不超过50字节]
变量作用域设定耗时:【12】
一对setlocal endlocal 执行一次 相当于 12 时间单位
set/p=... <nul 耗时 【29】
set/p=... <nul [这里...一般不超过50字节]
跳转耗时:【72 】
仅仅一个goto 标签或者call :标签 相当于72个时间单位!!!
二次预处理赋值耗时:【108】
一个call set 相当于 108个时间单位
call echo 耗时 【120】
call echo ... [这里...一般不超过50字节]
三方命令耗时 【2500左右】
非cmd内置命令的外部工具或者for /f ... %%a in ('commond')do 相当于2450个时间单位
其他的大家继续补充,或者写个代码做批量测试,此工作还是蛮有意义的, 以后分析算法的效率一定很有用
现在我拿折半法求字符串长度的代码分析耗费的时间单位-
-
- @echo off&setlocal enabledelayedexpansion
- set "str=afdjg do men contgfirfmck song putint"
- :binsearch //by 随风
- set /a max=8190,min=0 // 【2.2】
- for /l %%a in (1,1,14) do ( // 【0.55】
- set /a "num=(max+min)/2" //【1.15*14】
- for /f "delims=" %%b in ("!num!") do if "!str:~%%b!" equ "" (set /a max=num) else set /a min=num //【0.55*14+(0.6+1.1)*14】
- )
- if "!str:~%num%!" neq "" set /a num+=1 //【0.55+1.1】
- echo 经计算字符串str共有%num%个字符
- pause>nul
复制代码
可以看出这个binsearch耗费 33.8 个时间单位,效率不错
--------------------------------------
-----------------------------
代码中有
findstr
find
sort
more
*.vbs
*.exe
*.com
for /f ... ('commond')do ...
goto
call :label // 对于过于复杂的代码子过程能提高可读性,缩短编写时间,这个就单另说了,但是绝大多数使用call,goto命令的代码【可以说接近百分之百】都可以转换为for语句
其中之一者,切记不要让他进入循环
findstr
find
sort
more
*.vbs
*.exe
*.com
for /f ... ('commond')do ...
其中之一,其执行次数不要超过两次
否则,你的代码效率将慢如驴。。。
[ 本帖最后由 plp626 于 2009-10-10 17:53 编辑 ]
作者: plp626 时间: 2009-10-7 05:50
忘了说一点:
cmd是从磁盘的bat文件以"整行为单位"读取到内存然后预处理解释,执行完后在再继续从磁盘。。。
这和js,vbs,等解释语言是不同的,
楼上的测试代码是整行的,实际代码,大家并不总是把多行代码用括号扩起来或者用&来连接多个命令,所以就成了多行,cmd会从文件中读取好多次到内存中,所以上面的结果代表了cmd最快的解释效率;
----------------------------------------------------------------------------------------------------------------
还有好多命令的耗费时间单位 需要大家测试啊
接力棒开始了
del
ren
md
rd
dir
attrib
shift
pushd + popd
break
for /r
for /d
生产临时文件
变量截取%%!! 混用等
[ 本帖最后由 plp626 于 2009-10-7 13:40 编辑 ]
作者: Batcher 时间: 2009-10-7 09:15
cmd是从磁盘的bat文件以"整行为单位"读取到内存然后预处理解释,执行完后在再继续从磁盘。。。
有什么证据来证明吗?
作者: zqz0012005 时间: 2009-10-7 09:23
以前的分析
CMD是逐行读取bat内容,并根据偏移量开始下一次的读取。
比如以下内容:
@echo off
pause
pause
第一次暂停时,已经读取过的内容是@echo off\r\npause\r\n,偏移量是18个字节,cmd接下来会从第19个字节开始读取,即下一行的pause。此时如果在第一个pause后面加上“ dir”(2个空格+dir),则从19个字节开始的内容变成了dir\r\n,碰到回车换行,于是执行dir命令。再接着才会执行后面的pause。
上面是在脚本运行过程中改变脚本文件的内容。
[ 本帖最后由 zqz0012005 于 2009-10-7 09:25 编辑 ]
作者: Batcher 时间: 2009-10-7 09:29 标题: 回复 4楼 的帖子
能否讲解一下所谓的“读取”是从哪里读到哪里呢?
硬盘?硬盘的缓存?虚拟内存?物理内存?
作者: zqz0012005 时间: 2009-10-7 09:44 标题: 回复 5楼 的帖子
应该是从硬盘上的文件读取到内存(文本放入物理内存一般都够吧)
作者: defanive 时间: 2009-10-7 11:38
的确,是执行到哪行就读文件的哪行,不会预先读到内存中。。。
批处理运行时修改文件本身可以看到端倪。。。
作者: plp626 时间: 2009-10-7 13:38
将多行代码 用括号括起来
比如
- (
- echo fdfd
- echo dfdfd
- echo fdfd
- )
复制代码
要比
- echo fdfd
- echo dfdfd
- echo fdfd
复制代码
执行的效率略高
cmd是从磁盘的bat文件以"整行为单位"读取到内存然后预处理解释,执行完后在再继续从磁盘。。。
我给一个很简结充分的证据
复制代码
当第一次暂停时,打开文件把第二个pause语句删掉,然后保存,回到控制台,按任键,还是暂停
如果把那对括号去掉,就不会有上面的现象
还有,在执行过程中,如果对所在bat文件进行改名,会导致cmd命令行提示
找不到批处理文件
导致后面的语句都不会得到执行
这在其他脚本中是没有的现象
作者: netbenton 时间: 2009-10-7 13:48
- @echo off
- echo 自动增涨的批处理
- set "abc=echo %%abc%%>>%0&call echo 当前大小:%%~z0字节&pause"
- %abc%
复制代码
作者: zqz0012005 时间: 2009-10-7 13:55
不错。
这个既是bat的缺点,也是它的优点,可以在执行过程中改变自身,并动态执行(重载?呵呵),比较灵活。而且有些用法很适合把bat自身作为临时文件/数据文件,运行时根据改变的内容决定执行步骤。
相比其他脚本和大多数命令而言,bat是比较另类的。for 也是全部读取文件到内存再处理。我还没注意到其他哪个程序处理文件是分部分逐次读取的。
作者: plp626 时间: 2009-10-7 14:05
关于cmd的解释机制, 大家若讨论,希望另开一帖,
现在大家的回复严重跑题了了。。。。。。。。。。。!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: zqz0012005 时间: 2009-10-7 14:42
还有管道耗时,&&、|| 与 if errorlevel 的效率比较。
重定向到文件,这个也许可以归结到文件写操作类命令。
读、写碰盘文件的命令可能普通耗时较多,尤其是写。
讨论命令机制的效率的一篇文:批处理中for /f 解析命令输出的效率
http://www.bathome.net/viewthread.php?tid=3591
运行外部命令,可能还有从path环境变量中找到命令程序的耗时。
直接运行一般文件而由系统自己运行关联程序来打开它,可能还要先搜索注册表的耗时。
类似的,运行外部命令时可能还要读取组策略、注册表等系统数据库的所有相关的配置,如映象劫持之类的。
这些算是命令的启动时间吧。
至于一个具体命令,可能还要到哪里读什么文件、信息之类的,再加上正式执行过程,最后可能又要更新什么文件(三方?),加起来算是命令的运行时间。
命令运行的总时间应该要包括这两个时间。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |