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


对变量的结论你是怎么得出的? 猜测的话你的控制实验现象是什么?

你看一些介绍中缀表达式计算的C代码,扩展后可以操作变量,可以解释文本里的数学公式,并有简单的编程功能,都是堆栈的方式,每一条命令行语句,对变量的读取,就是读地址,预处理的时候变量的字符串已经成为常量,cmd把这个常量转换为散列地址,你赋值时后它已经放在哪,然后读变量的时候cmd又把这个变量解释为散列地址,就直接取值了,若没定义过它就返回空。只是谁也没见识过cmd的源代码,汇编也是更是门外汉。

cmd里的random,errorlevel,date,time变量又不同于我们定义的变量,对于延迟处理我们还是靠现象猜测,有时候我给cmd发一条好长的复合语句,它会报告存储空间不足,无法处理此命令,我们是在黑暗中摸索,较真的话,很耗费时间精力的。

TOP

我们若为提高效率,记住这条实用的:

对数值的单一赋值,set 比set/a 快25%左右。

TOP

有个给大伙的建议,我们在做cmd执行效率的时候,能不能把耗费时间的秒换算成是echo off(或其他某条语句,大伙可以指定可统一标准)语句耗费时间的多少倍,这样方便参考。

都说自己运行耗费了多少秒,那只是时间,没要参考价值的。当然你可以给出自己的cpu型号,内存,但即使这样各人的机子也不同。

效率是单位时间所执行的任务才对。

TOP

11# caruko


你怎么排除预处理的因素?

TOP

26# caruko


老了,把函数的et忘了改了成%3了;
  1. :etime
  2. set/a %3=1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,%3+=-6000*("%3>>31")
复制代码
你的试验数据属实,不过我把你才试验改进下,不是相差4.5倍,是相差70倍,我得到一个很有意义的结论。
这个结论对我们在进行大量变量赋值时具有很现实的指导意义。

待会告诉大家。

caruko为大家做了一个很有意义的试验。暂一个。

TOP

本帖最后由 plp626 于 2011-4-23 09:41 编辑

结论就是:                                            【结论就是,只看测试代码运行结果,或者直接跳到40楼】

endlocal(不是setlocal)释放掉大量垃圾变量后赋值操作才会变快

代码比较如下:
  1. @echo off
  2. :: 测试一,垃圾变量在变量空间一内,变量二空间内变量的赋值耗时测试
  3. setlocal enabledelayedexpansion
  4. call:tt
  5. call:etime t1 t2 one
  6. set one
  7. for /l %%a in (1,1,10000) do set _%%a=1
  8. endlocal&Set one=%one%&setlocal enabledelayedexpansion
  9. call:tt
  10. call:etime t1 t2 two
  11. set two
  12. set/a pp=two/one
  13. echo 倍数: !pp!
  14. pause
  15. :tt -------------------------- sub -----------------------------
  16. set t1=%time%
  17. for /l %%a in (1 1 10000)do set/a _9+=2
  18. set t2=%time%
  19. goto:eof
  20. :etime
  21. set/a %3=1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,%3+=-6000*("%3>>31")
  22. goto:eof
复制代码
  1. @echo off
  2. :: 测试二,垃圾变量在变量空间二而内,变量空间二内变量的赋值耗时测试。
  3. setlocal enabledelayedexpansion
  4. call:tt
  5. call:etime t1 t2 one
  6. set one
  7. endlocal&Set one=%one%&setlocal enabledelayedexpansion
  8. for /l %%a in (1,1,10000) do set _%%a=1
  9. call:tt
  10. call:etime t1 t2 two
  11. set two
  12. set/a pp=two/one
  13. ECHO 倍数:!pp!
  14. pause
  15. :tt -------------------------- sub -----------------------------
  16. set t1=%time%
  17. for /l %%a in (1 1 10000)do set/a _9+=2
  18. set t2=%time%
  19. goto:eof
  20. :etime
  21. set/a %3=1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,%3+=-6000*("%3>>31")
  22. goto:eof
