标题: [文本处理] 批处理中goto,call和P+JS混编代码的实测效率对比 [打印本页]
作者: aloha20200628 时间: 2022-10-27 21:15 标题: 批处理中goto,call和P+JS混编代码的实测效率对比
本帖最后由 aloha20200628 于 2022-10-27 21:17 编辑
曾以为goto和call都是cmd内部命令,效率级别相当...
曾以为P+JS混编效率应高于纯P...
但实测结果,还真不一定...
借用前几天的帖子(http://www.bathome.net/thread-64179-1-1.html)简化出一个测试题型,即对源文件(1.txt)每行文本逐列插入字符@,再输出到新文件1.new
现通过以下四段代码看一下比对结果
测试样本》顺便找了一个简中编码的文本文件,1000行(行数少不足以彰显差别),文本行掺杂中英文字符,单行字符量≤128
第一段纯P代码》用goto实现循环,实测耗时约 29 秒
第二段纯P代码》不用goto,实测耗时约 5 秒
第三段混编代码》用js逐行处理,实测耗时约 30 秒
第四段混编代码》用js一次性处理全文件,实测耗时约0.05秒(与以上各段比对可忽略不计了)
用整型换算1-3段代码实测结果》6 : 1 : 6
第一段代码- @echo off &setlocal enabledelayedexpansion
- echo,%time%
- (for /f "delims=" %%F in (1.txt) do (
- (call :_insertCharInStr "%%~F" newF)
- echo,!newF!
- ))>1.new
- echo,%time%
- endlocal&exit/b
-
- :_insertCharInStr // %1=srcStr %2=newStr //处理1000行文本数据(单行字符量≤128)耗时约29秒
- set "srcStr=%~1" &set "sn=" &set "k=0"
- :[Loop]
- for %%n in (!k!) do (set "cn=!srcStr:~%%n,1!")
- if "!cn!"=="" (set "%~2=!sn!" &exit/b)
- set "sn=!sn!@!cn!" &set/a "k+=1" &goto:[Loop]
复制代码
第二段代码- @echo off &setlocal enabledelayedexpansion
- echo,%time%
- (for /f "delims=" %%F in (1.txt) do (
- (call :insertCharInStr "%%~F" newF)
- echo,!newF!
- ))>1.new
- echo,%time%
- endlocal&exit/b
-
- :insertCharInStr // %1=srcStr %2=newStr //处理1000行文本数据耗时约5秒
- set "srcStr=%~1" &(call :strLen srcStr sL) &set "sn=" &set/a "sL-=1"
- for /L %%k in (0,1,!sL!) do (set "sn=!sn!@!srcStr:~%%k,1!")
- set "%~2=!sn!" &exit/b
-
- :strLen // %1=被测字符串变量名 %2=返回值变量名
- (set "str=a!%~1!"
- set "len=0"
- for /l %%a in (12,-1,0) do (
- set/a "len|=1<<%%a"
- for %%b in (!len!) do if "!str:~%%b,1!"=="" set/a "len&=~1<<%%a"
- )
- )
- if "%~2" neq "" set/a "%~2=!len!"
- exit /b
复制代码
第三段代码- @set @v=1 /*
- @echo off &setlocal enabledelayedexpansion
- echo,%time%
- ::处理1000行数据耗时约30秒
- (for /f "delims=" %%F in (1.txt) do (
- for /f "delims=" %%v in ('cscript /e:jscript "%~f0" "%%~F" ') do set "newF=%%v"
- echo,!newF!
- ))>1.new
- echo,%time%
- endlocal&exit/b
- */
- var v=WSH.Arguments; //获取命令行参数
- WSH.Echo(v(0).replace(/(.)/g,'@$1')); //在字符串中逐列插入字符
复制代码
第四段代码- @set @v=1 /*
- @echo off
- echo,%time%
- ::处理1000行文本数据(单行字符量≤128)耗时约0.05秒
- cscript /e:jscript "%~f0" "1.txt"
- echo,%time%
- exit/b
- */
- var v=WSH.Arguments; //获取命令行参数
- var fso=new ActiveXObject('scripting.filesystemobject');
- var alltext=fso.opentextfile(v(0)).readall();
- alltext=alltext.replace(/([^\r\n])/g,'@$1'); //在字符串中逐列(排除换行符)插入字符
- fso.opentextfile("1.new", 2, true).write(alltext);
复制代码
作者: terse 时间: 2022-10-28 16:41
第一段代码和第二段代码在处理字符串长度上方法不一样,效率也会不一样
第三段代码,假如一千行的文本,相当于启动JS处理一千次,尤其在FOR内部启用JS会影响效率
记得论坛有专门针对CALL GOTO SET FOR等命令的测试
作者: aloha20200628 时间: 2022-10-29 13:19
闲时又用一个6000行的样本练了一把四段代码,代码4仅用了0.08秒,依然是厘秒级秒杀本题,略去不提了。1-3代码的量化耗时比例关系 6:1:6 基本未变,但1和3代码的绝对耗时却飙升到3分钟,令goto版和for(...)外部进程调用版的“钝感”毕现,看来通常用小量样本试过的算法代码,还真经不起大数据样本的折腾。
细想想,其实从实测结果复读出的还是些常识,无论是驾驭c/c++,还是摆弄“远古而简单”的纯P,都是大道至简,一脉相通,不都是在打磨锤炼“算法及其代码实现”吗 ... 代码量少不一定效率高,样本不足时,利刃和钝器似乎无感。
记起旧帖中有实例用 for /f ... ('dir ...') 处理几十万项的目录文件,陷入了几小时“不动”的困境,后改用 dir ...>tmp.txt & for /f ... (tmp.txt) 得以解困了事。cmd给每个纯P变量只有8k内存,系统给每个cmd进程只有64M内存,一旦超限了要么系统立即报错退出,要么系统启用磁盘交换文件,脚本的运行效率就会明显降低...
ok, 这些闲聊仅供那些有心鼓捣纯P代码的人—或是那些有趣在'螺蛳壳里做道场'的玩家们参考吧。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |