DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: tino0914
今日帖子: 28
在线用户: 15
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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下字符串处理效率没救了吗?还是我没整对,望大神赐教!
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 14:17:07
1楼: 有高手了解吗?
----------------------------------------------
-
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
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/
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 14:30:58
3楼: to keymark (嬲):啊!这种问题搜也不好搜,网上找了很多所谓高效字符串替换函数,到D11下一测试都不行,效率都很低了
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 16:05:01
4楼: 搜了半天,也没找到类似的答案解决这个效率问题
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
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 -- 您最贴心的个人数据管理助手
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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函数的人水平肯定比我高多了……
----------------------------------------------
-
作者:
男 744840146 (744840146) ▲▲▲▲▲ -
普通会员
2022/1/17 17:29:51
7楼: 试试mormot的stringreplaceall这个方法
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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;
----------------------------------------------
-
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
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/
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2022/1/17 18:45:59
7楼: 你修改之后能用, 是因此系统先将unicode string转换成ansi string,然后旧代码可以正常工作了,然后 再将结果ansistring转换成unicode string, 这两次转换都是非常费时的,特别是涉及到非英文字符时,基本上没有什么取巧,都是一个一个字符查表处理.

StringReplace我看了,写得已经很高效了.因此我觉得不应该它的问题. 可能还是你不小心导致了自动编码转换. 如果你能放出一个demo, 也许我可以帮你看看.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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倍!用天壤之别来形容毫不为过啊!
此帖子包含附件:
JPEG 图像
大小:587.9K
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 18:59:00
10楼: to hardnut:不是的,Delphi自带的StringReplace函数在D7下就很慢,当文件达到数百KB的时候执行时间就基本无法让人忍受了。我用纯文本文件测试,网上汇编的那个Q_ReplaceStr函数,3370万字(64.2MB)替换上述相同的“人”字为“★”,耗时也就3.3秒,替换了377460处,这效率高的发指!如果让StringReplace来执行(文件越大效率越低,并不是和大小成正比关系),几个小时都搞不完,说不定死机了!
此帖子包含附件:
JPEG 图像
大小:635.6K
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 19:14:19
11楼: 这是网上的那个高手用汇编写的替换函数,大家可以自己对比测试一下,D7下工作正常,效率极高,比Delphi自带的StringReplace函数效率高数百倍!
此帖子包含附件:wufan314_2022117191622.txt 大小:24.9K
----------------------------------------------
-
作者:
男 xiaobaosoft (小宝软件) ▲▲△△△ -
普通会员
2022/1/17 20:06:19
12楼: 吧数据发出来 别人才可以测试。不然都是口水
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 20:22:47
13楼: to xiaobaosoft :发出来了啊,连网上大神的那个汇编替换函数都发出来了,还有对比测试的截图都有啊
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2022/1/17 20:32:52
14楼: 把你的那个64.2MB测试数据压缩下发出来
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 20:43:53
15楼: to hardnut:那个就是同一个内容的TXT不断重复搞成了一个超大的TXT文件。压缩成7z后仅24KB。7z不让传,改成zip,文件就大多了,496KB,见附件。
此帖子包含附件:wufan314_2022117204350.zip 大小:497.0K
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
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 -- 您最贴心的个人数据管理助手
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2022/1/17 21:05:52
17楼: 用你的测试数据, 但你发出来的是gb2312, 我是先转换成 ucs 2 le bom格式再保存为test2.txt的

因此,最大可能还是你没有用对
此帖子包含附件:hardnut_202211721551.zip 大小:627.6K
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 21:35:43
18楼: to hardnut:你不能那么执行的,要在文本编辑器的图形界面下操作,就像记事本里面那样,要基于已经打开的、在编辑器里面的文件内容进行操作。你把你的这个代码转换到编辑器界面你再试试,我试了,等同于死机了……
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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]);
这有啥区别?上面的不过多了一道赋值,这不费啥时间啊,为啥执行起来效率相差数百倍?
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/1/17 22:33:38
18楼: 楼主,
我用你的例子数据,就是60多MB的文本试了一下,替换所有“人”字为“★”。
我这里大概只用了1.4秒多。

用的是你原始文件,GB2312,或者GBK,或者GB18030编码(这个没有影响)。
从文件里面读一行出来,替换后写入新的文件,直到写完。
没有加什么缓存。

StringAnsiString都试了,时间上没什么区别。
所以我估计慢不在替换,而是字符串(过大)的处理不一样吧。
毕竟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;


