问题描述
是否有任何代码用于 64 位的 Pos() 版本比当前的 32 位快?
Is there any code for a Pos() version that's as fast in 64-bit than the current 32-bit?
据我所知,Delphi 中的 32 位版本(测试到 XE5)在很多年前就采用了 FastCode 汇编器版本,但对于 64 位,它使用 PurePascal 版本,速度大约慢 5 到 10 倍.
To my understanding, the 32-bit version in Delphi (tested up to XE5) adopted the FastCode assembler versions many years ago, but for 64-bit it uses a PurePascal version, which is around 5 to 10 times slower.
一些测试,长循环中的相同过程:
Some tests, same procedure in a long loop:
32 位:65..90 毫秒
32-bit: 65..90ms
64 位:280..300 毫秒
64-bit: 280..300ms
推荐答案
使用 Fastcoders
purepascal PosEx_Sha_Pas_2
算法(修改为适合 x64):
Using Fastcoders
purepascal PosEx_Sha_Pas_2
algorithm (modified to fit x64):
function PosEx_Sha_Pas_2(const SubStr, S: string; Offset: Integer = 1): Integer;
Type
PInteger =^Integer;
var
len, lenSub: Integer;
ch: char;
p, pSub, pStart, pStop: pchar;
label
Loop0, Loop4,
TestT, Test0, Test1, Test2, Test3, Test4,
AfterTestT, AfterTest0,
Ret, Exit;
begin;
pSub := pointer(SubStr);
p := pointer(S);
if (p = nil) or (pSub = nil) or (Offset < 1) then
begin;
Result := 0;
goto Exit;
end;
lenSub := PLongInt(PByte(pSub) - 4)^ - 1; // <- Modified
len := PLongInt(PByte(p) - 4)^; // <- Modified
if (len < lenSub + Offset) or (lenSub < 0) then
begin;
Result := 0;
goto Exit;
end;
pStop := p + len;
p := p + lenSub;
pSub := pSub + lenSub;
pStart := p;
p := p + Offset + 3;
ch := pSub[0];
lenSub := -lenSub;
if p < pStop then
goto Loop4;
p := p - 4;
goto Loop0;
Loop4:
if ch = p[-4] then
goto Test4;
if ch = p[-3] then
goto Test3;
if ch = p[-2] then
goto Test2;
if ch = p[-1] then
goto Test1;
Loop0:
if ch = p[0] then
goto Test0;
AfterTest0:
if ch = p[1] then
goto TestT;
AfterTestT:
p := p + 6;
if p < pStop then
goto Loop4;
p := p - 4;
if p < pStop then
goto Loop0;
Result := 0;
goto Exit;
Test3:
p := p - 2;
Test1:
p := p - 2;
TestT:
len := lenSub;
if lenSub <> 0 then
repeat
;
if (pSub[len] <> p[len + 1]) or (pSub[len + 1] <> p[len + 2]) then
goto AfterTestT;
len := len + 2;
until len >= 0;
p := p + 2;
if p <= pStop then
goto Ret;
Result := 0;
goto Exit;
Test4:
p := p - 2;
Test2:
p := p - 2;
Test0:
len := lenSub;
if lenSub <> 0 then
repeat
;
if (pSub[len] <> p[len]) or (pSub[len + 1] <> p[len + 1]) then
goto AfterTest0;
len := len + 2;
until len >= 0;
Inc(p);
Ret:
Result := p - pStart;
Exit:
end;
以及使用 David 的测试用例(x64 版本)的结果:
And the result using David's test case (x64 release):
System.Pos 18427
wcsstr 8122
PosEx_Sha_Pas_2 2282
对于 x32 版本,结果是:
For the x32 release the results are:
System.Pos 2171
wcsstr 9634
PosEx_Sha_Pas_2 1868
结论:
PosEx_Sha_Pas_2
在 x64 位模式下的速度几乎与在 x32 位模式下的 Pos
一样快.此外,在 x32 位模式下,PosEx_Sha_Pas_2
似乎比 Pos
更快.
PosEx_Sha_Pas_2
is almost as fast in x64 bit mode as Pos
in x32 bit mode.Additionally it seems as PosEx_Sha_Pas_2
is faster than Pos
in x32 bit mode.
此处的所有测试均使用 XE4 版本.
All tests here is with the XE4 version.
更新:
从 Delphi 11.0 Alexandria 开始,Pos()
的 purepascal 版本使用 Fastcoders PosEx_Sha_Pas_2.pas
版本.感谢 @StefanGlienke 为实现这一目标所做的努力!
As of Delphi 11.0 Alexandria, the purepascal version of Pos()
is using the Fastcoders PosEx_Sha_Pas_2.pas
version. Thanks @StefanGlienke for your effort in making this happen!
这篇关于Delphi:64 位快速 Pos的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!