[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

【共同参与】批处理代码,算法的效率分析

提前告知大家:发此帖子为了大家共同完成接力任务,【请看二楼的帖子】,
希望关注此帖的fans能继续接力任务


cmd基本命令耗时预备知识

测试方法:
  1. set aa=%time%&for /l %%a in (1 1 10000)do echo .......
  2. call etime %aa% %time%
复制代码
  1. set aa=%time%&for /l %%a in (1 1 10000)do set a=0
  2. 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个时间单位

其他的大家继续补充,或者写个代码做批量测试,此工作还是蛮有意义的, 以后分析算法的效率一定很有用
现在我拿折半法求字符串长度的代码分析耗费的时间单位
  1. @echo off&setlocal enabledelayedexpansion
  2. set "str=afdjg do men contgfirfmck     song putint"
  3. :binsearch //by 随风
  4. set /a max=8190,min=0 // 【2.2】
  5. for /l %%a in (1,1,14) do ( // 【0.55】
  6.      set /a "num=(max+min)/2" //【1.15*14】
  7.      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】
  8. )
  9. if "!str:~%num%!" neq "" set /a num+=1 //【0.55+1.1】
  10. echo 经计算字符串str共有%num%个字符
  11. 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 编辑 ]
1

评分人数

    • CrLf: 好!学习了PB + 10 技术 + 1

忘了说一点:
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 编辑 ]

TOP

cmd是从磁盘的bat文件以"整行为单位"读取到内存然后预处理解释,执行完后在再继续从磁盘。。。

有什么证据来证明吗?
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

以前的分析
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 编辑 ]
1

评分人数

命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

回复 4楼 的帖子

能否讲解一下所谓的“读取”是从哪里读到哪里呢?
硬盘?硬盘的缓存?虚拟内存?物理内存?
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 5楼 的帖子

应该是从硬盘上的文件读取到内存(文本放入物理内存一般都够吧)
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

的确,是执行到哪行就读文件的哪行,不会预先读到内存中。。。
批处理运行时修改文件本身可以看到端倪。。。
1

评分人数

    • plp626: 不错,这就是我想说的证据PB + 4
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

将多行代码 用括号括起来
比如
  1. (
  2. echo fdfd
  3. echo dfdfd
  4. echo fdfd
  5. )
复制代码

要比
  1. echo fdfd
  2. echo dfdfd
  3. echo fdfd
复制代码

执行的效率略高
cmd是从磁盘的bat文件以"整行为单位"读取到内存然后预处理解释,执行完后在再继续从磁盘。。。

我给一个很简结充分的证据
  1. (
  2. pause
  3. pause
  4. )
复制代码

当第一次暂停时,打开文件把第二个pause语句删掉,然后保存,回到控制台,按任键,还是暂停
如果把那对括号去掉,就不会有上面的现象

还有,在执行过程中,如果对所在bat文件进行改名,会导致cmd命令行提示
找不到批处理文件
导致后面的语句都不会得到执行

这在其他脚本中是没有的现象
1

评分人数

    • neorobin: 这就是命令 &quot;行&quot;PB + 5

TOP

  1. @echo off
  2. echo 自动增涨的批处理
  3. set "abc=echo %%abc%%>>%0&call echo 当前大小:%%~z0字节&pause"
  4. %abc%
复制代码

TOP

不错。
这个既是bat的缺点,也是它的优点,可以在执行过程中改变自身,并动态执行(重载?呵呵),比较灵活。而且有些用法很适合把bat自身作为临时文件/数据文件,运行时根据改变的内容决定执行步骤。

相比其他脚本和大多数命令而言,bat是比较另类的。for 也是全部读取文件到内存再处理。我还没注意到其他哪个程序处理文件是分部分逐次读取的。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

关于cmd的解释机制, 大家若讨论,希望另开一帖,
现在大家的回复严重跑题了了。。。。。。。。。。。!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

TOP

还有管道耗时,&&、|| 与 if errorlevel 的效率比较。
重定向到文件,这个也许可以归结到文件写操作类命令。
读、写碰盘文件的命令可能普通耗时较多,尤其是写。

讨论命令机制的效率的一篇文:批处理中for /f 解析命令输出的效率
http://www.bathome.net/viewthread.php?tid=3591

运行外部命令,可能还有从path环境变量中找到命令程序的耗时。
直接运行一般文件而由系统自己运行关联程序来打开它,可能还要先搜索注册表的耗时。
类似的,运行外部命令时可能还要读取组策略、注册表等系统数据库的所有相关的配置,如映象劫持之类的。
这些算是命令的启动时间吧。
至于一个具体命令,可能还要到哪里读什么文件、信息之类的,再加上正式执行过程,最后可能又要更新什么文件(三方?),加起来算是命令的运行时间。
命令运行的总时间应该要包括这两个时间。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

返回列表