比较:
此帖子包含附件:
PNG 图像
大小:507.6K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 22:47:09
20楼: to ddrfan:你是基于Richedit编辑器里的文本内容处理的还是基于文件的内容处理的?在基于文件的是比较快,但基于Richedit编辑器等UI里的文本内容则很慢,上面我说过了,你看一下,也可以测试一下。我看你的代码,也和前面那位朋友一样是基于文件处理的,不是基于Richedit编辑器里的文本内容处理的。
----------------------------------------------
-
作者:
男 xjia (xjia) ★☆☆☆☆ -
盒子活跃会员
2022/1/17 23:11:41
21楼: 20楼:
那是不是就不是替换的问题,是界面显示的原因?
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/17 23:24:37
22楼: 但是那个汇编编写的替换函数Q_ReplaceStr为什么那么快?它包含界面+替换的时间仍然远远小于StringReplace纯界面的时间,说明函数本身有很大影响。同样都不用界面,Q_ReplaceStr的速度比StringReplace领先的更多,快数千倍。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/1/18 9:15:43
23楼: 那可能就是我说的:
慢不在替换,而是字符串(过大)的处理不一样吧。
毕竟Delphi11早已跨平台了,而Delphi7不用考虑别的平台,也不用管啥unicodestring,widestring。


你用的Richedit,我只能猜基于上面的原因(毕竟隔了20年)VCL组件变化也很大?
毕竟现在内部都用双字节字符串了。

我再试试看……
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 10:08:02
24楼: to ddrfan:但是那个汇编编写的替换函数Q_ReplaceStr很快啊,同样是D7,它快几百倍,同样没有界面的时候它比StringReplace快的更多,速度不是几百倍而是几千倍了。
我觉得和VCL组件没多大关系,因为是基于同样的组件啊,别人就快几个数量级,这能说是组件的问题吗对吧。和是否D7或者D11也没关系,同为D7它就快得多,还是函数本身的问题。
你也用基于显示界面测试看看,看看效率如何,不出意外应该和我这表现差不多。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 10:26:53
25楼: to ddrfan:我在D7下RichEdit加载这个64.2MB这个文本只要几秒钟啊!刚用秒表掐了一下,4秒而已,很快。
就算界面慢,但是为什么人家那个汇编编写的替换函数Q_ReplaceStr很快呢?64.2MB的文件人家替换完毕到显示完成仅3.3秒!这说明不是界面慢的问题。
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 10:44:22
26楼: 我的笔记本Thinkpad pad t530 i5-3210m 8G内存,win32 X11编译,执行替换楼主的64兆文本,约200毫秒,delphi x11 文本替换性能没什么问题
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 10:46:57
27楼: 测试楼主的64兆文本,我自己写的替换函数319好毫秒,delphi x11自带的函数200毫秒,和楼主说的天差地别
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 10:47:56
28楼: 楼主肯定搞错了
----------------------------------------------
-
作者:
男 hexi (Hexi) ★☆☆☆☆ -
盒子活跃会员
2022/1/18 12:55:55
29楼: 楼主是不是把刷新显示时间也算到stringreplace里面去了
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 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...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/1/18 15:36:29
32楼: 个人总结:
1)字符串替换D11和D7其实区别不大。可能效率不是特别高,但是没那么夸张的慢。

2)D11因为要考虑的情况太多,界面用RichEdit展示很大的文本内容效率没有D7高。

3)测试归测试。即便是非界面,也建议不要用TStringList一类来处理文本文件,万一文件很大几十个GB呢。。。在《这个帖子》里面有一些相关文本读写的讨论。PS:提到了Go效率高,都有人不高兴。。。

