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

我测试过 set /a _1000+=2 跟 set /a _9999 +=2
排除了字符长度问题,结果仍然。

因为很多人没看懂,所以代码就简单写了2个, _9 耗时比 _10000 长,最能说明问题。

耗时的多少,跟排序后的先后顺序有关。

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

39# plp626


确实没怎么用过...
不过endlocal的基本作用我是知道的,它会清除最近一个setlocal后的所有变量改动,但是我对“栈内数据存储操作和不受栈外垃圾变量影响”这句不太理解,为什么说是栈外变量呢?“栈外”存在变量吗?那些变量不是应该被清空了吗?

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

真的是没有调查就没有发言权,我之前有点想当然了。。。

但是按理来说,变量在内存中的存储应该是堆栈,先入的后出,也就是说在定义_1-_10000的变量时,_1变量

在堆栈中应该是放在堆栈的最下面的,而_10000变量是在堆栈的顶部,如果遵循先入后出的原则,则读取_10

000变量的时间是最短的,而读取_1变量的时间是最长的。

但是从caruko的测试中我们可以看出读取_1和_10000变量的时间是差不多的,而读取_9和_9999变量的时

间也是差不多的,但是读取_1和_9以及读取_9999和_10000的时间却出现了很大的相差。这不得不让我们

从cmd默认排序机制上猜想,在内存中变量_1至_10000的排列是_9999置于最底部,接着是_9998.......

_9990,_999,_9989....._9980,_998,_9979......._10000,_1000,_100,_10,_1,_1是置于最顶部。

这一猜测几乎可以推翻开始堆栈的设想,除非在堆栈中变量名也存在排序的机制。真的希望有牛人能找到变量

在内存的存放地址,这样真相才能大白于天下。
***共同提高***

TOP

本帖最后由 terse 于 2011-4-23 00:25 编辑

猜测下   定义变量后 CND是否开始 在变量表查找变量 然后分析是否已经定义  再对变量表重新排列 整个过程的快慢 是否就是取决于变量表复杂度,
貌似以前翻到过类似贴 解释变量的存储

补充:如果变量如不是已定义, 则寻找一个空的位置来存放 所以相对旧的变量反而查找快 反之cmd 寻找先前变量位置 这个寻找过程的快慢和执行效率相关

TOP

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

变量数目越多,操作越慢。 那么基本的设想就是,每次读取一个变量,都对整个“变量组”做了某种操作。

如果假设:这些变量是一个数组,那么以指针的方式读取Array(10000)中的Array[0],与读取Array(1)中的Array[0]并不会有很大的差别,除非在每次取值的时候,都将整个数组复制了一次(或者类似操作才会使得耗时成倍增加)。

