返回列表 发帖
奇怪,你们为什么就不用debug直接查询本地化变量在内存中的存储呢,很容易的事
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

69# zm900612


不错,因为 set /a =%#39999% 这一句,在预处理 a 变量时,搜索指针就已经经过了 #39999 变量,一次预处理得到了a,#399992个值,所以实际耗时就是一次取值 "a "的耗时。
所以hanyeguxin的代码才没有测试出差距。

TOP

奇怪,你们为什么就不用debug直接查询本地化变量在内存中的存储呢,很容易的事
hanyeguxing 发表于 2011-4-23 09:01

门外汉表示没学过...麻烦您教教呗

TOP

看了plp626老兄几次测试数据,百思不得其解为什么只要循环到变量名为_1n的时候,阶差会突然间低得可怜,居然还有负的...和_1完全不在一个档次上,这是什么原因呢?

TOP

本帖最后由 plp626 于 2011-4-23 10:35 编辑

垃圾变量名集合 不含有待赋值变量 与 含有待赋值变量 的比较

上面那个代码设定
set loop=4500
set p=150
set "pre1=_"      :: 垃圾变量前缀
set "pre2=#"      :: 待赋值变量前缀
set "med=set"    :: 赋值方式

set loop=4500
set p=150
set "pre1=_"      :: 垃圾变量前缀
set "pre2=_"      :: 待赋值变量前缀
set "med=set"    :: 赋值方式
的输出:分别为
待测试变量数占垃圾变量数(4500个)的比:1/150
“垃圾变量名”中【不含有】待赋值变量的测试
====================================
执行4500set _1=1耗时:161,阶差:161 // 第一个阶差不做参考
执行4500set _2=1耗时:161,阶差:0
执行4500set _3=1耗时:163,阶差:2
执行4500set _4=1耗时:162,阶差:-1
执行4500set _5=1耗时:163,阶差:1
执行4500set _6=1耗时:161,阶差:-2
执行4500set _7=1耗时:161,阶差:0
执行4500set _8=1耗时:161,阶差:0
执行4500set _9=1耗时:164,阶差:3
执行4500set _10=1耗时:161,阶差:-3
执行4500set _11=1耗时:161,阶差:0
执行4500set _12=1耗时:161,阶差:0
执行4500set _13=1耗时:161,阶差:0
执行4500set _14=1耗时:159,阶差:-2
执行4500set _15=1耗时:159,阶差:0
执行4500set _16=1耗时:162,阶差:3
执行4500set _17=1耗时:163,阶差:1
执行4500set _18=1耗时:160,阶差:-3
执行4500set _19=1耗时:161,阶差:1
执行4500set _20=1耗时:162,阶差:1
执行4500set _21=1耗时:161,阶差:-1
执行4500set _22=1耗时:161,阶差:0
执行4500set _23=1耗时:161,阶差:0
执行4500set _24=1耗时:161,阶差:0
执行4500set _25=1耗时:161,阶差:0
执行4500set _26=1耗时:161,阶差:0
执行4500set _27=1耗时:162,阶差:1
执行4500set _28=1耗时:164,阶差:2
执行4500set _29=1耗时:163,阶差:-1
执行4500set _30=1耗时:162,阶差:-1
请按任意键继续. . .COPY
::::::::::::::::::::::::::::::::::::::::::::::::
待测试变量数占垃圾变量数(4500个)的比:1/150
“垃圾变量名”中【含有】待赋值变量的测试
====================================
执行4500set _1=1耗时:67,阶差:67
执行4500set _2=1耗时:91,阶差:24
执行4500set _3=1耗时:116,阶差:25
执行4500set _4=1耗时:139,阶差:23
执行4500set _5=1耗时:155,阶差:16
执行4500set _6=1耗时:155,阶差:0  // 略微变化
执行4500set _7=1耗时:158,阶差:3
执行4500set _8=1耗时:162,阶差:4
执行4500set _9=1耗时:164,阶差:2
执行4500set _10=1耗时:68,阶差:-96 // 显著变化
执行4500set _11=1耗时:73,阶差:5
执行4500set _12=1耗时:72,阶差:-1
执行4500set _13=1耗时:73,阶差:1
执行4500set _14=1耗时:75,阶差:2
执行4500set _15=1耗时:78,阶差:3
执行4500set _16=1耗时:79,阶差:1
执行4500set _17=1耗时:83,阶差:4
执行4500set _18=1耗时:84,阶差:1
执行4500set _19=1耗时:88,阶差:4
执行4500set _20=1耗时:91,阶差:3
执行4500set _21=1耗时:94,阶差:3
执行4500set _22=1耗时:95,阶差:1
执行4500set _23=1耗时:98,阶差:3
执行4500set _24=1耗时:100,阶差:2
执行4500set _25=1耗时:105,阶差:5
执行4500set _26=1耗时:106,阶差:1
执行4500set _27=1耗时:108,阶差:2
执行4500set _28=1耗时:111,阶差:3
执行4500set _29=1耗时:112,阶差:1
执行4500set _30=1耗时:116,阶差:4
请按任意键继续. . .COPY

TOP

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

  系统每运行一次命令解释器都要生成一个256字节的内存块——程序段前缀PSP(Program Segment Prefix),它包含了一些比较重要的信息,如内存单元、矢量、命令行上键入的文件名、命令行本身(用户运行程序的命令行的拷贝)、各种保留缓冲器存储地点的信息。只要涉及环境,那些存储地点之一就会保存系统环境地址。

  打开命令解释器,运行 for /l %a in (1,1,100) do set "#%a=%a" ,设置这些变量,接着运行 DEBUG

  在DEBUG命令状态下查看环境,首先查看偏移量2C处的两个字节:

  -D2CL2
   0B2DA:0020  66 05

  数据66 05是在某系统上得到的计算机环境的段地址值(操作时应以实际显示数为准),把这两对数以相反的顺序,并在后面跟上偏移量0,就能在DEBUG命令上显示系统环境。

  -D0566:0

附件: 您需要登录才可以下载或查看附件。没有帐号?注册
1

评分人数

    • plp626: debug方法确实能反映本质。用代码的输出只是 ...技术 + 1
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

75# hanyeguxing

原来如此,学习了。追问一下:“在DEBUG命令状态下查看环境,首先查看偏移量2C处的两个字节:”这里的2C是怎么的出来的呢?

TOP

从内存中可以看出,几乎和set 显示的一样,唯一的差别就是%COMSPEC%永远在内存的最前面。。。
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

hanyeguxing的debug变量储存展示已经力证了变量存储是按照变量名+=号+值全字符的ansi序列先后进行的,为什么还要强调变量的读取又不是按照这一基本序列机制呢?
***共同提高***

TOP

hanyeguxing的debug变量储存展示已经力证了变量存储是按照变量名+=号+值全字符的ansi序列先后进行的,为什么还要强调变量的读取又不是按照这一基本序列机制呢?
***共同提高***

TOP

77# zm900612


从当年MS-DOS开始,这里就标记环境变量的段地址值,到windows下都没变过。。。
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

果然是 变量名+值 都一起以字符存储的。
难怪 set a=1 比 set /a a=1要快。

这种存储法,自由度不错,某种程度上方便了用户,但效率就低了。

TOP

有一个结论对指导我们提高效率还有一定意义的:

垃圾变量名集合包含待赋值变量名时,待赋值变量的赋值耗时
明显少于
垃圾变量名集合不包含待赋值变量名时,对 待赋值变量的赋值耗时

TOP

80# batman


1,用来说明微软为什么使用全字符ANSI来排列变量名。
2,命令解释器进内存中的环境变量区间是如何匹配的,是拿着变量名一个一个的遍历所有变量名来比较,还是按着ANSI顺序逐字比较变量名。
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

本帖最后由 batman 于 2011-4-23 11:19 编辑

加入debug的测试
代码:
@echo off&setlocal enabledelayedexpansion
call :lp 1 10 random
call :lp 11 100 random
del /q db
goto :eof
:lp
for /l %%a in (%1,1,%2) do set "_%%a=!%3!"
(echo d2cl2
echo q
echo,
)>db
(for /f "skip=1 tokens=2,3" %%a in ('debug^<db') do (
     echo d%%b%%a:0380&echo q&echo,
))>tem
del /q db&ren tem db
debug<db>%1.txt
start %1.txtCOPY
1.txt
-d0D96:0380
0D96:0380  00 5F 31 3D 36 31 33 35-00 5F 31 30 3D 32 38 36   ._1=6135._10=286
0D96:0390  31 32 00 5F 32 3D 32 39-36 38 30 00 5F 33 3D 32   12._2=29680._3=2
0D96:03A0  33 30 36 39 00 5F 34 3D-33 31 32 32 37 00 5F 35   3069._4=31227._5
0D96:03B0  3D 38 34 37 37 00 5F 36-3D 32 33 39 38 38 00 5F   =8477._6=23988._
0D96:03C0  37 3D 33 32 36 31 36 00-5F 38 3D 32 39 35 38 00   7=32616._8=2958.
0D96:03D0  5F 39 3D 32 37 37 32 31-00 42 4C 41 53 54 45 52   _9=27721.BLASTER
0D96:03E0  3D 41 32 32 30 20 49 35-20 44 31 20 50 33 33 30   =A220 I5 D1 P330
0D96:03F0  20 54 33 00 00 01 00 43-3A 5C 57 49 4E 44 4F 57    T3....C:\WINDOW
-qCOPY
11.txt
-d0E0D:0380
0E0D:0380  00 5F 31 3D 36 31 33 35-00 5F 31 30 3D 32 38 36   ._1=6135._10=286
0E0D:0390  31 32 00 5F 31 30 30 3D-31 34 36 31 34 00 5F 31   12._100=14614._1
0E0D:03A0  31 3D 35 33 30 37 00 5F-31 32 3D 33 30 32 38 37   1=5307._12=30287
0E0D:03B0  00 5F 31 33 3D 31 30 35-31 00 5F 31 34 3D 35 39   ._13=1051._14=59
0E0D:03C0  36 37 00 5F 31 35 3D 32-37 34 37 38 00 5F 31 36   67._15=27478._16
0E0D:03D0  3D 31 35 33 37 33 00 5F-31 37 3D 31 37 30 31 33   =15373._17=17013
0E0D:03E0  00 5F 31 38 3D 32 36 38-31 37 00 5F 31 39 3D 38   ._18=26817._19=8
0E0D:03F0  31 33 31 00 5F 32 3D 32-39 36 38 30 00 5F 32 30   131._2=29680._20
-qCOPY
由此可见cmd在变量有变化的情况下会重新分配内存的储存地址,1.txt和11.txt中开始的地址分别为0D96:0380和0E0D:0380,而这一存储过程是按变量名+=号+值的全字符(实际上就是变量名,因为cmd是不会允许有同名变量的存在的)的ansi序列先后进行的。
***共同提高***

TOP

返回列表