返回列表 发帖
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码顺序的,耗时比值不是单调的。暂对规律不做猜想
@echo off
for /l %%a in (900 1 999)do call:xp %%a _ 已定义_[1-1000]再定义_?的耗时与直接定义_?
变量
echo -------------------
for /l %%a in (900 1 999)do call:xp %%a # 已定义#[1-1000]再定义_?的耗时与直接定义_?
变量
pause
:xp
setlocal enabledelayedexpansion
        call:tt
        call:etime t1 t2 one
        for /l %%a in (1,1,1000) do set %2%%a=1
        call:tt
        call:etime t1 t2 two
set/a pp=two/one,r=(two%%one)*10/one
echo 变量: _%1 %3耗时比: !pp!.%r%
endlocal&goto:eof
:tt -------------------------- sub -----------------------------
set t1=%time%
for /l %%a in (1 1 1000)do set/a _%1=1
set t2=%time%
goto:eof
:etime
setlocal enabledelayedexpansion
set/a rt=1!%2:~-5,2!!%2:~-2!-1!%1:~-5,2!!%1:~-2!,%3+=-6000*("%3>>31")
endlocal&set %3=%rt%&goto:eofCOPY

TOP

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

TOP

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

TOP

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

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

TOP

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

TOP

50# batman


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

TOP

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

TOP

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

TOP

返回列表