标题: [原创] 讨论:批处理运行效率浅谈 [打印本页]
作者: 随风 时间: 2008-10-7 05:25 标题: 讨论:批处理运行效率浅谈
批处理运行效率浅谈
大家在写批处理时,除了要考虑代码的通用性,易读性,及简洁以外,效率也是一个应该要考虑的问题。
那么批处理在什么情况下会影响效率呢?
以下是自己写代码的一些经验,欢迎大家跟帖讨论,发表自己的看法。。。
1、call 命令 若在代码使用次数超过50次左右,(大概)会影响效率
2、goto 命令 若在代码使用次数超过50次左右,(大概)会影响效率
3、findstr find dir 这几个命令,若是在一个代码中使用5次,有时甚至是2次,都会明显拖慢速度。
所以在写代码时,应尽量避开这样的用法。
call- ::假设a.txt内容有50行。测试以下两个代码的速度
- @echo off
- for /f %%a in (a.txt) do (
- set var=%%a
- set /a n=2
- call echo %%var:~!n!,1%%
- )
- pause
复制代码
- ::假设a.txt内容有50行。
- @echo off
- for /f %%a in (a.txt) do (
- set var=%%a
- set /a n=2
- echo !var:~2,1!
- )
- pause
复制代码
findstr- ::假设a.txt内容有50行。测试以下两个代码的速度
- @echo off
- for /f %%a in (a.txt) do (
- echo %%a|findstr a
- )
- pause
复制代码
- ::假设a.txt内容有50行
- @echo off
- for /f %%a in ('findstr "a" a.txt') do echo %%a
- pause
复制代码
dir- @echo off
- ::假设当前目录文件比较多。
- for /f "delims=" %%a in ('dir/b/s/a-d') do (
- for /f "delims=" %%i in ('dir/b "%%a"') do (
- echo %%i
- ))
- pause
复制代码
作者: Batcher 时间: 2008-10-7 08:49
遍历目录文件的时候,for /r应该比for /f效率高吧。
作者: batman 时间: 2008-10-7 10:30 标题: 我来说两句吧
&&关于代码运行的效率,本人以前也在各种回贴中多次提及。写出来的代码效率不高
这是新手们经常出现的问题,这是正常的,高手们也都是从这个阶段走过来的。新手们
刚开始自己写代码时应重在于解决问题上,只要代码能够解决问题,这就是成功,关于
代码的简洁和效率问题,只有在不断的学习和练习中去慢慢解决它。当然,新手们在编
写代码时还应多听听老手们的意见。下面本人就结合个人的经验来谈谈如何提高代码运
行时的效率:
1、call语式是批处理中经常使用的语式,在代码中合理地运用call能大大减少代码,
但,就如随风兄所说的一样,如果在代码中调用call的次数过多的话,代码的效率就会明
显降低,同时还有call的变量延迟功能在反复赋值的情况下也会降低代码效率,下面就以
两段代码来说明下这个问题(call语式的例子随风兄已给出,在这里就不再举例了):- @echo off&setlocal enabledelayedexpansion
- set "t=%time%"
- for /l %%i in (1,1,10000) do (
- set "str=%%i"
- echo !str!
- )
- echo 开始时间%t%
- echo 结束时间%time%
- pause>nul
复制代码
- @echo off
- set "t=%time%"
- for /l %%i in (1,1,10000) do (
- set "str=%%i"
- call,echo %%str%%
- )
- echo 开始时间%t%
- echo 结束时间%time%
- pause>nul
复制代码
分别运行这两段代码你会发现第二段代码运行的时间远远长于第一段代码,这就是
因为反复使用了10000次call延迟的原因。
2、新手们在刚刚接触for循环特别是多个for循环的嵌套时也经常会出现效率上的大
问题,而这个效率问题就是总循环次数是+还是*的问题,可能这样说大家不是很明白,
下面一样结合代码来说明吧:
有a.txt、b.txt,两文本行数相同(假设为均有100行)现在要求通过批处理将两文本
相同行数的内容合并输出并在中间以一个#来连接- @echo off&setlocal enabledelayedexpansion
- set "t=%time%"
- for /f "delims=" %%a in (a.txt) do ([
- set /a n+=1,m=0
- for /f "delims=" %%i in (b.txt) do (
- set /a m+=1
- if !n! equ !m! echo %%a#%%i
- )
- )
- echo 开始时间%t%
- echo 结束时间%time%
- pause>nul
复制代码
- @echo off
- set "t=%time%"&set "n=-1"
- :begin
- set /a n+=1
- if %n% equ 0 (
- set "sk="
- ) else (
- set "sk=skip=%n%"
- )
- for /f "%sk% delims=" %%i in (a.txt) do set /p=%%i#<NUL&GOTO next
- :next
- for /f "%sk% delims=" %%i in (b.txt) do set /p=%%i<NUL&ECHO.&GOTO begin
- echo 开始时间%t%
- echo 结束时间%time%
- pause>nul
复制代码
大家可以看出第二段代码比起第一段代码要复杂,那么运行效率呢,实际上第二段
代码的效率是远高于第一段代码的,为什么呢?我们就来分析一下吧:第一段代码先是
从a.txt中读取第一行内容然后将n值加1并将m值归0,然后进行b.txt开始逐行读取并将每
次将m值加1如遇到n值和m值相同时就输出a.txt中的第一行和b.txt中的这一行(实际也
就是b.txt中的第一行),然后再读取a.txt中的第二行再重复上述比对和输出,如此当整个
循环运行完成,第二个for循环就足足整个比对了b.txt100次,也就是比对了10000行的内
容;而第二段代码是先从a.txt中读取第一行并输出然后跳到b.txt读取和输出第一行内容
再返回begin标签,再用skip来忽略a.txt的第一行读取输出第二行后又跳到b.txt同样用skip
忽略掉b.txt的第一行读取和输出b.txt的第二行再次返回begin标签,如此一直到所有的内
容被输出,所以其总共的读取次数是200,这也是最少的比对次数,100+100和100*100
相信大家都知道谁快谁慢了吧。
3、还有一个不但是新手同样老手也会常出现的效率问题,那就是在设计代码方案时
存在的问题,本来在一个代码不需要进行比对和返回而设计了比对和返回,以代码示之:
如随机生成9000个不同的0-10000内的数- @echo off
- set "t=%time%"
- :begin
- set /a a=%random%%%10000+1
- if not defined _%a% (
- set /p=%a% <NUL
- set /a n+=1&set "_%a%=a"
- ) else (
- goto begin
- )
- if %n% neq 9000 goto begin
- echo.&echo 开始时间%t%
- echo 结束时间%time%
- pause>nul
复制代码
- @echo off&setlocal enabledelayedexpansion
- set "t=%time%"
- for /l %%i in (0,1,10000) do set "_!random!!random!!random!!random!=%%i"
- for /f "tokens=2 delims==" %%i in ('set _') do (
- set /p=%%i <NUL
- set /a n+=1
- if !n! equ 9000 goto end
- )
- :end
- echo.&echo 开始时间%t%
- echo 结束时间%time%
- pause>nul
复制代码
第一段代码将会慢得让你的机器都不能忍受,就是因为其中不可计数的比对和返回
次数大大降低了运行的效率,当然在所取数和基数相差值较大的情况下这种方案还是可
以采用的。
好了,说了这么一大通无非就是请大家在设计和编写代码时多多考虑效率方面的问
题,如有解释得不透或有误的地方还望大家指出了。
[ 本帖最后由 batman 于 2008-10-7 16:21 编辑 ]
作者: pusofalse 时间: 2008-10-7 11:45
工作量多时用setlocal延迟,少时则可以用call延迟(简洁代码),总之用最适合的代码做最适合的事情吧。
作者: namejm 时间: 2008-10-7 14:24
关注代码的执行效率,应该是我们应该高度重视的事情,应该放在简洁性之前。我认为,衡量一个代码质量的高低,首先要看这个代码的设计方案是否合理,其次是具体代码是否正确,再然后,就是代码效率如何,然后,再关注代码的简洁性,最后,再看兼容性或通用性如何,如果再提高一个层次,还得关注易用性如何,如果要对这些因素的优先级别做一个排序的话,应该是这样的:方案的合理性>代码的准确性>代码的执行效率>代码的简洁性>代码的通用性>代码的易用性。
对于代码的执行效率问题,前面各位已经有了较为详细的介绍,并且还用代码加以解释,已经比较透彻了,时间关系,我暂时不再详细展开予以补充,在这里只是指出顶楼的一个小错误:随风在考察findstr的执行效率的时候,用了 echo %%a|findstr a 这个代码,这个代码其实并不能很好地解释findstr的执行效率问题,真正影响这段代码执行效率的,是管道符号|,大量的输入输出操作才是系统执行效率的瓶颈所在,要想提高效率,应该尽量不要频繁使用管道操作符,如果实在无法避免输入输出操作,建议用临时文件方案替代。
作者: 随风 时间: 2008-10-7 14:55
原帖由 namejm 于 2008-10-7 14:24 发表
真正影响这段代码执行效率的,是管道符号|,大量的输入输出操作才是系统执行效率的瓶颈所在 ...
管道符号也许也是一个问题,(本人暂时还没遇到过这方面的问题)也许是我顶楼的例子不恰当。
但频繁使用 findstr 应该绝对是影响效率的原因。
请分别测试以下两句代码便知。
- @echo off
- for /l %%a in (1 1 30) do findstr . a.txt
- for /l %%a in (1 1 30) do type a.txt
- pause
复制代码
作者: namejm 时间: 2008-10-7 17:41
findstr确实会拖慢速度,推测原因是这样的:因为findstr的开关很多,在执行findstr的时候,需要检测每个开关的打开状态,而type没有开关,不用在检测开关状态上花费时间,所以费时不多。
作者: wangzhantong 时间: 2008-10-7 21:16
findstr是什么意思,新手,请大家多多指教
作者: 愚无尽 时间: 2008-10-7 22:22
坛子群雄聚集啊,这贴精华当之无愧。
作者: refuelslu 时间: 2008-10-8 10:04
呵呵。都是斑竹,超级斑竹,管理员!!呵呵~~经典的讨论
作者: hlzj88 时间: 2008-11-12 22:01
一个成功的bat是能完成任务
一个高质量的bat是用最少的时间
我现在在向第一个目标前进
作者: Batcher 时间: 2008-11-13 11:05 标题: 回复 8楼 的帖子
帮助里面解释的很详细:
findstr /?
作者: TomZhang 时间: 2010-10-13 20:44
受教了。在论坛里确实学到很多。代码的效率和各种语言一样应该都是很重要的。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |