[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
奇怪,你们为什么就不用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"    :: 赋值方式
的输出:分别为
  1. 待测试变量数占垃圾变量数(4500个)的比:1/150
  2. “垃圾变量名”中【不含有】待赋值变量的测试
  3. ====================================
  4. 执行4500次set _1=1耗时:161,阶差:161 // 第一个阶差不做参考
  5. 执行4500次set _2=1耗时:161,阶差:0
  6. 执行4500次set _3=1耗时:163,阶差:2
  7. 执行4500次set _4=1耗时:162,阶差:-1
  8. 执行4500次set _5=1耗时:163,阶差:1
  9. 执行4500次set _6=1耗时:161,阶差:-2
  10. 执行4500次set _7=1耗时:161,阶差:0
  11. 执行4500次set _8=1耗时:161,阶差:0
  12. 执行4500次set _9=1耗时:164,阶差:3
  13. 执行4500次set _10=1耗时:161,阶差:-3
  14. 执行4500次set _11=1耗时:161,阶差:0
  15. 执行4500次set _12=1耗时:161,阶差:0
  16. 执行4500次set _13=1耗时:161,阶差:0
  17. 执行4500次set _14=1耗时:159,阶差:-2
  18. 执行4500次set _15=1耗时:159,阶差:0
  19. 执行4500次set _16=1耗时:162,阶差:3
  20. 执行4500次set _17=1耗时:163,阶差:1
  21. 执行4500次set _18=1耗时:160,阶差:-3
  22. 执行4500次set _19=1耗时:161,阶差:1
  23. 执行4500次set _20=1耗时:162,阶差:1
  24. 执行4500次set _21=1耗时:161,阶差:-1
  25. 执行4500次set _22=1耗时:161,阶差:0
  26. 执行4500次set _23=1耗时:161,阶差:0
  27. 执行4500次set _24=1耗时:161,阶差:0
  28. 执行4500次set _25=1耗时:161,阶差:0
  29. 执行4500次set _26=1耗时:161,阶差:0
  30. 执行4500次set _27=1耗时:162,阶差:1
  31. 执行4500次set _28=1耗时:164,阶差:2
  32. 执行4500次set _29=1耗时:163,阶差:-1
  33. 执行4500次set _30=1耗时:162,阶差:-1
  34. 请按任意键继续. . .
复制代码
::::::::::::::::::::::::::::::::::::::::::::::::
  1. 待测试变量数占垃圾变量数(4500个)的比:1/150
  2. “垃圾变量名”中【含有】待赋值变量的测试
  3. ====================================
  4. 执行4500次set _1=1耗时:67,阶差:67
  5. 执行4500次set _2=1耗时:91,阶差:24
  6. 执行4500次set _3=1耗时:116,阶差:25
  7. 执行4500次set _4=1耗时:139,阶差:23
  8. 执行4500次set _5=1耗时:155,阶差:16
  9. 执行4500次set _6=1耗时:155,阶差:0  // 略微变化
  10. 执行4500次set _7=1耗时:158,阶差:3
  11. 执行4500次set _8=1耗时:162,阶差:4
  12. 执行4500次set _9=1耗时:164,阶差:2
  13. 执行4500次set _10=1耗时:68,阶差:-96 // 显著变化
  14. 执行4500次set _11=1耗时:73,阶差:5
  15. 执行4500次set _12=1耗时:72,阶差:-1
  16. 执行4500次set _13=1耗时:73,阶差:1
  17. 执行4500次set _14=1耗时:75,阶差:2
  18. 执行4500次set _15=1耗时:78,阶差:3
  19. 执行4500次set _16=1耗时:79,阶差:1
  20. 执行4500次set _17=1耗时:83,阶差:4
  21. 执行4500次set _18=1耗时:84,阶差:1
  22. 执行4500次set _19=1耗时:88,阶差:4
  23. 执行4500次set _20=1耗时:91,阶差:3
  24. 执行4500次set _21=1耗时:94,阶差:3
  25. 执行4500次set _22=1耗时:95,阶差:1
  26. 执行4500次set _23=1耗时:98,阶差:3
  27. 执行4500次set _24=1耗时:100,阶差:2
  28. 执行4500次set _25=1耗时:105,阶差:5
  29. 执行4500次set _26=1耗时:106,阶差:1
  30. 执行4500次set _27=1耗时:108,阶差:2
  31. 执行4500次set _28=1耗时:111,阶差:3
  32. 执行4500次set _29=1耗时:112,阶差:1
  33. 执行4500次set _30=1耗时:116,阶差:4
  34. 请按任意键继续. . .
复制代码

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

TOP

返回列表