还有一种猜想,就是类似数据库的存储方式。这样才会出现在变量大量增加时,耗时成倍增加。同时兼顾排序,输出所有匹配前几个字符的变量(如set _,set _@#等),等功能。


所以,“变量-耗时”的问题估计主要有两个方面。
1:  每次读取一个变量,都操作了整个“变量组”,体现在“总变量多少--耗时”的关系。
2:  读取变量时,会有一个查找操作,查找耗时跟排序位置有关,体现在“变量排序位置--耗时”的关系。

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

你这样,应该还有很多CALL的耗时在内。

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

可能以下代码能说明一点问题:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (1,1,1000) do set /a "_%%a=1"
  3. for /l %%a in (1,1,100) do (
  4.     set "t=!time!"
  5.     for /l %%b in (1,1,10000) do set /a _%%a+=1
  6.     set "t1=!time!"&set "a="
  7.     if "!t:~,2!" lss "!t1:~,2!" set "a=+24"
  8.     set /a ".%%a=(!t1:~,2!-!t:~,2!!a!)*360000+(1!t1:~3,2!%%100-1!t:~3,2!%%100)*6000+(1!t1:~6,2!%%100-1!t:~6,2!%%100)*100+(1!t1:~-2!%%100-1!t:~-2!%%100)"
  9. )
  10. set .
  11. pause>nul
复制代码
这是将_1到_100变量计算10000次的时间(ms)用.1到.100变量储存然后列出,本机上运行结果如下:
  1. .1=50
  2. .10=54
  3. .100=69
  4. .11=54
  5. .12=57
  6. .13=57
  7. .14=59
  8. .15=63
  9. .16=62
  10. .17=66
  11. .18=67
  12. .19=70
  13. .2=62
  14. .20=68
  15. .21=70
  16. .22=72
  17. .23=73
  18. .24=75
  19. .25=78
  20. .26=78
  21. .27=80
  22. .28=85
  23. .29=82
  24. .3=78
  25. .30=83
  26. .31=85
  27. .32=87
  28. .33=88
  29. .34=89
  30. .35=90
  31. .36=96
  32. .37=93
  33. .38=97
  34. .39=100
  35. .4=91
  36. .40=97
  37. .41=100
  38. .42=101
  39. .43=103
  40. .44=105
  41. .45=108
  42. .46=109
  43. .47=111
  44. .48=114
  45. .49=116
  46. .5=106
  47. .50=112
  48. .51=114
  49. .52=118
  50. .53=118
  51. .54=119
  52. .55=123
  53. .56=124
  54. .57=126
  55. .58=127
  56. .59=128
  57. .6=119
  58. .60=130
  59. .61=128
  60. .62=133
  61. .63=133
  62. .64=134
  63. .65=137
  64. .66=138
  65. .67=140
  66. .68=141
  67. .69=144
  68. .7=131
  69. .70=143
  70. .71=146
  71. .72=146
  72. .73=147
  73. .74=152
  74. .75=151
  75. .76=154
  76. .77=154
  77. .78=156
  78. .79=159
  79. .8=145
  80. .80=158
  81. .81=160
  82. .82=161
  83. .83=166
  84. .84=175
  85. .85=194
  86. .86=178
  87. .87=174
  88. .88=173
  89. .89=177
  90. .9=159
  91. .90=173
  92. .91=175
  93. .92=176
  94. .93=180
  95. .94=180
  96. .95=182
  97. .96=185
  98. .97=184
  99. .98=191
  100. .99=187
复制代码
从这个运行结果可以看出确实变量名的存储和读取是按照cmd默认序列进行的。
***共同提高***

TOP

50# batman


似乎,只1位的数字,耗时都会相对减少,预处理的原因?

TOP

再测试(这下等得我。。。。)
代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (1,1,10000) do set /a "_%%a=1"
  3. for /l %%a in (1,1,100) do (
  4.     set "t=!time!"
  5.     for /l %%b in (1,1,10000) do set /a _%%a+=1
  6.     set "t1=!time!"&set "a="
  7.     if "!t:~,2!" lss "!t1:~,2!" set "a=+24"
  8.     set /a ".%%a=(!t1:~,2!-!t:~,2!!a!)*360000+(1!t1:~3,2!%%100-1!t:~3,2!%%100)*6000+(1!t1:~6,2!%%100-1!t:~6,2!%%100)*100+(1!t1:~-2!%%100-1!t:~-2!%%100)"
  9. )
  10. set .
  11. pause>nul
复制代码
运行结果:
  1. .1=389
  2. .10=390
  3. .100=413
  4. .11=406
  5. .12=426
  6. .13=439
  7. .14=466
  8. .15=473
  9. .16=502
  10. .17=514
  11. .18=520
  12. .19=546
  13. .2=528
  14. .20=520
  15. .21=537
  16. .22=555
  17. .23=577
  18. .24=590
  19. .25=606
  20. .26=625
  21. .27=647
  22. .28=652
  23. .29=677
  24. .3=654
  25. .30=657
  26. .31=678
  27. .32=697
  28. .33=717
  29. .34=736
  30. .35=738
  31. .36=758
  32. .37=786
  33. .38=799
  34. .39=810
  35. .4=782
  36. .40=791
  37. .41=804
  38. .42=823
  39. .43=841
  40. .44=855
  41. .45=872
  42. .46=887
  43. .47=906
  44. .48=926
  45. .49=943
  46. .5=918
  47. .50=918
  48. .51=961
  49. .52=969
  50. .53=978
  51. .54=992
  52. .55=1011
  53. .56=1018
  54. .57=1033
  55. .58=1059
  56. .59=1067
  57. .6=1050
  58. .60=1052
  59. .61=1071
  60. .62=1085
  61. .63=1107
  62. .64=1118
  63. .65=1136
  64. .66=1154
  65. .67=1176
  66. .68=1200
  67. .69=1216
  68. .7=1179
  69. .70=1192
  70. .71=1206
  71. .72=1224
  72. .73=1242
  73. .74=1254
  74. .75=1280
  75. .76=1302
  76. .77=1322
  77. .78=1324
  78. .79=1345
  79. .8=1330
  80. .80=1356
  81. .81=1372
  82. .82=1366
  83. .83=1387
  84. .84=1395
  85. .85=1425
  86. .86=1444
  87. .87=1452
  88. .88=1461
  89. .89=1483
  90. .9=1455
  91. .90=1473
  92. .91=1486
  93. .92=1520
  94. .93=1522
  95. .94=1536
  96. .95=1549
  97. .96=1566
  98. .97=1586
  99. .98=1644
  100. .99=1646
复制代码
***共同提高***

TOP

懒人关注: 等各位阶段性的研究成果, 支持!

TOP

返回列表