怎么展示/编辑那么大的文本,只能结合自己业务逻辑来考虑。对我RichEdit好像只是为了展示有格式的文本会用。工作关系几乎没用到过,只有一个内嵌的帮助用了?找了一下如下图(好像和主题无关):
此帖子包含附件:
PNG 图像
大小:41.2K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 18:45:37
33楼: to hq200306:你要到UI界面下测试,不是LS几位朋友那样,你认真看一下我的回复就知道了。
我这里贴出我自己改造的文本编辑器,大家可以用替换或者“智能分段”和“段落重排”功能测试我贴的那个64.2MB的TXT文件,也可以用WPS或者WORD等软件同样替换对比看看,当然自己也可以写个简单实现替换功能的文本编辑器测试就知道了。
此帖子包含附件:wufan314_2022118184529.zip 大小:2.50M
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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秒左右?那真不可能!你录屏看看?
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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一样低下了,于是提出了主贴的问题。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 19:04:52
36楼: to hexi:我计算时间是在替换前用一个高精度的计时控件开始计时(比GetTickOut函数精度高很多,当然这个也够用了),然后替换完毕后计时结束,计算两者差值。不存在另外的显示时间的。你测试要用文本编辑器界面,就像记事本那样,不能是创建一个TStringList在后台替换,这没有实际意义。前面我说了,虽然这样搞Delphi自带的函数StringReplace很快,但是如此一来大神写的那个汇编替换函数Q_ReplaceStr更快,比Q_ReplaceStr快1000倍以上!效率是相对的,相比之下StringReplace就是蜗牛速度了,也就是效率低。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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;
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 19:18:07
38楼: 我将我的文本编辑器Noteedit(基于Richedit,D7编写,前面已上传该文本编辑器exe文件)载入64.2MB文本文件录制视频并转换成GIF动画了,大家看看载入时间,不足4秒。
此帖子包含附件:
GIF 图像
大小:306.5K
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 19:25:49
39楼: 再贴个大神汇编Q_Replace函数(该函数前面帖子中已上传)替换64.2MB文件“人”到“★”耗费的时间动画,替换约37.7万处完毕3.3秒不到。
此帖子包含附件:
GIF 图像
大小:289.7K
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 19:35:44
40楼: xe11的替换文本函数性能确实没问题,测了替换64兆文本,只花0.2秒,楼主是把文本替换和界面显示混为一谈,稀里糊涂
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 19:45:15
41楼: to hq200306:麻烦你完整看下我的回复就知道到底什么问题了。是你想的那么简单我还需要来这提问吗?
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
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;
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 20:47:43
44楼: 200毫秒?不可能!你啥CPU?你Delphi什么版本?我就不信你能例外!经过测试,D11的StringReplace比D7效率高了不少,但是比我发的那个汇编的替换函数还是蛮了好几倍,D7下汇编的那个64.2MB替换都要3.3秒,你StringReplace只要200毫秒?忽悠谁啊,哈哈哈!
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 20:51:50
45楼: Thinkpad pad t530 i5-3210m 8G内存,win32 XE11编译,计算时间174毫秒
此帖子包含附件:
PNG 图像
大小:2,576B
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 20:52:30
46楼: 测试60兆文本,174毫秒
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/18 20:54:08
45楼: 楼主试试把
 t1:=HPCounter1.ReadInt;  //计时开始
放在
Editor.Text:=Q_Replace(S,f,r);    //大神用汇编写的替换函数
前面呢?
考察StrReplace的执行时间,最好把计时器的起止紧贴StrReplace函数,否则容易引入额外的干扰因素
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 20:55:52
47楼: 替换后的文件是正确的
此帖子包含附件:
PNG 图像
大小:68.7K
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 21:02:23
48楼: 看了楼主代码,主要问题是分不清替换和可视化控件赋值显示耗时的问题,计算机基本功的问题
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2022/1/18 21:09:51
49楼: 楼上正解,要看效率就要将有可能影响效率的其它东西都尽可能排除,你将它与控件搅在一起,问题复杂了,是搞不清楚的.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 21:10:16
49楼: to hq200306:要在文本编辑器里面测试才行,比如Richedit里面
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 21:12:53
50楼: to kentty:我这是正常替换程序,实际影响页几乎为0,作为用户,时间是从点下替换按钮开始计算的,替换完毕到显示出来这才是完整的替换过程。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 21:20:47
51楼: to hardnut:因为其它代码都完全一样,只改变了替换函数,带来的时间差就是函数不同带来的时间差,也就是效率的差距,这没啥疑问的。我是从正常程序里才知道Delphi7自带的StringReplace效率比较低,尤其是大文件,文件越大效率越低,大文件时比起大神那个汇编替换函数效率差数百倍,这是经过实践检验的。
前几天装了Delphi11后想把之前D7写的程序重新编译一下,才发现D7下的大神汇编替换函数不能用了,于是引发了主贴的问题。经过多次测试,发现D11自带的StringReplace函数比起D7的StringReplace函数效率提高了非常多,已经算可用了,虽然仍然不及大神汇编的那个替换函数。
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/18 21:24:16
50楼: 你的问题是RichEdit1跑不动,不是StringReplace不行
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/18 21:34:43
52楼: to hq200306:你那段代码,我笔记本上只要74.5毫秒,但这不能说明问题啊
此帖子包含附件:
JPEG 图像
大小:19.4K
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/18 21:41:28
53楼: to 50楼: 你现在怀疑的是D11的StringReplace效率差,那就先测StringReplace的执行时间
万一是D11执行 
S:= Editor.Text;          //文本编辑器
的效率低呢? 那就是另一个话题了

