tim*_*m93 0 delphi string performance substring delphi-xe2
我有一些函数来计算由空格分隔的字符串中的子字符串:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses System.SysUtils,windows;
//s=string to search in
//t=string to search for
//cs=delimiters
function f0(const s,t:string;const cs:tsyscharset):integer;
var
p,q:pchar;
u:string;
begin
result:=0;
p:=pointer(s);
if p<>nil then
while p^<>#0 do
begin
while (p^<>#0) and charinset(p^,cs) do inc(p);
q:=p;
while (p^<>#0) and not charinset(p^,cs) do inc(p);
if p>q then
begin
setstring(u,q,p-q);
//writeln('[',u,']');
if u=t then inc(result);
end;
end;
end;
function f1(const s,t:string;const cs:tsyscharset):integer;
var
i,j,l:integer;
u:string;
begin
result:=0;
l:=length(s);
i:=1;
while i<=l do
begin
while (i<=l) and charinset(s[i],cs) do inc(i);
j:=i;
while (i<=l) and not charinset(s[i],cs) do inc(i);
if i>j then
begin
u:=copy(s,j,i-j);
//writeln('[',u,']');
if u=t then inc(result);
end;
end;
end;
function f2(const s,t:string;const cs:tsyscharset):integer;
var
i,j,l:integer;
u:string;
begin
result:=0;
l:=length(s);
i:=1;
while i<=l do
begin
while (i<=l) and charinset(s[i],cs) do inc(i);
j:=i;
while (i<=l) and not charinset(s[i],cs) do inc(i);
if i>j then
begin
setlength(u,i-j);
move(s[j],pointer(u)^,(i-j)*2);
//writeln('[',u,']');
if u=t then inc(result);
end;
end;
end;
type
tfunc=function(const s,t:string;const cs:tsyscharset):integer;
const
s=' de foo de'+#13+' baz blah de de blah'+#10+' asd de qwe rtz un f'+#9+' t de ds w de ';
t='de';
cs=[' ',#13,#10,#9];//CR,LF,TAB
n=5000000;
procedure time(i:integer;f:tfunc);
var
j,k:integer;
start,finish,freq:int64;
begin
QueryPerformanceCounter(start);
for j := 1 to n do k:=f(s,t,cs);
QueryPerformanceCounter(finish);
QueryPerformanceFrequency(freq);
Writeln(Format('f%u:%u:%.3fs',[i,k,(finish-start)/freq]));
end;
const
funcs:array[0..2] of tfunc=(f0,f1,f2);
var
i:integer;
begin
setpriorityclass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
for i := low(funcs) to high(funcs) do time(i,funcs[i]);
readln
end.
Run Code Online (Sandbox Code Playgroud)
速度结果是
f0:7:7,624s
f1:7:8,066s
f2:7:6,454s
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是:为什么f2比f0快?
我的第二个问题是:你是否知道如何更好地优化它(没有内联汇编程序)?
IDE:Delphi XE2(Unicode)
为什么它更快?没有探查器就无法猜测.它取决于您运行的CPU.
我想更快将被处理f2
因为SetLength()
将避免在大多数时间重新分配,而SetString()
在分配它之前将始终释放内存.这取决于你的情况.
对于更快的过程,使用相同的算法(您可能会发现更优化的东西),我会尝试:
const
cs = [32,13,10,9];
function f2(const s,t:string):integer;
var
i,j,l:integer;
begin
result := 0;
l := length(s);
i := 1;
while i<=l do
begin
while (i<=l) and (ord(s[i]) in cs) do inc(i);
j:=i;
while (i<=l) and not(ord(s[i]) in cs) do inc(i);
if (i>j) and CompareMem(pointer(s[j]),pointer(t),(i-j)*sizeof(char)) then
inc(result);
end;
end;
Run Code Online (Sandbox Code Playgroud)
那是:
CompareMem
- 这里仍有改进的余地.你可以尝试写:
const
cs: set of 0..32 = [32,13,10,9];
Run Code Online (Sandbox Code Playgroud)
这可能会快一点,因为生成的ASM代码将是一个快速的位寻指令,而第一个版本将使用比较列表.但我认为这不会产生很大的影响.
在所有情况下,我想你应该更好:
归档时间: |
|
查看次数: |
805 次 |
最近记录: |