lke*_*ler 15 delphi unicode stringbuilder delphi-2009
一年前我将程序从Delphi 4转换为Delphi 2009,主要是为了跳转到Unicode,同时也获得了Delphi多年来改进的好处.
我的代码当然是所有遗留代码.它使用短字符串,现在已经很方便地变成了长Unicode字符串,并且我已经将所有旧的ANSI函数更改为新的等效函数.
但是在Delphi 2009中,他们引入了TStringBuilder类,可能是在StringBuilder类.NET之后建模的.
我的程序执行了大量的字符串处理和操作,并且可以同时将数百兆字节的大字符串加载到内存中.
我不太了解Delphi的TStringBuilder实现,但我听说它的一些操作比使用默认字符串操作更快.
我的问题是我是否值得通过努力并将我的标准字符串转换为使用TStringBuilder类.这样做我会得到什么和失去什么?
感谢您的回答并引导我得出结论,除非需要.NET兼容性,否则不要打扰.
在他关于Delphi 2009 String Performance的博客中,Jolyon Smith说:
但它看起来好像TStringBuilder主要作为.NET兼容性工具,而不是为Win32应用程序的开发人员提供任何真正的好处,可能除了希望或需要单一来源Win32/.NET代码库的开发人员字符串处理性能不是一个问题.
Lac*_*anG 13
据我所知,TStringBuilder只是为了与.NET和Java的一些奇偶校验而引入,它似乎更像是一个盒子类型功能而不是任何重大进步.
共识似乎是TStringBuilder在某些操作中更快,但在其他操作中更慢.
你的程序在TStringBuilder比较之前/之后听起来像一个有趣的程序,但除了作为学术练习之外我不会这样做.
Jer*_*ers 11
基本上,我使用这些习语来构建字符串.最重要的区别是:
对于复杂的构建模式,第一个使我的代码更清晰,第二个只有我添加行并且通常包括许多Format调用.
当格式模式很重要时,第三个使代码更清晰.
我只在表达式非常简单时才使用最后一个.
前两个成语之间的一些差异:
TStringBuilder有许多重载Append,如果你想添加像can 这样的行,也有AppendLine(只有两个重载)TStringList.AddTStringBuilder 使用超容量方案重新分配底层缓冲区,这意味着使用大缓冲区和频繁附加,它可能比 TStringListTStringBuilder内容,您必须调用ToString方法,这可能会减慢速度.所以:速度不是选择你的字符串附加成语最重要的事情.可读代码是.
我试图改进一个解析文本文件(1.5GB)的旧例程.例程非常愚蠢,它正在构建一个这样的字符串:Result:= Result+ buff[i];
所以我认为TStringBuilder会显着提高速度.事实证明,'dumb'代码实际上比使用TStringBuilder的'改进'版本快114%.
因此,从字符构建字符串不是一个可以通过TStringBuilder获得速度提升的地方.
我的StringBuilder(下面)比经典的s:= s + chr快184.82倍(是184 !!!!!!).(4MB字符串的实验)
经典s:= s + c
时间:8502毫秒
procedure TfrmTester.btnClassicClick(Sender: TObject);
VAR
s: string;
FileBody: string;
c: Cardinal;
i: Integer;
begin
FileBody:= ReadFile(File4MB);
c:= GetTickCount;
for i:= 1 to Length(FileBody) DO
s:= s+ FileBody[i];
Log.Lines.Add('Time: '+ IntToStr(GetTickCount-c) + 'ms'); // 8502 ms
end;
Run Code Online (Sandbox Code Playgroud)
Prebuffered
时间:
BUFFSIZE = 10000; // 10k buffer = 406ms BuffSize = 100000; // 100k buffer = 140ms BuffSize = 1000000; // 1M缓冲区= 46ms
代码:
procedure TfrmTester.btnBufferedClick(Sender:TObject); VAR s:string; FileBody:string; c:红衣主教; CurBuffLen,marker,i:整数; 开始FileBody:= ReadFile(File4MB); c:= GetTickCount;
Time:
BuffSize= 10000; // 10k buffer = 406ms
BuffSize= 100000; // 100k buffer = 140ms
BuffSize= 1000000; // 1M buffer = 46ms
Run Code Online (Sandbox Code Playgroud)
预补充,如类
Time:
BuffSize = 10000; // 10k buffer = 437ms
BuffSize = 100000; // 100k buffer = 187ms
BuffSize = 1000000; // 1M缓冲区= 78ms
代码:
procedure TfrmTester.btnBuffClassClick(Sender:TObject); VAR StringBuff:TCStringBuff; s:字符串; FileBody:string; c:红衣主教; 我:整数; 开始FileBody:= ReadFile(File4MB); c:= GetTickCount;
procedure TfrmTester.btnBufferedClick(Sender: TObject);
VAR
s: string;
FileBody: string;
c: Cardinal;
CurBuffLen, marker, i: Integer;
begin
FileBody:= ReadFile(File4MB);
c:= GetTickCount;
marker:= 1;
CurBuffLen:= 0;
for i:= 1 to Length(FileBody) DO
begin
if i > CurBuffLen then
begin
SetLength(s, CurBuffLen+ BuffSize);
CurBuffLen:= Length(s)
end;
s[marker]:= FileBody[i];
Inc(marker);
end;
SetLength(s, marker-1); { Cut down the prealocated buffer that we haven't used }
Log.Lines.Add('Time: '+ IntToStr(GetTickCount-c) + 'ms');
if s <> FileBody
then Log.Lines.Add('FAILED!');
end;
Run Code Online (Sandbox Code Playgroud)
这是班级:
Time:
BuffSize= 10000; // 10k buffer = 437ms
BuffSize= 100000; // 100k buffer = 187ms
BuffSize= 1000000; // 1M buffer = 78ms
Run Code Online (Sandbox Code Playgroud)
结论:如果您有大(超过10K)字符串,请停止使用s:= s + c.即使你有小字符串也可能是这样,但你经常这样做(例如,你有一个函数在一个小字符串上做一些字符串处理,但你经常调用它)._
PS:你可能也想看到这个:https://www.delphitools.info/2013/10/30/efficient-string-building-in-delphi/2/
TStringBuilder的引入仅仅是为了在Delphi和Delphi.NET中执行字符串处理的应用程序提供源代码兼容机制.您在Delphi中牺牲了一些速度,以获得Delphi.NET中一些潜在的显着优势
.NET中的StringBuilder概念解决了该平台上字符串实现的性能问题,这是Delphi(本机代码)平台根本没有的问题.
如果您没有编写需要为本机代码和Delphi.NET编译的代码,那么就没有理由使用TStringBuilder.
根据Marco Cantu的说法,不是为了提高速度,但是你可能会获得更清晰的代码以及与.Net更好的代码兼容性.这里(以及这里的一些更正)使用TStringBuilder的另一个速度测试不是更快.
TStringBuilder基本上只是一个me-too功能,就像LachlanG所说的那样.它在.NET中是必需的,因为CLR字符串是不可变的,但是Delphi没有那个问题所以它并不需要字符串构建器作为变通方法.
| 归档时间: |
|
| 查看次数: |
5803 次 |
| 最近记录: |