找到问题点,才能知道代码优化的方向
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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的文件也只要几秒钟。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 0:10:39
56楼: 不同的替换函数替换时Editor.Text:=tmp有区别吗?没任何区别好吧!
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/19 8:03:58
57楼: 前面好几个人已经验证了D11的StringReplace效率并不差, 看你的测试代码中,在计时阶段调用了TRichEdit.GetText和TRichEdit.SetText,
万一是这两个在D7和D11下的实现效率有差别呢?
D11为了unicode,跨平台,在上面两个函数实现中塞入了太多的东西,也是很有肯能的

楼主可以分别验证一下TRichEdit.GetText, StringReplace, TRichEdit.SetText三个函数在D7和D11下用时
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 11:30:51
59楼: to wr960204:是你根本没搞清楚什么原委。
只反问你,你说慢是RichEdit导致的,为什么大神汇编的Q_Replace极其高效?没有用RichEdit?完全相同的代码,就替换函数换了效率提高数百倍,不是函数本身的原因你告诉我啥原因?
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 11:34:29
60楼: to kentty:前面讲过,经过验证,D11的StringReplace效率比D7的StringReplace确实高很多,虽然仍然比不上大神汇编的Q_Replace高效。
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/19 11:42:34
61楼: 楼主给我的感觉入错行
----------------------------------------------
-
作者:
男 fdltc (fdltc) ★☆☆☆☆ -
普通会员
2022/1/19 11:55:28
60楼: 武稀松是正解,两个版本的RE内部实现完全不同。

楼主水平还只是停留在拖控件、抄代码阶段,好好努力吧
----------------------------------------------
-
作者:
男 inbreak (入侵) ★☆☆☆☆ -
盒子活跃会员
2022/1/19 12:27:50
62楼: to 59楼

你连58楼说的东西都没有看懂吧。看懂就不会这么说了。
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 12:32:32
63楼: to wr960204:咋就那么喜欢抬杠?这是D7下的对比,代码除了替换函数不同其它完全相同,也没有用Richedit,纯效率差距,你看看差距多少倍?3522倍!
此帖子包含附件:
JPEG 图像
大小:365.0K
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 12:36:21
64楼: to nbreak:不是我没看懂,是你们几个人老在乱扯,非要扯什么Richedit,本身和Richedit没什么关系,UI降低了效率都降低了,又不是单单降低了StringReplace,都一样,带来的差距就是函数的差距!
你们非要扯Richedit,好,那都不要UI,纯函数替换,看看,StringReplace效率低不低?低3522倍,比UI下低600倍严重多了!你还有什么可扯的?
此帖子包含附件:
JPEG 图像
大小:365.0K
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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动态滚动不平滑,但程序执行实际是很平滑的,录制帧率限制的原因)
此帖子包含附件:
GIF 图像
大小:2.01M
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 14:04:58
66楼: 我知道有些人瞧不上我这“业余”的水平,但我这业余的写的东西,笑话我的也不一定比我做的更好和效率比我高。
比如我的程序“智能分段”功能,效果和效率都比WPS的“段落重排”要好,比如顶部的段落,WPS整理后全乱了,我的保持了原来正确的格式。
笑话我的,做一个更优秀的出来大家看看呗!
此帖子包含附件:
JPEG 图像
大小:2.03M
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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即可,问题不大了。
按此在新窗口浏览图片
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 18:31:16
70楼: to wr960204:晚点我再测试一下D11下StringReplace的效率,这两天相同的代码表现不稳定,被我前面称为“灵异现象”,还不知道原因。就如下面这个截图,当时就是D11下用StringReplace做的测试,很慢,但现在发现D11的StringReplace很快,就好像经过运行多次相同的代码后有“优化”似的……
之前68楼的图贴错了,重贴:
按此在新窗口浏览图片
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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后提升的更厉害,效率高低是相对的!
说了半天,逻辑不对的是你们,不是我。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/1/19 20:30:35
72楼: 好吧楼主你赢了。
我们不对。

我测试的D7原版replace60多MB:
替换用时1.1秒左右。
显示用时3.3秒左右。

肯定是假的。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 21:15:58
73楼: 你D7下用StringReplace来替换60MB的那个文件替换用时1.1秒根本就不可能,肯定假的。如果有这效率,我还会说它低效吗?
要不你把你的源代码放上来,大家看看?
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 21:35:54
74楼: to wr960204:单独又试了一下,现在D11下的StringReplace确实比D7下的Q_Replace还快点,没想到D11下的StringReplace比D7下的完全是脱胎换骨的提升!了不起!
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/19 21:49:26
75楼: 楼主,你用错误的测试方法得出了一个错误的结论,赶紧认个错回去优化你的代码吧
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 22:35:41
77楼: to kentty:并没有。一开始我用D11的StringReplace就是很慢,就是这个图中的下面那副图的结果(477KB的文件替换),很慢,这是事实,不是我瞎编的,所以才会主贴中那么说。否则怎么可能呢?我也不知道为什么出现这种状况。
按此在新窗口浏览图片
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/19 22:40:06
78楼: to wr960204:我就是一业余的菜鸟,就根据POS函数鼓捣了一下而已,没技术含量,和D7的StringReplace也没得比。
但就是如此,在当时测试这个自定义的替换函数时却没有比StringReplace慢很多,我还列出了具体毫秒数,但现在用这个自定义的函数比D7自带的StringReplace也慢得多,包括当时D11下的StringReplace也很慢。真不知道当时是啥情况,为啥出现这种“灵异现象”?
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/1/19 23:04:48
79楼: 看了上面些贴子,好佩服武稀松,真的做到诲人不倦,难能可贵。
----------------------------------------------
-
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2022/1/20 1:12:26
80楼: 楼主浪费大家的时间与我无关
但是楼主引出了武大关于新版StringReplace已经变快的结论
嗯,我还得感谢一下楼主
----------------------------------------------
-
作者:
男 parhelia (-_-) ★☆☆☆☆ -
普通会员
2022/1/20 5:35:18
81楼: 这个问题是由TRichEdit字体的字符集设置错误引起的,可以重现,不是“灵异现象”。
字体为简中字体,如宋体、微软雅黑时一切正常;字体为非简中字体,如Ariel、Segoe UI时显示速度奇慢。
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2022/1/20 8:52:11
82楼: 稍稍问下楼主,码龄几年?大约写过多少行代码?
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 vga (vga) ★☆☆☆☆ -
盒子活跃会员
2022/1/20 11:40:14
83楼: "Talk is cheap, show me the code!  "  ^_^
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/1/20 11:40:19
83楼: 不管是编程,还是干别的什么事情,查问题的时候,尽量把不相关的东西分开,一个一个查,而不是搅合到一起去查。这个是做事情的基本思路。但是,我发现,很多人不具备这种简单的思路。

如果中学物理学得好,这种思路应该是初中就会培养出来的。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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;

也是年末闲得……顺便祝大家虎年大吉:)
此帖子包含附件:
PNG 图像
大小:91.7K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ygm_mm ( ) ★☆☆☆☆ -
盒子活跃会员
2022/1/20 17:16:58
85楼:  parhelia分析的有道理。 pcplayer说的有道理。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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倍多,怎么可能?看我的截图。
此帖子包含附件:
JPEG 图像
大小:1.14M
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/21 0:51:01
87楼: to hardnut:码龄几年不重要,写过多少行代码也不重要,我又不是程序员,也不靠编程吃饭。
to pcplayer:只能说,你还没.理.解问题的本.质到底在哪里。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/21 1:16:06
88楼: to parhelia:试了一下,果然如此,同一个文件,用微软雅黑字体时替换只要几百毫秒,用Segoe UI字体则要30多秒,真的重现了!我说怎么回事,真可能是当时无意中字体变化了没注意。十分感谢!
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/1/21 16:21:51
89楼: 字体和字符串替换有啥关系?完全就是两码事,非要扯到一起来查,当然查不出来。

一个人又吃了耗子药,又打了篮球。非要说打篮球会致命。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/21 20:54:10
90楼: to pcplayer:相同条件下自然可以相提并论!
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/1/21 21:20:50
92楼: 顺便多说一句:既然分步骤太多,不如打个日志,省的弹窗了。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/21 21:41:32
93楼: to ddrfan:问题是,我用的就是你的代码,没改动。我的硬件比你的强,同样的Delphi 7,速度反而低6~9倍,不科学吧。系统是WIN11,不说效率高不会比WIN10低多少吧?字体是微软雅黑,你啥字体?低6~9倍不科学。
再说了,你这个测试证明不了你的观点,证明的是我的观点:D7的StringReplace函数效率低,大文件效率则极低,你是在规避而已。
此帖子包含附件:
JPEG 图像
大小:221.5K
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/21 22:09:08
94楼: 没想到这个话题还没结束 :)