复制代码

TOP

29# plp626


你的代码,好像不是 全局 与 局部 的关系啊。
而是2个相对独立的局部。

这样的意义就相当于:
当我们需要大量变量参与计算(计算后这大量的变量需要废弃),而我们只需要计算后的少数几个结果, ...
caruko 发表于 2011-4-22 21:57


你说的对,是两个相对独立的局部。。

TOP

用1和10000来做对比测试不太严谨吧,因为字符长度会影响预处理耗时,不如改成类似10000和16383的数(十进制和二进制位数均相同)
plp626兄台的测试代码我有点看不懂啊,endlocal之后不是不存在刚刚制造饿垃圾变量了 ...
zm900612 发表于 2011-4-22 22:43



记得你说过自己不怎么用call,那可想而知你更是少用endlocal;

endlocal执行后,就把垃圾变量“释放”了。
把这段代码执行下,看看运行结果:
@echo off
setlocal&set plp=1&endlocal&set plp
pause

TOP

本帖最后由 plp626 于 2011-4-23 09:39 编辑
用1和10000来做对比测试不太严谨吧,因为字符长度会影响预处理耗时,不如改成类似10000和16383的数(十进制和二进制位数均相同)
plp626兄台的测试代码我有点看不懂啊,endlocal之后不是不存在刚刚制造饿垃圾变量了 ...
zm900612 发表于 2011-4-22 22:43


说明,此楼以上到29楼的所有结论皆无效!
=====================================================
我感到自己有罪了,你们俩现在还没看出我那两个代码测试的结论是错误的,哎,苦了看帖的人了;

刚给你回复了帖子,我才想到有已经endlocal了!那就是说测试一代码没有垃圾变量了;

所以测试代码一不能叫垃圾变量在变量空间一内,赋值在二,而是,垃圾变量在空间一内生成,刚生成完又被cmd释放清空了。

所以测试一和二代码等效的来说就是都在同一个变量空间赋值;

测试一是在一个释放了垃圾变量的空间相等于清空的空间赋值,测试二则是在已经充满垃圾变量的空间进行变量赋值;

29楼那个结论“用setlocal可以减少其他变量赋值的耗费时间”真的惹笑话了!!

正确结论是 垃圾变量越多赋值越耗时,你没办法了~~~~除非你endlocal把他释放掉。

搞了这么久,就搞出来这个常识性的结论,是在汗!

TOP

本帖最后由 plp626 于 2011-4-23 00:43 编辑

做了一个变量赋值除了与已有变量数量有关外还和字符串的数据有关,但不是单纯的按ascii码顺序,还没找到规律,大家运行这个代码看看合字符串的顺序

_900到_999这样的变量是按照ascii码顺序的,耗时比值不是单调的。暂对规律不做猜想
  1. @echo off
  2. for /l %%a in (900 1 999)do call:xp %%a _ 已定义_[1-1000]再定义_?的耗时与直接定义_?
  3. 变量
  4. echo -------------------
  5. for /l %%a in (900 1 999)do call:xp %%a # 已定义#[1-1000]再定义_?的耗时与直接定义_?
  6. 变量
  7. pause
  8. :xp
  9. setlocal enabledelayedexpansion
  10.         call:tt
  11.         call:etime t1 t2 one
  12.         for /l %%a in (1,1,1000) do set %2%%a=1
  13.         call:tt
  14.         call:etime t1 t2 two
  15. set/a pp=two/one,r=(two%%one)*10/one
  16. echo 变量: _%1 %3耗时比: !pp!.%r%
  17. endlocal&goto:eof
  18. :tt -------------------------- sub -----------------------------
  19. set t1=%time%
  20. for /l %%a in (1 1 1000)do set/a _%1=1
  21. set t2=%time%
  22. goto:eof
  23. :etime
  24. setlocal enabledelayedexpansion
  25. set/a rt=1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,%3+=-6000*("%3>>31")
  26. endlocal&set %3=%rt%&goto:eof
复制代码

