导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2022/1/17 13:29:02
标题:
请教个关于字符串String的问题,怎么感觉Delphi11字符串效率比D7要低不少啊
浏览:4922
加入我的收藏
楼主:
大家都知道,Delphi自带的字符串替换函数StringReplace效率很低,当执行容量大比如几百KB字符串的时候慢的就开始难以仍受(一般10秒以上,以I7 11800H为例)。网上有个高手用汇编写的高效字符串替换甘薯Q_Replace,估计大家也了解,毫不夸张的说,在D7下效率比StringReplace高100以上都不止。StringReplace替换需要10秒的,Q_Replace一般只有几十毫秒就完成,而且还带计数功能。 最近我安装了Delphi11,准备重新编译一下以前D7下写的文本编辑器,但发现替换功能失效了,多长的文本替换完都变的很少,大量文本丢失。 于是了解了一下,发现是D11对String的定义变了,D7的String是AnsiString,而D11的String是UnicodeString,所以出问题了。于是我将Q_Replace对String的定义全改手动改成AnsiString,将PChar改成PAnsiChar,倒是能正常工作了,但是发现效率变的极为低下,和Delphi自带的StringReplace差不多了,降低了百倍以上的效率。 这是个啥情况啊?D11下字符串处理效率没救了吗?还是我没整对,望大神赐教!
----------------------------------------------
-
作者:
2022/1/17 14:17:07
1楼:
有高手了解吗?
----------------------------------------------
-
作者:
2022/1/17 14:26:51
2楼:
高手们回答次数太多都懒得回答已有的。
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
2022/1/17 14:30:58
3楼:
to keymark (嬲):啊!这种问题搜也不好搜,网上找了很多所谓高效字符串替换函数,到D11下一测试都不行,效率都很低了
----------------------------------------------
-
作者:
2022/1/17 16:05:01
4楼:
搜了半天,也没找到类似的答案解决这个效率问题
----------------------------------------------
-
作者:
2022/1/17 16:31:49
5楼:
AnsiString 与 Unicode string内存结构区别很大, 简单讲 Unicode string 一个字符总是两个字节, AnsiString 则有可能是1个,2个,3个. 因此处理 Unicode string 更简单更有效率. 但是如果使用了汇编在字节层面来操作字符串, 那处理ansi string的汇编代码基本上是没有可能简单移植到unicode string上来的. 建议你使用 pos定位然后复制的方法来实现一个自己的 StringReplace, pos的效率杠杠的.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 17:01:38
6楼:
to hardnut:感谢解答!不过我更改了原Q_Replace替换函数所以定义String和PChar的参数为AnsiString了,也不行吗?按理说改成AnsiString后应该和原来D7下一样了,但实际上是已经能正常工作了,不会再丢失字符和乱码了,但是效率却急剧下降,和Delphi自带的StringReplace效率差不多了,D7下处理大字符串的效率那是StringReplace百倍还有多的,效率差距非常明显。POS定位在D7下用过,但是好像对中文支持不是太好,双字节有时出现乱码,不知道D11下还有没有这个问题。但是对于几百KB甚至MB以上的文本,通过POS定位+COPY复制的方式实现替换,感觉效率应该不会太高,不一定干的过Delphi自带的StringReplace,写StringReplace函数的人水平肯定比我高多了……
----------------------------------------------
-
作者:
2022/1/17 17:29:51
7楼:
试试mormot的stringreplaceall这个方法
----------------------------------------------
-
作者:
2022/1/17 17:41:15
8楼:
不知道你说的几百KB就要10秒以上是怎么得来的。 我在VMWare虚拟机里面,Delphi11测试。 1.7MB大的字符串,stringreplace 1000次的测试结果。 var s,t : string; c, i : Integer; begin // s := System.IOUtils.TFile.ReadAllText('c:\program files (x86)\embarcadero\studio\22.0\source\rtl\win\Winapi.Windows.pas'); //s 内容1.7MB c := GetTickCount; for i := 0 to 1000-1 do begin t := StringReplace(s, 'windows', 'w', [rfReplaceAll]);//1000次1秒 //t := StringReplace(s, 'windows', 'w', []);//1000次0.5秒 //t := StringReplace(s, 'windows', 'w', [rfReplaceAll, rfIgnoreCase]);//1000次7秒 end; c := GetTickCount - c; Caption := c.ToString; end;
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/17 18:25:28
7楼:
用POS功能定义了一个替换函数,执行试了一下,比Delphi自带的StringReplace慢了差不多3倍,同一个大约240KB的文件,StringReplace用时约5.6秒,我这个用时约15.7秒,反而差了不少:( function StrRep(const SRC,OldStr,NewStr:string):string; var SrcStr,TmpStr,S1:string; i,j,l:integer; begin SrcStr:=SRC; TmpStr:=''; S1:=''; l:=length(OldStr); for i:=0 to length(SrcStr)-1 do begin if pos(OldStr,SrcStr)<>0 then begin j:=pos(OldStr,SrcStr); S1:=copy(SrcStr,1,j-1); TmpStr:=TmpStr+S1+NewStr; delete(SrcStr,1,j-1+l); end else begin result:=TmpStr+SrcStr; //exit; end; end; end;
----------------------------------------------
-
作者:
2022/1/17 18:26:57
9楼:
这个不行???????
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
2022/1/17 18:45:59
7楼:
你修改之后能用, 是因此系统先将unicode string转换成ansi string,然后旧代码可以正常工作了,然后 再将结果ansistring转换成unicode string, 这两次转换都是非常费时的,特别是涉及到非英文字符时,基本上没有什么取巧,都是一个一个字符查表处理. StringReplace我看了,写得已经很高效了.因此我觉得不应该它的问题. 可能还是你不小心导致了自动编码转换. 如果你能放出一个demo, 也许我可以帮你看看.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 18:47:05
9楼:
to wr960204:几百KB耗时10秒以上是实测出来的。比如,我笔记本CPU是I7 11800H,这算比较高的配置了。 测试一个477KB的TXT文件,用系统自带的StringReplace替换全部“人”字(实际替换2700处),耗时29秒左右(我自己定义的那个函数更慢,耗时约65秒),如下图所示。图中选中“区分大小写”是为了让执行StringReplace函数,因为没有计数,所以计数显示为0,这是D11下编译的。 然后看看D7下用那个汇编高效率替换函数执行的结果,只花费了48.5毫秒不到,效率相差600倍!用天壤之别来形容毫不为过啊!
此帖子包含附件: 大小: 587.9K
----------------------------------------------
-
作者:
2022/1/17 18:59:00
10楼:
to hardnut:不是的,Delphi自带的StringReplace函数在D7下就很慢,当文件达到数百KB的时候执行时间就基本无法让人忍受了。我用纯文本文件测试,网上汇编的那个Q_ReplaceStr函数,3370万字(64.2MB)替换上述相同的“人”字为“★”,耗时也就3.3秒,替换了377460处,这效率高的发指!如果让StringReplace来执行(文件越大效率越低,并不是和大小成正比关系),几个小时都搞不完,说不定死机了!
此帖子包含附件: 大小: 635.6K
----------------------------------------------
-
作者:
2022/1/17 19:14:19
11楼:
这是网上的那个高手用汇编写的替换函数,大家可以自己对比测试一下,D7下工作正常,效率极高,比Delphi自带的StringReplace函数效率高数百倍!
----------------------------------------------
-
作者:
2022/1/17 20:06:19
12楼:
吧数据发出来 别人才可以测试。不然都是口水
----------------------------------------------
-
作者:
2022/1/17 20:22:47
13楼:
to xiaobaosoft :发出来了啊,连网上大神的那个汇编替换函数都发出来了,还有对比测试的截图都有啊
----------------------------------------------
-
作者:
2022/1/17 20:43:53
15楼:
to hardnut:那个就是同一个内容的TXT不断重复搞成了一个超大的TXT文件。压缩成7z后仅24KB。7z不让传,改成zip,文件就大多了,496KB,见附件。
----------------------------------------------
-
作者:
2022/1/17 21:02:38
16楼:
procedure TForm1.Button1Click(Sender: TObject); var sl:TStringList; tmp,t2:string; t,i:Integer; begin sl:= TStringList.Create; sl.LoadFromFile('test2.txt'); tmp:=sl.Text; t := GetTickCount(); for I := 0 to 100 do t2 := StringReplace(tmp,'人','★',[rfReplaceAll, rfIgnoreCase]); t := GetTickCount()-t; ShowMessage( Format( '%.4f',[t/1000.0] ) ); //执行100次,用时2.26秒 end;
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 21:05:52
17楼:
用你的测试数据, 但你发出来的是gb2312, 我是先转换成 ucs 2 le bom格式再保存为test2.txt的 因此,最大可能还是你没有用对
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 21:35:43
18楼:
to hardnut:你不能那么执行的,要在文本编辑器的图形界面下操作,就像记事本里面那样,要基于已经打开的、在编辑器里面的文件内容进行操作。你把你的这个代码转换到编辑器界面你再试试,我试了,等同于死机了……
----------------------------------------------
-
作者:
2022/1/17 21:59:04
19楼:
我用你的代码,原封不动的在Delphi 7中测试,也等同于死机,于是用之前那个477KB的小文件测试,仍然不行,改成循环2次,结果用时2.031秒,改用Q_ReplaceStr那个函数,循环10000次,用时3.078秒。时间差1.5倍,循环次数差5000倍,两者的效率不言而喻。 原封不动在Delphi 11中测试,循环100次,用时1.859秒,但在编辑器图形界面下不行,等于死机。 我在想: Sl:= TStringList.Create; RichEdit1.LoadFromFile('D:\TT\test2_ansi.txt'); Sl.Text:=RichEdit1.Text; tmp:=Sl.Text; 和 Sl.LoadFromFile('D:\TT\test2_ansi.txt'); tmp:=Sl.Text; 然后t2 := StringReplace(tmp,'人','★',[rfReplaceAll, rfIgnoreCase]); 这有啥区别?上面的不过多了一道赋值,这不费啥时间啊,为啥执行起来效率相差数百倍?
----------------------------------------------
-
作者:
2022/1/17 22:33:38
18楼:
楼主, 我用你的例子数据,就是60多MB的文本试了一下,替换所有“人”字为“★”。 我这里大概只用了1.4秒 多。 用的是你原始文件,GB2312 ,或者GBK ,或者GB18030 编码(这个没有影响)。 从文件里面读一行出来,替换后写入新的文件,直到写完。 没有加什么缓存。String 和AnsiString 都试了,时间上没什么区别。 所以我估计慢不在替换,而是字符串(过大)的处理不一样吧。 毕竟Delphi11早已跨平台了,而Delphi7不用考虑别的平台,也不用管unicodestring,widestring。 代码: procedure TForm3.Button1Click(Sender: TObject); var inFile:TEXTFILE; outFile:TEXTFILE; aLine,replaceLine,inFileName,outFileName:String; t:Integer; begin t := GetTickCount(); inFileName:= 'D:\Download\****ddd.txt'; outFileName:= 'D:\Download\****out.txt'; if FileExists(outFileName) then DeleteFile(outFileName); FileClose(FileCreate(outFileName)); AssignFile(outFile,outFileName,936); Rewrite(outFile); AssignFile(inFile,inFileName,936); Reset(inFile); while not EOF(inFile) do begin ReadLn(inFile,aLine); replaceLine:=StringReplace(aLine,'人','★',[rfReplaceAll]); WriteLn(outFile, replaceLine); end; CloseFile(inFile); CloseFile(outFile); t := GetTickCount()-t; //1.4210 秒 ShowMessage( Format( '%.3f秒',[t/1000.0] ) ); end; procedure TForm3.Button2Click(Sender: TObject); var inFile:TEXTFILE; outFile:TEXTFILE; aLine,replaceLine:AnsiString; inFileName,outFileName:String; t: TDateTime; begin t := Now(); inFileName:= 'D:\Download\****ddd.txt'; outFileName:= 'D:\Download\****out.txt'; if FileExists(outFileName) then DeleteFile(outFileName); FileClose(FileCreate(outFileName)); AssignFile(outFile,outFileName,936); Rewrite(outFile); AssignFile(inFile,inFileName,936); Reset(inFile); while not EOF(inFile) do begin ReadLn(inFile,aLine); replaceLine:= System.AnsiStrings.StringReplace(aLine,'人','★',[rfReplaceAll]); WriteLn(outFile, replaceLine); end; CloseFile(inFile); CloseFile(outFile); ShowMessage( Format( '%d毫秒',[System.DateUtils.MilliSecondsBetween(Now(),t)] ) ); end; 比较:
此帖子包含附件: 大小: 507.6K
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/17 22:47:09
20楼:
to ddrfan:你是基于Richedit编辑器里的文本内容处理的还是基于文件的内容处理的?在基于文件的是比较快,但基于Richedit编辑器等UI里的文本内容则很慢,上面我说过了,你看一下,也可以测试一下。我看你的代码,也和前面那位朋友一样是基于文件处理的,不是基于Richedit编辑器里的文本内容处理的。
----------------------------------------------
-
作者:
xjia (xjia)
★☆☆☆☆
-
盒子活跃会员
2022/1/17 23:11:41
21楼:
20楼: 那是不是就不是替换的问题,是界面显示的原因?
----------------------------------------------
-
作者:
2022/1/17 23:24:37
22楼:
但是那个汇编编写的替换函数Q_ReplaceStr为什么那么快?它包含界面+替换的时间仍然远远小于StringReplace纯界面的时间,说明函数本身有很大影响。同样都不用界面,Q_ReplaceStr的速度比StringReplace领先的更多,快数千倍。
----------------------------------------------
-
作者:
2022/1/18 9:15:43
23楼:
那可能就是我说的: 慢不在替换,而是字符串(过大)的处理不一样吧。 毕竟Delphi11早已跨平台了,而Delphi7不用考虑别的平台,也不用管啥unicodestring,widestring。 你用的Richedit,我只能猜基于上面的原因(毕竟隔了20年)VCL组件变化也很大? 毕竟现在内部都用双字节字符串了。 我再试试看……
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 10:08:02
24楼:
to ddrfan:但是那个汇编编写的替换函数Q_ReplaceStr很快啊,同样是D7,它快几百倍,同样没有界面的时候它比StringReplace快的更多,速度不是几百倍而是几千倍了。 我觉得和VCL组件没多大关系,因为是基于同样的组件啊,别人就快几个数量级,这能说是组件的问题吗对吧。和是否D7或者D11也没关系,同为D7它就快得多,还是函数本身的问题。 你也用基于显示界面测试看看,看看效率如何,不出意外应该和我这表现差不多。
----------------------------------------------
-
作者:
2022/1/18 10:13:46
24楼:
60多MB文本,仅仅加载到RichEdit就慢死了啊……95秒。-__- 替换了几分钟没出来。 我把文件缩小到256KB,加载大概1秒,替换8-9秒(包括显示)。 把RichEdit换成Memo后,加载100毫秒,替换200毫秒,替换完的内容放入Memo显示到屏幕上又用了2秒左右。 把加载的内容不放入Memo而是一个StringList,则替换1毫秒完成,替换完的内容放入Memo显示到屏幕上还是2秒左右。这根本就是界面慢啊…… 而且就算这样写,也没快一点点: Memo1.Lines.BeginUpdate; Memo1.Lines.Clear; Memo1.Lines.AddStrings(outList); Memo1.Lines.EndUpdate;
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 10:26:53
25楼:
to ddrfan:我在D7下RichEdit加载这个64.2MB这个文本只要几秒钟啊!刚用秒表掐了一下,4秒而已,很快。 就算界面慢,但是为什么人家那个汇编编写的替换函数Q_ReplaceStr很快呢?64.2MB的文件人家替换完毕到显示完成仅3.3秒!这说明不是界面慢的问题。
----------------------------------------------
-
作者:
2022/1/18 10:44:22
26楼:
我的笔记本Thinkpad pad t530 i5-3210m 8G内存,win32 X11编译,执行替换楼主的64兆文本,约200毫秒,delphi x11 文本替换性能没什么问题
----------------------------------------------
-
作者:
2022/1/18 10:46:57
27楼:
测试楼主的64兆文本,我自己写的替换函数319好毫秒,delphi x11自带的函数200毫秒,和楼主说的天差地别
----------------------------------------------
-
作者:
2022/1/18 10:47:56
28楼:
楼主肯定搞错了
----------------------------------------------
-
作者:
hexi (Hexi)
★☆☆☆☆
-
盒子活跃会员
2022/1/18 12:55:55
29楼:
楼主是不是把刷新显示时间也算到stringreplace里面去了
----------------------------------------------
-
作者:
2022/1/18 15:05:33
30楼:
楼主,事情要一件一件的说。 目前未证实的仅是第3点,前面2点已经无需讨论了。 至于D11慢,也许解决不了,请参考第2点。1)D11字符串替换不慢,放到RichEdit界面非常慢。 上面的测试已证明。2)D7界面显示比D11快很多。 推测:D7效率高,很可能是不用考虑下列因素: 字符编码(无法LoadFromFile设置UTF8)。 32/64位。 跨平台。 单字节多字节(仅Ansi)。 但即使比D11快,D7弄到界面显示还是数量级的慢于直接处理字符串。3)D7下Q_ReplaceStr很快,包括界面都快。 楼主写的:Q_ReplaceStr很快呢?64.2MB的文件人家替换完毕到显示完成仅3.3秒!这说明不是界面慢的问题。 我确实重现不了,因为D7下我根本没办法Load进去,RichEdit试图Load个StringList就报EOutOfResouce。 60多MB的文件只能LoadFromFile才能打开,我不熟悉,不知道为什么。 楼主可以贴出代码,让大家看看怎么做到替换完加显示可以3点几秒的。 因为替换是替换,显示是显示,难道不是2步么?逻辑上不会因为你前面用了Q_ReplaceStr,后面显示就能从4秒变成3秒呀。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 15:20:55
31楼:
接着上面的,我用了个变通的办法:存临时文件,再加载到RichEdit里面。。。 RichEdit里的数据仅来自和存到文件,其它处理都用内部的StringList。 D7下面,替换60MB多的文本所有'人'变成'★'。 替换方式是循环每行StringReplace(aLine,'人','★',[rfReplaceAll]); 替换用时1.1秒左右。 显示用时3.3秒左右。 LZ参考一下吧,我不太想继续测了,如果一定要用D11显示到界面,我不知道怎么办。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 15:36:29
32楼:
个人总结: 1)字符串替换D11和D7其实区别不大。可能效率不是特别高,但是没那么夸张的慢。 2)D11因为要考虑的情况太多,界面用RichEdit展示很大的文本内容效率没有D7高。 3)测试归测试。即便是非界面,也建议不要用TStringList一类来处理文本文件,万一文件很大几十个GB呢。。。在《这个帖子》 里面有一些相关文本读写的讨论。PS:提到了Go效率高,都有人不高兴。。。 怎么展示/编辑那么大的文本,只能结合自己业务逻辑来考虑。对我RichEdit好像只是为了展示有格式的文本会用。工作关系几乎没用到过,只有一个内嵌的帮助用了?找了一下如下图(好像和主题无关):
此帖子包含附件: 大小: 41.2K
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 18:45:37
33楼:
to hq200306:你要到UI界面下测试,不是LS几位朋友那样,你认真看一下我的回复就知道了。 我这里贴出我自己改造的文本编辑器,大家可以用替换或者“智能分段”和“段落重排”功能测试我贴的那个64.2MB的TXT文件,也可以用WPS或者WORD等软件同样替换对比看看,当然自己也可以写个简单实现替换功能的文本编辑器测试就知道了。
----------------------------------------------
-
作者:
2022/1/18 18:52:39
34楼:
to ddrfan:我把我的那个文本编辑器发上来了,上一个帖子的附件里,你就当个记事本测试下就知道了。 我的配置是是I7 11800H,固态硬盘,即便是机械硬盘载入64.2MB文件也只要几秒钟。代码没啥特别的,就是普通的Richedit1.Lines.Loadfromfile()载入TXT文件,我待会录屏下来给你看。 如果是界面显示慢,那为啥Q_ReplaceStr那么快,所以界面显示是个问题,但不是根本问题。 你测试D7下面,替换60MB多的文本所有'人'变成'★'。替换方式是循环每行StringReplace(aLine,'人','★',[rfReplaceAll]);替换用时1.1秒左右。显示用时3.3秒左右?那真不可能!你录屏看看?
----------------------------------------------
-
作者:
2022/1/18 18:57:28
35楼:
to ddrfan:不是D7效率高,D7的StringReplace也是极其慢啊!你没看我前面说的吗?就是因为D7自带的StringReplace效率低下,所以我才用大神汇编写的Q_ReplaceStr替换函数,效率提高几百倍。但在D11下发现Q_ReplaceStr用不了,因为D11下的String不再是D7下的String了,于是我将Q_ReplaceStr函数的String改成了AnsiString,可以正常工作,但是效率也和D11的StringReplace一样低下了,于是提出了主贴的问题。
----------------------------------------------
-
作者:
2022/1/18 19:04:52
36楼:
to hexi:我计算时间是在替换前用一个高精度的计时控件开始计时(比GetTickOut函数精度高很多,当然这个也够用了),然后替换完毕后计时结束,计算两者差值。不存在另外的显示时间的。你测试要用文本编辑器界面,就像记事本那样,不能是创建一个TStringList在后台替换,这没有实际意义。前面我说了,虽然这样搞Delphi自带的函数StringReplace很快,但是如此一来大神写的那个汇编替换函数Q_ReplaceStr更快,比Q_ReplaceStr快1000倍以上!效率是相对的,相比之下StringReplace就是蜗牛速度了,也就是效率低。
----------------------------------------------
-
作者:
2022/1/18 19:09:56
37楼:
我的替换代码很简单的: if frReplaceAll in Options then begin t1:=HPCounter1.ReadInt; //计时开始 Screen.Cursor := crHourglass; S:= Editor.Text; //文本编辑器 f:= FindText; r:= ReplaceText; if frMatchCase in Options then begin Editor.Text:=Q_Replace(S,f,r); //大神用汇编写的替换函数 //Editor.Text:=StringReplace(S,f,r,[rfReplaceAll]); //Delphi自带的替换函数 t2:=HPCounter1.ReadInt; //计时结束 Application.MessageBox(pchar('共 '+inttostr(ReplCount)+' 处全部替换完毕,耗时:'+floattostr((t2-t1)/1000)+'毫秒。 '),pchar('信息') ,MB_ICONINFORMATION); Screen.Cursor := crDefault; end;
----------------------------------------------
-
作者:
2022/1/18 19:18:07
38楼:
我将我的文本编辑器Noteedit(基于Richedit,D7编写,前面已上传该文本编辑器exe文件)载入64.2MB文本文件录制视频并转换成GIF动画了,大家看看载入时间,不足4秒。
此帖子包含附件: 大小: 306.5K
----------------------------------------------
-
作者:
2022/1/18 19:25:49
39楼:
再贴个大神汇编Q_Replace函数(该函数前面帖子中已上传)替换64.2MB文件“人”到“★”耗费的时间动画,替换约37.7万处完毕3.3秒不到。
此帖子包含附件: 大小: 289.7K
----------------------------------------------
-
作者:
2022/1/18 19:35:44
40楼:
xe11的替换文本函数性能确实没问题,测了替换64兆文本,只花0.2秒,楼主是把文本替换和界面显示混为一谈,稀里糊涂
----------------------------------------------
-
作者:
2022/1/18 19:45:15
41楼:
to hq200306:麻烦你完整看下我的回复就知道到底什么问题了。是你想的那么简单我还需要来这提问吗?
----------------------------------------------
-
作者:
2022/1/18 20:41:59
43楼:
//我的笔记本,不到200毫秒 procedure TForm7.SpeedButton1Click(Sender: TObject); var d1: TStopwatch; tmp: string; ts: TStringList; begin ts := TStringList.Create; try ts.LoadFromFile('e:\d1.txt'); d1 := TStopwatch.StartNew; tmp := StringReplace(ts.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); d1.ElapsedMilliseconds; Caption := IntToStr(d1.ElapsedMilliseconds); ts.Clear; ts.Text := tmp; ts.SaveToFile('e:\d2.txt'); finally ts.Free; end; end;
----------------------------------------------
-
作者:
2022/1/18 20:47:43
44楼:
200毫秒?不可能!你啥CPU?你Delphi什么版本?我就不信你能例外!经过测试,D11的StringReplace比D7效率高了不少,但是比我发的那个汇编的替换函数还是蛮了好几倍,D7下汇编的那个64.2MB替换都要3.3秒,你StringReplace只要200毫秒?忽悠谁啊,哈哈哈!
----------------------------------------------
-
作者:
2022/1/18 20:51:50
45楼:
Thinkpad pad t530 i5-3210m 8G内存,win32 XE11编译,计算时间174毫秒
此帖子包含附件: 大小: 2,576B
----------------------------------------------
-
作者:
2022/1/18 20:52:30
46楼:
测试60兆文本,174毫秒
----------------------------------------------
-
作者:
2022/1/18 20:54:08
45楼:
楼主试试把 t1:=HPCounter1.ReadInt; //计时开始 放在 Editor.Text:=Q_Replace(S,f,r); //大神用汇编写的替换函数 前面呢? 考察StrReplace的执行时间,最好把计时器的起止紧贴StrReplace函数,否则容易引入额外的干扰因素
----------------------------------------------
-
作者:
2022/1/18 20:55:52
47楼:
替换后的文件是正确的
此帖子包含附件: 大小: 68.7K
----------------------------------------------
-
作者:
2022/1/18 21:02:23
48楼:
看了楼主代码,主要问题是分不清替换和可视化控件赋值显示耗时的问题,计算机基本功的问题
----------------------------------------------
-
作者:
2022/1/18 21:10:16
49楼:
to hq200306:要在文本编辑器里面测试才行,比如Richedit里面
----------------------------------------------
-
作者:
2022/1/18 21:12:53
50楼:
to kentty:我这是正常替换程序,实际影响页几乎为0,作为用户,时间是从点下替换按钮开始计算的,替换完毕到显示出来这才是完整的替换过程。
----------------------------------------------
-
作者:
2022/1/18 21:20:47
51楼:
to hardnut:因为其它代码都完全一样,只改变了替换函数,带来的时间差就是函数不同带来的时间差,也就是效率的差距,这没啥疑问的。我是从正常程序里才知道Delphi7自带的StringReplace效率比较低,尤其是大文件,文件越大效率越低,大文件时比起大神那个汇编替换函数效率差数百倍,这是经过实践检验的。 前几天装了Delphi11后想把之前D7写的程序重新编译一下,才发现D7下的大神汇编替换函数不能用了,于是引发了主贴的问题。经过多次测试,发现D11自带的StringReplace函数比起D7的StringReplace函数效率提高了非常多,已经算可用了,虽然仍然不及大神汇编的那个替换函数。
----------------------------------------------
-
作者:
2022/1/18 21:24:16
50楼:
你的问题是RichEdit1跑不动,不是StringReplace不行
----------------------------------------------
-
作者:
2022/1/18 21:34:43
52楼:
to hq200306:你那段代码,我笔记本上只要74.5毫秒,但这不能说明问题啊
此帖子包含附件: 大小: 19.4K
----------------------------------------------
-
作者:
2022/1/18 21:41:28
53楼:
to 50楼: 你现在怀疑的是D11的StringReplace效率差,那就先测StringReplace的执行时间 万一是D11执行 S:= Editor.Text; //文本编辑器 的效率低呢? 那就是另一个话题了 找到问题点,才能知道代码优化的方向
----------------------------------------------
-
作者:
2022/1/18 22:07:39
54楼:
to kentty:我才刚用上D11,对D11还不了解,我以为D11的StringReplace效率跟D7的StringReplace一样差,事实上,D11的StringReplace比D7的StringReplace效率高了非常多,这次讨论中间用代码测试出来的,虽然还是比不上大神的汇编Q_Replace,但差距没那么大了。S:= Editor.Text的问题,毕竟Q_Replace时人家没问题,所以就不应该是它的问题。 现在基本清楚了,D11的StringReplace比D7的StringReplace效率高了非常多,虽然仍然不及大神的汇编Q_Replace,但可用了,之前D7下的StringReplace在大文件时基本不可用,比如我的那个程序里的“智能分段”功能,在D7下遇到大文件完全不可用,因为看起来程序死了,但Q_Replace下哪怕60多M的文件也只要几秒钟。
----------------------------------------------
-
作者:
2022/1/18 22:43:50
55楼:
原来LZ是text全部替换的。 加一句话嘛,不就看出来了。 tmp := Q_Replace(S,f,r); 这里计时 Editor.Text:=tmp; 这里计时 vs tmp := StringReplace(ts.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); 这里计时 Editor.Text:=tmp; 这里计时 不过弄到最后,D11的RichEdit显示60多MB文本,还是不行吧。。。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 0:10:39
56楼:
不同的替换函数替换时Editor.Text:=tmp有区别吗?没任何区别好吧!
----------------------------------------------
-
作者:
2022/1/19 8:03:58
57楼:
前面好几个人已经验证了D11的StringReplace效率并不差, 看你的测试代码中,在计时阶段调用了TRichEdit.GetText和TRichEdit.SetText, 万一是这两个在D7和D11下的实现效率有差别呢? D11为了unicode,跨平台,在上面两个函数实现中塞入了太多的东西,也是很有肯能的 楼主可以分别验证一下TRichEdit.GetText, StringReplace, TRichEdit.SetText三个函数在D7和D11下用时
----------------------------------------------
-
作者:
2022/1/19 11:27:17
58楼:
楼主自己的逻辑不清,无数人帮他验证了StringReplace效率不差,他抱着RicheEdit中替换的时间觉得是函数的效率差。 实际上也是RichEdit的效率导致的,RichEdit是Windows系统提供的,Delphi做了个简单的封装。 D7和D11用的RichEdit就不是一个东西。 D7用的是RICHED32.DLL,是微软早期封装的RichEdit非常简陋(可能简单速度就会快)。 D11用的是MSFTEDIT.DLL,更加完善,能处理的东西非常多(处理的东西多,速度会慢一些)。 把UI和函数混在一块来测试函数性能首先逻辑已经混乱了。 把两个不同实现的UI和掺在一块说函数性能不行就是逻辑混乱加逻辑混乱。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 11:30:51
59楼:
to wr960204:是你根本没搞清楚什么原委。 只反问你,你说慢是RichEdit导致的,为什么大神汇编的Q_Replace极其高效?没有用RichEdit?完全相同的代码,就替换函数换了效率提高数百倍,不是函数本身的原因你告诉我啥原因?
----------------------------------------------
-
作者:
2022/1/19 11:34:29
60楼:
to kentty:前面讲过,经过验证,D11的StringReplace效率比D7的StringReplace确实高很多,虽然仍然比不上大神汇编的Q_Replace高效。
----------------------------------------------
-
作者:
2022/1/19 11:34:42
60楼:
Q_Replace你是在D7里面用的,RichEdit是旧的 然后和用了新Richedit的D11比,怎么比? 去掉Richedit比才是纯函数性能,你抱着RichEdit的不同实现来测函数? MSFTEDIT是微软实现的4.0的RichEdit。 增加了如下特性: 多级表 自动更正 改进的自动超链接检测 友好名称的超链接 根据书写系统的字体绑定(字符集泛化) 印度支持 垂直文本 支持最新的输入法 语音和手写输入(Windows 文本服务框架) 更标准的热键 你觉得速度应该更快吗? 公平的做法是你在去掉控件,比较函数。或者你在D7上引入新的RichEdit或者在D11上使用旧的RichEdit的核心DLL。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 11:42:34
61楼:
楼主给我的感觉入错行
----------------------------------------------
-
作者:
fdltc (fdltc)
★☆☆☆☆
-
普通会员
2022/1/19 11:55:28
60楼:
武稀松是正解,两个版本的RE内部实现完全不同。 楼主水平还只是停留在拖控件、抄代码阶段,好好努力吧
----------------------------------------------
-
作者:
2022/1/19 12:27:50
62楼:
to 59楼 你连58楼说的东西都没有看懂吧。看懂就不会这么说了。
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
2022/1/19 12:32:32
63楼:
to wr960204:咋就那么喜欢抬杠?这是D7下的对比,代码除了替换函数不同其它完全相同,也没有用Richedit,纯效率差距,你看看差距多少倍?3522倍!
此帖子包含附件: 大小: 365.0K
----------------------------------------------
-
作者:
2022/1/19 12:36:21
64楼:
to nbreak:不是我没看懂,是你们几个人老在乱扯,非要扯什么Richedit,本身和Richedit没什么关系,UI降低了效率都降低了,又不是单单降低了StringReplace,都一样,带来的差距就是函数的差距! 你们非要扯Richedit,好,那都不要UI,纯函数替换,看看,StringReplace效率低不低?低3522倍,比UI下低600倍严重多了!你还有什么可扯的?
此帖子包含附件: 大小: 365.0K
----------------------------------------------
-
作者:
2022/1/19 12:43:52
65楼:
to fdltc:我又不靠编程吃饭,用Delphi就是好玩而已。我只知道除了函数不同外其它完全相同,带来的效率差距我就认为是函数的差距,很简单。实测表明,排除UI影响后,StringReplace虽然性能提高了很多,但比Q_Replace的效率差距更大,从落后600倍到落后3522倍,上面也贴图了,不信你自己用D7测试!这不是函数效率的差距你告诉是是什么差距? procedure TForm1.Button1Click(Sender: TObject); var sl:TStringList; tmp,t2:string; t,i:Integer; begin sl:= TStringList.Create; sl.LoadFromFile('D:\Delphi\0Noteedit\体制化迷信与mzd难题x.txt'); //500KB tmp:=sl.Text; t := HPCounter1.ReadInt; for I := 1 to 100 do t2 := StringReplace(tmp,'人','★',[rfReplaceAll]); //t2 := Q_Replace(tmp,'人','★'); t := HPCounter1.ReadInt-t; caption:= '100次 StringReplace 耗时:'+Format( '%.4f',[t*0.000001])+' 秒'; //ShowMessage( Format( '%.4f',[t/1000.0] ) ); end; procedure TForm1.Button2Click(Sender: TObject); var sl:TStringList; tmp,t2:string; t,i:Integer; begin sl:= TStringList.Create; sl.LoadFromFile('D:\Delphi\0Noteedit\体制化迷信与mzd难题x.txt'); //500KB tmp:=sl.Text; t := HPCounter1.ReadInt; for I := 1 to 100 do //t2 := StringReplace(tmp,'人','★',[rfReplaceAll, rfIgnoreCase]); t2 := Q_Replace(tmp,'人','★'); t := HPCounter1.ReadInt-t; caption:= '100次 Q_Replace 耗时:'+Format( '%.4f',[t*0.000001])+' 秒'; end; 另外,你能不能给我指导下,我这个滚动渐变彩虹字有个不足,就是有2个地方“相伴”和最后的“phi”字符的地方颜色突变了,不是渐变,你有没有好方法实现这样的滚动渐变彩虹字?(gif动态滚动不平滑,但程序执行实际是很平滑的,录制帧率限制的原因)
此帖子包含附件: 大小: 2.01M
----------------------------------------------
-
作者:
2022/1/19 14:04:58
66楼:
我知道有些人瞧不上我这“业余”的水平,但我这业余的写的东西,笑话我的也不一定比我做的更好和效率比我高。 比如我的程序“智能分段”功能,效果和效率都比WPS的“段落重排”要好,比如顶部的段落,WPS整理后全乱了,我的保持了原来正确的格式。 笑话我的,做一个更优秀的出来大家看看呗!
此帖子包含附件: 大小: 2.03M
----------------------------------------------
-
作者:
2022/1/19 14:42:24
67楼:
LZ真激动啊,我前面写的: tmp := Q_Replace(S,f,r); 这里计时 Editor.Text:=tmp; 这里计时 vs tmp := StringReplace(ts.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); 这里计时 Editor.Text:=tmp; 这里计时 结果楼主回答: 不同的替换函数替换时Editor.Text:=tmp有区别吗?没任何区别好吧! 确实速度没有区别,但是可以【区分】两个步骤。 去掉界面显示对替换函数的影响,上一句的实际时间不就出来了吗。 由于界面慢,替换函数快,而且是数量级的不同。 那么加入界面的影响后,对测试函数速度是致命的影响。 再直白一点,替换函数的速度用楼主的值。 快的0.03毫秒,自带的慢很多100毫秒。界面显示需要3000毫秒。 本身是 0.03:100 约等于 1:3000。 那么加入界面后: 变成了 3000.003:3100 约等于 1:1。 这个逻辑不需要很专业的编程,了解底层原理等等,静心仔细想想就明白了。 所以大家都在说,减少干扰。 我测试的时候没有整个字符串text替换,是逐行替换的,所以没看出来D11比D7更快。我逐行原因是日常工作要考虑几十GB的文本,习惯了。但是这个并不重要。 我看到最后,没明白LZ的问题到底解决没有…… 问题根源不是字符串替换的效率。即便是数千倍的差异,但是都能秒级别替换完。所以这个也不重要了。 最后似乎并没有解决吧,因为D11的RichEdit无法高效显示太大的字符串。 是这样吧?
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 15:15:09
68楼:
const fn = 'f:\test2.txt'; var str, tmp : String; c, i : Integer; begin // {$IFDEF UNICODE} str := System.IOUtils.TFile.ReadAllText(fn); {$ELSE} str := readAllUTF16Text(fn); {$ENDIF} c := GetTickCount; {$IFDEF UNICODE} tmp := StringReplace(str, '人','★',[rfReplaceAll]); {$ELSE} tmp := Q_ReplaceStr(str, '人','★'); //tmp := StringReplace(str, '人','★',[rfReplaceAll]); {$ENDIF} c := GetTickCount - c; Caption := IntToStr(C); end; 同一套代码,去掉你所谓的RichEdit。 在Delphi7里面用你的Q_ReplaceStr,在D11里面用StringReplace。 跑你上面上传的文件,各自测试10次 D7的Q_ReplaceStr的耗时在78-91ms之间 D11的自带StringReplace,在31-46ms之间。 你所谓慢还是慢在D11里面集成微软新的RichEdit,增强的内容特别多,所以慢。实际上单单看字符串替换,D11自带的StringReplace比你所说的Q_ReplaceStr还要快。 结论: Q_ReplaceStr确实比D7自带的StringReplace的要快上几千倍, 但是D11自带的StringReplace比Q_ReplaceStr还要快一倍左右。 D7的RichEdit使用的微软提供的RICHED32.DLL是旧版,功能少,速度快 D11的RichEdit使用的是微软提供的MSFTEDIT.DLL,是4.0以上的版本,功能锁,速度慢。 如果你又想替换快,又想RichEdit加载快。那就用D11,然后使用旧版的RichEdit的DLL。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 15:20:13
68楼:
to ddrfan:我之所以说Editor.Text:=tmp没区别,有2个原因,第一,用不同替换函数,这语句本身确实没区别,第二,是因为这个赋值对结果影响极小,在D7下可以说没有影响,因为D7的StringReplace函数效率比大神的汇编Q_Replace低了几百倍,文件大时差距上千倍,3个数量级了,就赋值的那点时间完全可以忽略不计,因为毕竟Q_Replace替换+显示干完64.2MB的文件也就3.3秒,说明Editor.Text:=tmp这个语句实际耗时很小,可以忽略了。 和你的情况不一样,你是逐行显示,所以这个UI慢会累加,我的是一次替换,UI慢不会累加,在总时间面前没影响。你的工作要考虑几十GB的文本?啥工作啊,这么大的文本,干嘛用的,哈哈! 另外,有个灵异现象(也就是D11下的StringReplace效率问题基本解决了,比D7的高了非常多,接近了大神的汇编Q_Replace,虽然稍慢,但在一个数量级上了),就是前天晚上我用D11编译我那个程序并放出StringReplace耗时截图(9楼的那个截图,附到后面),当时替换速度确实很慢,和D7下差不多慢,载入64.2MB那个TXT也非常慢,但是昨天原来的代码重新在D11下编译时速度却非常快,接近了D7下大神的汇编Q_Replace,效率只低了4倍不到了,你说怪不怪?所以现在问题基本解决了,在D11下替换用StringReplace即可,问题不大了。
----------------------------------------------
-
作者:
2022/1/19 16:49:01
69楼:
我没试 Editor.Text:=tmp,因为当时不知道楼主是这么写的。 但是我试了Editor.Line.AddStrings D7下加载不出来会报错。 D11下速度取决于传入的参数是不是界面的内容。 也试了Editor.Line.LoadFromFile 看我在31楼写的【显示用时3.3秒】就是指它。 替换用时1.1秒左右。 显示用时3.3秒左右。 这几个函数不仅是内部的字符串操作,还要在UI上显示出内容。 很可能不是楼主说的“就赋值的那点时间完全可以忽略不计”…… 【LoadFromFile】大概3.3秒,所以我推测【Text:=】基本耗时相同。 所以我推荐楼主分步骤测试一下。 楼主仔细看看上面的逻辑。 以及实际测试的速度: LZ:“毕竟Q_Replace替换+显示干完64.2MB的文件也就3.3秒” 我:“替换用时1.1秒左右。” 我:“显示用时3.3秒左右。” 综合前面得到的结果:Q_Replace比D7自带replace快1000倍。 结论就非常明显了, 和我在67楼说的一样:加入界面的影响后,对测试函数速度是致命的影响。 为啥我要回复那么多次,是因为我看到楼主最后一贴里面,还是有很多不对的逻辑。很着急啊。。。 比如上面那句替换+显示觉得显示部分赋值不耗时的推测。 比如“你是逐行显示,所以这个UI慢会累加”根本没看我的代码呀…… 实际上代码都贴了,加个计时器自己测试一下,比猜测和怀疑有用得多(楼主甚至让我录屏证明……)哈哈^o^ 希望楼主理解:)
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 18:31:16
70楼:
to wr960204:晚点我再测试一下D11下StringReplace的效率,这两天相同的代码表现不稳定,被我前面称为“灵异现象”,还不知道原因。就如下面这个截图,当时就是D11下用StringReplace做的测试,很慢,但现在发现D11的StringReplace很快,就好像经过运行多次相同的代码后有“优化”似的…… 之前68楼的图贴错了,重贴:
----------------------------------------------
-
作者:
2022/1/19 18:49:44
71楼:
to ddrfan:你的替换方式是通过循环逐行替换,不是替换一行显示一行?如果不是逐行显示,那就没必要说逐行替换,因为你替换的内部工作方式我不关心啊,我关心的是结果,就是说从点下鼠标替换开始到替换完成显示在编辑框里的时间。而这个过程中,赋值也就是显示的时间是固定的,且占比例不高,很简单,因为D7下64.2MB用Q_Replace替换仅3.3秒,所以显示时间一定是小于3.3秒,而StringReplace则可能要几个小时(没有实际测试完毕,因为太慢了),这个显示时间对于StringReplace来说完全可忽略不计,也就是说StringReplace慢根本就不是因为UI显示的原因,我一直在强调这个观点。 但你们很多人非要抓住Richedit参与了替换时间,StringReplace效率测试不纯粹,这样说没有意义!因为第一刚才说了,显示时间比重可忽略不计,第二发现D7的StringReplace效率低并不是做测试发现的,而是实际使用发现的,于是提出了主贴的问题。你们没抓住问题的重点,虽然绝对来说好像排除UI显示的时间对于测试StringReplace的效率是科学的,但实际上因为你们忽略了我说的前提,所以是没有意义的,你现在还在强调这个,可见,重点错了。为什么D7的StringReplace效率比Q_Replace慢几百倍甚至几千倍?归根结底还是这个函数写的不高效,虽然排除UI参与后速度提升了,但Q_Replace排除UI后提升的更厉害,效率高低是相对的! 说了半天,逻辑不对的是你们,不是我。
----------------------------------------------
-
作者:
2022/1/19 20:30:35
72楼:
好吧楼主你赢了。 我们不对。 我测试的D7原版replace60多MB: 替换用时1.1秒左右。 显示用时3.3秒左右。 肯定是假的。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 21:15:58
73楼:
你D7下用StringReplace来替换60MB的那个文件替换用时1.1秒根本就不可能,肯定假的。如果有这效率,我还会说它低效吗? 要不你把你的源代码放上来,大家看看?
----------------------------------------------
-
作者:
2022/1/19 21:35:54
74楼:
to wr960204:单独又试了一下,现在D11下的StringReplace确实比D7下的Q_Replace还快点,没想到D11下的StringReplace比D7下的完全是脱胎换骨的提升!了不起!
----------------------------------------------
-
作者:
2022/1/19 21:49:26
75楼:
楼主,你用错误的测试方法得出了一个错误的结论,赶紧认个错回去优化你的代码吧
----------------------------------------------
-
作者:
2022/1/19 22:10:51
76楼:
D11的StringReplace比D7下的Q_Replace快不仅仅有这个好处,而且是纯Pascal实现的,可以编译到Android,IOS,Linux,MAC等各个平台,比Q_Replace通用不少。 实际上D11的StringReplace和Q_Replace用的同样类似的方式,就是先Pos到所有的匹配字符串,然后算好Result的长度,一次性分配。你自己写的那个之所以非常慢主要就是慢在不停的重新分配Result的内容和长度。 那两个函数都可以看成下面这个基本函数的变形,下面这个函数是在D11上调试的,比内置的StringReplace慢一丝丝,主要是拷贝没有细分情况处理。 function StrReplace(const Source, OldPattern, NewPattern: string): string; const arraySizeStep = 4096; var p, I, patternCount: Integer; oldPatternLen, NewPatternLen, SourceLen: Integer; poses: TArray<Integer>; posesSize: Integer; PDest, pSource, copyLlen: Integer; begin oldPatternLen := Length(OldPattern); NewPatternLen := Length(NewPattern); SourceLen := Length(Source); if (SourceLen < oldPatternLen) or (OldPattern = NewPattern) then begin Result := Source; Exit; end; posesSize := arraySizeStep; SetLength(poses, posesSize); // 把计算好的替换字符串位置填写到poses数组里面 p := 0; patternCount := 0; while true do begin p := Pos(OldPattern, Source, p + oldPatternLen); if (p = 0) then begin Break; end; Inc(patternCount); if posesSize < patternCount then begin Inc(posesSize, arraySizeStep); SetLength(poses, posesSize); end; poses[patternCount - 1] := p; end; // if patternCount > 0 then begin // 计算好返回值的长度,免得一次次重新分配移动,否则这里将成为最耗时的 SetLength(Result, Length(Source) + patternCount * (NewPatternLen - oldPatternLen)); PDest := 1; pSource := 1; // 把Source内容和NewPattern内容拷贝到Result里面。 for I := 0 to patternCount - 1 do begin // 拷贝Source copyLlen := poses[I] - pSource; Move(Source[pSource], Result[PDest], SizeOf(Char) * copyLlen); Inc(pSource, copyLlen); Inc(PDest, copyLlen); // 拷贝NewPattern Move(NewPattern[1], Result[PDest], SizeOf(Char) * NewPatternLen); Inc(PDest, NewPatternLen); //源偏移跳过oldPattern Inc(pSource, oldPatternLen); end; // 拷贝Source最后一部分 copyLlen := SourceLen - pSource; if (copyLlen > 0) then Move(Source[pSource], Result[PDest], SizeOf(Char) * copyLlen); end else Result := Source; end;
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 22:35:41
77楼:
to kentty:并没有。一开始我用D11的StringReplace就是很慢,就是这个图中的下面那副图的结果(477KB的文件替换),很慢,这是事实,不是我瞎编的,所以才会主贴中那么说。否则怎么可能呢?我也不知道为什么出现这种状况。
----------------------------------------------
-
作者:
2022/1/19 22:40:06
78楼:
to wr960204:我就是一业余的菜鸟,就根据POS函数鼓捣了一下而已,没技术含量,和D7的StringReplace也没得比。 但就是如此,在当时测试这个自定义的替换函数时却没有比StringReplace慢很多,我还列出了具体毫秒数,但现在用这个自定义的函数比D7自带的StringReplace也慢得多,包括当时D11下的StringReplace也很慢。真不知道当时是啥情况,为啥出现这种“灵异现象”?
----------------------------------------------
-
作者:
2022/1/19 23:04:48
79楼:
看了上面些贴子,好佩服武稀松,真的做到诲人不倦,难能可贵。
----------------------------------------------
-
作者:
yookee (yookee)
★☆☆☆☆
-
盒子活跃会员
2022/1/20 1:12:26
80楼:
楼主浪费大家的时间与我无关 但是楼主引出了武大关于新版StringReplace已经变快的结论 嗯,我还得感谢一下楼主
----------------------------------------------
-
作者:
2022/1/20 5:35:18
81楼:
这个问题是由TRichEdit字体的字符集设置错误引起的,可以重现,不是“灵异现象”。 字体为简中字体,如宋体、微软雅黑时一切正常;字体为非简中字体,如Ariel、Segoe UI时显示速度奇慢。
----------------------------------------------
-
作者:
vga (vga)
★☆☆☆☆
-
盒子活跃会员
2022/1/20 11:40:14
83楼:
"Talk is cheap, show me the code! " ^_^
----------------------------------------------
-
作者:
2022/1/20 11:40:19
83楼:
不管是编程,还是干别的什么事情,查问题的时候,尽量把不相关的东西分开,一个一个查,而不是搅合到一起去查。这个是做事情的基本思路。但是,我发现,很多人不具备这种简单的思路。 如果中学物理学得好,这种思路应该是初中就会培养出来的。
----------------------------------------------
-
作者:
2022/1/20 17:12:18
84楼:
我那是吐槽,没想到楼主真的不信。 之前代码删了,又写了一次。 不过楼主说对了,确实不能那么快,因为笔记本要慢一些。。。 procedure TForm1.Button1Click(Sender: TObject); var t: TDateTime; begin t:=now(); RichEdit1.Lines.LoadFromFile('D:\Testddd.txt'); ShowMessage( Format( '%d毫秒,第一次加载。总长度%d。',[MilliSecondsBetween(Now(),t),Length(RichEdit1.Text)]) ); end; procedure TForm1.Button2Click(Sender: TObject); var t: TDateTime; //aTmpS: TMemoryStream; //为什么连流都慢? aTmpS: String; aInList,aOutList: TStringList; i: Integer; begin t:=now(); aTmpS:='D:\Testddd.tmp';//TMemoryStream.Create; aInList:=TStringList.Create; aOutList:=TStringList.Create; RichEdit1.Lines.SaveToFile(aTmpS); aInList.LoadFromFile(aTmpS); for i:=0 to aInList.Count -1 do begin aOutList.Add(StringReplace(aInList[i],'人','★',[rfReplaceAll])); end; ShowMessage( Format( '%d毫秒,替换字符串。',[MilliSecondsBetween(Now(),t)] ) ); t:=now(); //aTmpS.Clear; aOutList.SaveToFile(aTmpS); RichEdit1.Lines.LoadFromFile(aTmpS); FreeAndNil(aOutList); FreeAndNil(aInList); //FreeAndNil(aTmpS); ShowMessage( Format( '%d毫秒,替换后加载。',[MilliSecondsBetween(Now(),t)] ) ); end; 也是年末闲得……顺便祝大家虎年大吉 :)
此帖子包含附件: 大小: 91.7K
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/20 17:16:58
85楼:
parhelia分析的有道理。 pcplayer说的有道理。
----------------------------------------------
-
作者:
2022/1/21 0:46:35
86楼:
to ddrfan:今天太忙了,才刚回来。你这代码贴出来了,我仔细看了看,你这证明不了你的观点,反而是证明了我的观点:D7的StringReplace函数效率低下,在大文件时极其低下! 你这用的StringReplace虽然性能看起来提高了很多,但是并非是StringReplace效率高,而是你通过TStringList将超大的文件分割成一个个超超超小的文件(每个只有几十个字)来提升整体的效率,因为StringReplace在小文件是效率比大文件时要高,并且替换时间、显示时间均单独计算,即便如此,加在一起也比Q_Replace慢得多。 另外,我用你的代码在D7下编译,很明显达不到你贴图上的效率,我第一次加载比你快,你4秒,我这里只要2.3秒,但你替换才1.7秒?我这11.3秒,你替换后加载4秒,我这37秒多,这可能吗?还是你哪里做了手脚呢? 第一次加载比你快我理解成我是M.2固态硬盘,所以快一点,但我替换11.3秒你才1.7秒,这效率差了6.6倍!要知道我的CPU是8核I7 11800H,这已经是高端CPU了,就算拿目前单线程跑分最牛逼的桌面12代旗舰12900K,单线程效率也只不过比11800H高了30%而已,而你也不过是笔记本,相信你就算是最顶级的旗舰CPU也不会比我的11800H高个百分之几,怎么可能有6.6倍?就算是2倍也不可能。后面重加载时间也是如此,你的效率高了9倍多,怎么可能?看我的截图。
此帖子包含附件: 大小: 1.14M
----------------------------------------------
-
作者:
2022/1/21 0:51:01
87楼:
to hardnut:码龄几年不重要,写过多少行代码也不重要,我又不是程序员,也不靠编程吃饭。 to pcplayer:只能说,你还没.理.解问题的本.质到底在哪里。
----------------------------------------------
-
作者:
2022/1/21 1:16:06
88楼:
to parhelia:试了一下,果然如此,同一个文件,用微软雅黑字体时替换只要几百毫秒,用Segoe UI字体则要30多秒,真的重现了!我说怎么回事,真可能是当时无意中字体变化了没注意。十分感谢!
----------------------------------------------
-
作者:
2022/1/21 16:21:51
89楼:
字体和字符串替换有啥关系?完全就是两码事,非要扯到一起来查,当然查不出来。 一个人又吃了耗子药,又打了篮球。非要说打篮球会致命。
----------------------------------------------
-
作者:
2022/1/21 20:54:10
90楼:
to pcplayer:相同条件下自然可以相提并论!
----------------------------------------------
-
作者:
2022/1/21 21:17:53
91楼:
对于替换我没有任何观点。。。 我测出来是怎样的,就写了出来而已。 我的观点是实验要减少干扰,能细分就不要混在一起。 前面你11秒多才替换完。 可能是因为字体原因,存盘慢了。 纯猜的…… 理由如下,耗时的代码只有这几句。其它的时间可以忽略。 //UI组件可能受干扰因素较多。 RichEdit1.Lines.SaveToFile(aTmpS); //时间相对固定 aInList.LoadFromFile(aTmpS); //时间相对固定 for i:=0 to aInList.Count -1 do begin aOutList.Add(StringReplace(aInList[i],'人','★',[rfReplaceAll])); end; PS:我的笔记本是10870H,不快。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/21 21:20:50
92楼:
顺便多说一句:既然分步骤太多,不如打个日志,省的弹窗了。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/21 21:41:32
93楼:
to ddrfan:问题是,我用的就是你的代码,没改动。我的硬件比你的强,同样的Delphi 7,速度反而低6~9倍,不科学吧。系统是WIN11,不说效率高不会比WIN10低多少吧?字体是微软雅黑,你啥字体?低6~9倍不科学。 再说了,你这个测试证明不了你的观点,证明的是我的观点:D7的StringReplace函数效率低,大文件效率则极低,你是在规避而已。
此帖子包含附件: 大小: 221.5K
----------------------------------------------
-
作者:
2022/1/21 22:09:08
94楼:
没想到这个话题还没结束 :) to 楼主, 2+3<1+5大家都同意,但是推理出来2<1就不是所有人都认同了。 如果你知道我在说什么,就不要回复了 上面好几个帖子都在告诉你你的方法不对,包括你不赞同的pcplayer,简直是高屋建瓴,并且告诉你了“相对更加正确”的方法,你一直在纠缠你测试来的结果就是这样。测试结果是没错,但是结论错了 遁了~~~
----------------------------------------------
-
作者:
2022/1/21 22:36:35
95楼:
大家不要说了, 人家不靠这个吃饭, 人家开心就好, 我们这些老coder又何必惹人家不开心呢? 我希望我这个回复是这个帖子的最后一个回复.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/21 23:27:06
96楼:
to kentty:你的类比明显不正确。何来 2+3<1+5推理出来2<1??? 其实问题早就很清楚了,按顺序列举如下: 1.我已知D7下的StringReplace函数效率低下,于是本身用网上大神用汇编写的Q_Replace替代,速度极快,效率极高。 2.刚安装D11,想将D7的程序拿到D11下重新编译(主要是为了获取Richedit可以载入带图片的RTF格式文件),但发现在D11下Q_Replace不能使用。 3.经过了解,确定是D11的String和D7的String不一样,于是修改Q_Replace函数的String为AnsiString,发现Q_Replace可以正常工作了,但是看起来效率降低了,比D7下慢很多,而且发现替换Q_Replace到StringReplace发现两者几乎一样慢,降到了和D11自带的StringReplace同一个水平(实际是因为Richedit字体原因导致当时D11下的StringReplace极慢,但当时未发现是该原因,以为D11下的StringReplace和D7下的一样效率低下)。 4.于是发帖问原因,是D11下字符串效率不行还是我没整对?其默认前提其实很简单,其它条件都一样,只是改了Q_Replace到StringReplace函数,但速度下降极大。 5.过后众多网友都来讨论这个问题,但是大多数人都偏离了方向,没搞清问题的本质到底是什么,大多都在讨论什么StringReplace效率不低,什么要衡量的StringReplace的效率应该排除UI,应该排除一切干扰……严格说,没有本帖的前提的话,是正确的,但在本帖中,这就是正确的废话!事实也证明了这一点,D7下的StringReplace有没有UI和其它因素影响其效率对比Q_Replace都极其低下!效率低不低看跟谁比和实用性如何,这2点实际D7下的StringReplace效率都低!其1,因为D7下的StringReplace在编辑器中替换数百KB的文本内容时其时间就变得难以忍受!其2,StringReplace效率比Q_Replace低数千倍!这2点,那些个喜欢抬杠的网友解决了?解释了?没有! 6.后来wr960204 (武稀松)网友经过测试得出了正确的结论,D7下的StringReplace效率确实低,比Q_Replace低千倍!但在D11下反而比Q_Replace效率还略高。经本人测试,发现的确如此,和我之前测试的结论“D11下的StringReplace也低”不符合,其中为什么D11下当时StringReplace效率也很低下?但这是当时测试的事实,我不知道原因,只好称之为“灵异现象”。但网友parhelia (-_-)指出,这其实不是灵异现象,是可以重现的,是字体原因造成,经验证,的确是,于是该问题有答案了:我一开始测试D11下的StringReplace效率低下的事实是因为字体导致的,并非其真实表现,我肯定了wr960204 (武稀松)的结论。 7.本来问题已经解决,事实也很清楚了。但是部分网友还在纠结我所谓衡量效率的方式不对,其实是他自己不对,他忘了前提,说了正确的废话而已。他们这个所谓“相对更加正确的方法”根本不是本人不会,是本人认为没有必要,因为该问题本身已经可以证明了主贴中的问题!只是有些人领会不到什么叫前提,什么叫整体。就好比,房间黑暗拉开窗帘光照射到房间小明眼睛就疼,我得出结论认为是光刺激了小明眼睛导致眼睛疼。这些网友认为,应该将小明送到医院,逐一检查眼睛疼的具体原因,要排除一切干扰:比如,去拉窗帘导致空气流动有风,会有影响,窗帘拉开后形态变化,对其眼睛也可能会有影响,窗帘拉动导致灰尘扩散、细菌传播……不得不说,这都可能是“正确的”废话!我不爱听废话,更不爱那些抓不住问题重点和本质的人,这些人大多没什么统筹力、领导力,实际解决问题的能力也不会很强。
----------------------------------------------
-
作者:
2022/1/22 1:57:21
97楼:
StringReplace效率大幅提高是最近几年的一个官方改进,是有官方宣布的,李维都专门讲过这个问题,你们都不知道吗?算是最近几个版本的小小亮点之一。
----------------------------------------------
只有偏执狂才能生存!
作者:
2022/1/22 16:52:05
98楼:
to nevergrief (孤独骑士):还真不知道这事。李维不是早就去微软了吗,怎么还专门讲StringReplace效率大幅提高这事啊?
----------------------------------------------
-
作者:
2022/1/22 20:02:00
99楼:
下面的代码就是按楼主的方法直接替换RichEdit1里面的文本了,用一台10年老电脑(E3 1230V2)来测试,耗时为6.4秒,这个结果应该和使用Q_ReplaceStr差不多了。Delphi版本: 10.3.3 procedure TForm1.ButtonModClick(Sender: TObject); var DeltaTime: TDateTime; begin DeltaTime := Now(); //耗时为6.4秒 //62M文本数据 RichEdit1.Text := StringReplace(RichEdit1.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); DeltaTime := Now() - DeltaTime; EditMod.Text := FormatDateTime('s:zzz', DeltaTime); end;
----------------------------------------------
-
作者:
2022/1/22 20:41:59
100楼:
to bluestorm8:嗯,后来的那么多回复估计你都没看,已经确认后来新版Delphi已经大幅提高了StringReplace的效率,具体从哪个版本提高的不太清楚。
----------------------------------------------
-
作者:
2022/1/29 23:50:06
101楼:
原因: 虽然用了AnsiString实现了功能,但Delphi11的界面控件是Unicode的,所以从界面里读数据要经过一次转换,写回界面又经过一次转换。 建议: 1、直接改汇编代码使其支持Unicode 2、不要在界面里直接替换数据,替换好了再加载。 3、超大的数据也不要在界面里一次加载,就算加载了也没有屏幕能显示下,影响效率。
----------------------------------------------
-
作者:
2022/2/2 18:56:05
102楼:
to pkwoinsert (啊舒服):感谢指导!不过没能力改汇编代码了,看都看不懂汇编,更不要说改了……另外,我发现大神的那个汇编替换函数有个BUG,就是在用不区分大小写的函数Q_ReplaceIgn时,中文字符“人”和“入”不能区分,替换其中之一时另外一个字也被替换掉了,不知道还有没有其它字也这样……我修改了其中早已定义好的ToUpperChars部分(应该就是关于大小写的字符,比较多,有256个,不过我想着大小写不就是只有英文26个字母共52个吗,怎么有256个之多),但即便改成只有26个大小写英文字母后,上述“人”和“入”还是没法区分…… const ToUpperChars: array[0..255] of Char = (#$00,#$01,#$02,#$03,#$04,#$05,#$06,#$07,#$08,#$09,#$0A,#$0B,#$0C,#$0D,#$0E,#$0F, #$10,#$11,#$12,#$13,#$14,#$15,#$16,#$17,#$18,#$19,#$1A,#$1B,#$1C,#$1D,#$1E,#$1F, #$20,#$21,#$22,#$23,#$24,#$25,#$26,#$27,#$28,#$29,#$2A,#$2B,#$2C,#$2D,#$2E,#$2F, #$30,#$31,#$32,#$33,#$34,#$35,#$36,#$37,#$38,#$39,#$3A,#$3B,#$3C,#$3D,#$3E,#$3F, #$40,#$41,#$42,#$43,#$44,#$45,#$46,#$47,#$48,#$49,#$4A,#$4B,#$4C,#$4D,#$4E,#$4F, #$50,#$51,#$52,#$53,#$54,#$55,#$56,#$57,#$58,#$59,#$5A,#$5B,#$5C,#$5D,#$5E,#$5F, #$60,#$41,#$42,#$43,#$44,#$45,#$46,#$47,#$48,#$49,#$4A,#$4B,#$4C,#$4D,#$4E,#$4F, #$50,#$51,#$52,#$53,#$54,#$55,#$56,#$57,#$58,#$59,#$5A,#$7B,#$7C,#$7D,#$7E,#$7F, #$80,#$81,#$82,#$81,#$84,#$85,#$86,#$87,#$88,#$89,#$8A,#$8B,#$8C,#$8D,#$8E,#$8F, #$80,#$91,#$92,#$93,#$94,#$95,#$96,#$97,#$98,#$99,#$8A,#$9B,#$8C,#$8D,#$8E,#$8F, #$A0,#$A1,#$A1,#$A3,#$A4,#$A5,#$A6,#$A7,#$A8,#$A9,#$AA,#$AB,#$AC,#$AD,#$AE,#$AF, #$B0,#$B1,#$B2,#$B2,#$A5,#$B5,#$B6,#$B7,#$A8,#$B9,#$AA,#$BB,#$A3,#$BD,#$BD,#$AF, #$C0,#$C1,#$C2,#$C3,#$C4,#$C5,#$C6,#$C7,#$C8,#$C9,#$CA,#$CB,#$CC,#$CD,#$CE,#$CF, #$D0,#$D1,#$D2,#$D3,#$D4,#$D5,#$D6,#$D7,#$D8,#$D9,#$DA,#$DB,#$DC,#$DD,#$DE,#$DF, #$C0,#$C1,#$C2,#$C3,#$C4,#$C5,#$C6,#$C7,#$C8,#$C9,#$CA,#$CB,#$CC,#$CD,#$CE,#$CF, #$D0,#$D1,#$D2,#$D3,#$D4,#$D5,#$D6,#$D7,#$D8,#$D9,#$DA,#$DB,#$DC,#$DD,#$DE,#$DF);
----------------------------------------------
-
作者:
2022/2/7 8:54:45
103楼:
StringReplace在D11比D7肯定要快很多。
----------------------------------------------
-
作者:
2022/2/9 9:59:58
104楼:
StringReplace 里面用到move,pos等几个函数,从Delphi2005开始就使用了fastcode提供的版本,后续的新版集成了很多fastcode的函数,和fastmm内存管理器的加持,我也觉得新版本的性能更好。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
2022/2/16 17:20:09
105楼:
D7 编译器的环境不一样,结果也不一样 FastMM MidasSpeedFix VCLFixPack DelphiSpeedUp
----------------------------------------------
-