to 楼主, 2+3<1+5大家都同意,但是推理出来2<1就不是所有人都认同了。 如果你知道我在说什么,就不要回复了

上面好几个帖子都在告诉你你的方法不对,包括你不赞同的pcplayer,简直是高屋建瓴,并且告诉你了“相对更加正确”的方法,你一直在纠缠你测试来的结果就是这样。测试结果是没错,但是结论错了

遁了~~~
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2022/1/21 22:36:35
95楼: 大家不要说了, 人家不靠这个吃饭,  人家开心就好, 我们这些老coder又何必惹人家不开心呢? 我希望我这个回复是这个帖子的最后一个回复.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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.本来问题已经解决,事实也很清楚了。但是部分网友还在纠结我所谓衡量效率的方式不对,其实是他自己不对,他忘了前提,说了正确的废话而已。他们这个所谓“相对更加正确的方法”根本不是本人不会,是本人认为没有必要,因为该问题本身已经可以证明了主贴中的问题!只是有些人领会不到什么叫前提,什么叫整体。就好比,房间黑暗拉开窗帘光照射到房间小明眼睛就疼,我得出结论认为是光刺激了小明眼睛导致眼睛疼。这些网友认为,应该将小明送到医院,逐一检查眼睛疼的具体原因,要排除一切干扰:比如,去拉窗帘导致空气流动有风,会有影响,窗帘拉开后形态变化,对其眼睛也可能会有影响,窗帘拉动导致灰尘扩散、细菌传播……不得不说,这都可能是“正确的”废话!我不爱听废话,更不爱那些抓不住问题重点和本质的人,这些人大多没什么统筹力、领导力,实际解决问题的能力也不会很强。
----------------------------------------------
-
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2022/1/22 1:57:21
97楼: StringReplace效率大幅提高是最近几年的一个官方改进,是有官方宣布的,李维都专门讲过这个问题,你们都不知道吗?算是最近几个版本的小小亮点之一。
----------------------------------------------
只有偏执狂才能生存!
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/22 16:52:05
98楼: to nevergrief (孤独骑士):还真不知道这事。李维不是早就去微软了吗,怎么还专门讲StringReplace效率大幅提高这事啊?
----------------------------------------------
-
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
普通会员
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;
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
2022/1/22 20:41:59
100楼: to bluestorm8:嗯,后来的那么多回复估计你都没看,已经确认后来新版Delphi已经大幅提高了StringReplace的效率,具体从哪个版本提高的不太清楚。
----------------------------------------------
-
作者:
男 pkwoinsert (啊舒服) ★☆☆☆☆ -
普通会员
2022/1/29 23:50:06
101楼: 原因:
虽然用了AnsiString实现了功能,但Delphi11的界面控件是Unicode的,所以从界面里读数据要经过一次转换,写回界面又经过一次转换。

建议:
1、直接改汇编代码使其支持Unicode
2、不要在界面里直接替换数据,替换好了再加载。
3、超大的数据也不要在界面里一次加载,就算加载了也没有屏幕能显示下,影响效率。
----------------------------------------------
-
作者:
男 wufan314 (真的吗) ★☆☆☆☆ -
普通会员
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);
----------------------------------------------
-
作者:
男 wiseinfo (wisienfo) ★☆☆☆☆ -
普通会员
2022/2/7 8:54:45
103楼: StringReplace在D11比D7肯定要快很多。
----------------------------------------------
-
作者:
男 earthsbest (全能中间件) ▲▲▲▲△ -
普通会员
2022/2/9 9:59:58
104楼: StringReplace 里面用到move,pos等几个函数,从Delphi2005开始就使用了fastcode提供的版本,后续的新版集成了很多fastcode的函数,和fastmm内存管理器的加持,我也觉得新版本的性能更好。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 flyhorsefj (pegasus) ★☆☆☆☆ -
普通会员
2022/2/16 17:20:09
105楼: D7 编译器的环境不一样,结果也不一样
    FastMM      
    MidasSpeedFix
    VCLFixPack
    DelphiSpeedUp  
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行347.6563毫秒 RSS