TOP

上面那个代码是用set/a定义_?,下面用直接用set,不带参数定义,看看运行结果:
  1. [code]@echo off
  2. for /l %%a in (900 1 999)do call:xp %%a _ 已定义_[1-1000]再定义_?的耗时与直接定义_?变量
  3. echo -------------------
  4. for /l %%a in (900 1 999)do call:xp %%a # 已定义#[1-1000]再定义_?的耗时与直接定义_?变量
  5. pause
  6. :xp
  7. setlocal enabledelayedexpansion
  8.         call:tt
  9.         call:etime t1 t2 one
  10.         for /l %%a in (1,1,1000) do set %2%%a=1
  11.         call:tt
  12.         call:etime t1 t2 two
  13. set/a pp=two/one,r=(two%%one)*10/one
  14. echo 变量: _%1 %3耗时比: !pp!.%r%
  15. endlocal&goto:eof
  16. :tt -------------------------- sub -----------------------------
  17. set t1=%time%
  18. for /l %%a in (1 1 1000)do set _%1=1
  19. set t2=%time%
  20. goto:eof
  21. :etime
  22. setlocal enabledelayedexpansion
  23. set/a rt=1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,%3+=-6000*("%3>>31")
  24. endlocal&set %3=%rt%&goto:eof
复制代码
[/code]

TOP

本帖最后由 plp626 于 2011-4-23 01:11 编辑
你这样,应该还有很多CALL的耗时在内。
caruko 发表于 2011-4-23 00:24

call的耗时不会计算在内。都是开始时间和结束时间存到变量,然后结束后计算的,再保存到变量内。

TOP

为什么要用 set /a 呢?set /a 能代表单纯的变量读写吗?
hanyeguxing 发表于 2011-4-23 03:04


你考虑的也挺全面的呵。。。,

TOP

  1. @echo off
  2. :: loop值不能过小(大于2000即可),便于看出差异
  3. set/a loop=6000
  4. set/a p=500
  5. set/a num=loop/p
  6. :: 测试变量为已储存变量数的5百分之一,
  7. :: 能看出均匀增加,但测试结果和loop值的千分之一有直接关系
  8. echo “垃圾变量名”中【含有】待赋值变量的测试
  9. for /l %%a in (1,1,%loop%) do set _%%a=1
  10. setlocal EnableDelayedExpansion
  11. for /l %%z in (1 1 %num%)do (set/a tp=tt,tt=0
  12. set t1=!time!
  13. for /l %%a in (1 1 %loop%)do set _%%z=1
  14. set t2=!time!
  15. set/a tt=1!t2:~-5,2!!t2:~-2!-1!t1:~-5,2!!t1:~-2!,tt+="-6000*(tt>>31)"
  16. set /a cc=tt-tp
  17. echo  执行%loop%次set _%%z=1耗时:!tt!,阶差:!cc!
  18. )
  19. pause
复制代码
运行结果:
  1. “垃圾变量名”中【含有】待赋值变量的测试
  2. 执行6000次set _1=1耗时:125,阶差:125
  3. 执行6000次set _2=1耗时:148,阶差:23
  4. 执行6000次set _3=1耗时:183,阶差:35
  5. 执行6000次set _4=1耗时:215,阶差:32
  6. 执行6000次set _5=1耗时:252,阶差:37
  7. 执行6000次set _6=1耗时:286,阶差:34
  8. 执行6000次set _7=1耗时:289,阶差:3
  9. 执行6000次set _8=1耗时:290,阶差:1
  10. 执行6000次set _9=1耗时:291,阶差:1
  11. 执行6000次set _10=1耗时:122,阶差:-169
  12. 执行6000次set _11=1耗时:125,阶差:3
  13. 执行6000次set _12=1耗时:128,阶差:3
复制代码

TOP

昨晚的测试代码含有call,运行后比较不出来,但把语句放在一个复合语句里却可以,

原因分析
1、垃圾变量设定太少;
2、call的堆栈也占用空间;

TOP

返回列表