我需要一个最快的哈希函数,在Delphi 2009中,它可以从Unicode字符串创建哈希值,并且能够在桶中分布得相对均匀。
我最初使用了GpStringHash中Gabr的HashOf函数。
但我发现这不能从Unicode字符串中产生好的数字。我注意到Gabr的例程没有更新到Delphi 2009。
然后我在Delphi 2009的SysUtils中发现了HashNameMBCS,并将其翻译为以下简单的函数(其中“string”是Delphi 2009 Unicode字符串):
这段代码似乎比Gabr的代码包含更多的汇编代码。
时间很重要。我是否可以做些什么来改进我编写的Pascal代码或者生成的汇编代码?
我最初使用了GpStringHash中Gabr的HashOf函数。
function HashOf(const key: string): cardinal;
asm
xor edx,edx { result := 0 }
and eax,eax { test if 0 }
jz @End { skip if nil }
mov ecx,[eax-4] { ecx := string length }
jecxz @End { skip if length = 0 }
@loop: { repeat }
rol edx,2 { edx := (edx shl 2) or (edx shr 30)... }
xor dl,[eax] { ... xor Ord(key[eax]) }
inc eax { inc(eax) }
loop @loop { until ecx = 0 }
@End:
mov eax,edx { result := eax }
end; { HashOf }
但我发现这不能从Unicode字符串中产生好的数字。我注意到Gabr的例程没有更新到Delphi 2009。
然后我在Delphi 2009的SysUtils中发现了HashNameMBCS,并将其翻译为以下简单的函数(其中“string”是Delphi 2009 Unicode字符串):
function HashOf(const key: string): cardinal;
var
I: integer;
begin
Result := 0;
for I := 1 to length(key) do
begin
Result := (Result shl 5) or (Result shr 27);
Result := Result xor Cardinal(key[I]);
end;
end; { HashOf }
我认为这很不错,直到我查看CPU窗口并看到它生成的汇编代码:
Process.pas.1649: Result := 0;
0048DEA8 33DB xor ebx,ebx
Process.pas.1650: for I := 1 to length(key) do begin
0048DEAA 8BC6 mov eax,esi
0048DEAC E89734F7FF call $00401348
0048DEB1 85C0 test eax,eax
0048DEB3 7E1C jle $0048ded1
0048DEB5 BA01000000 mov edx,$00000001
Process.pas.1651: Result := (Result shl 5) or (Result shr 27);
0048DEBA 8BCB mov ecx,ebx
0048DEBC C1E105 shl ecx,$05
0048DEBF C1EB1B shr ebx,$1b
0048DEC2 0BCB or ecx,ebx
0048DEC4 8BD9 mov ebx,ecx
Process.pas.1652: Result := Result xor Cardinal(key[I]);
0048DEC6 0FB74C56FE movzx ecx,[esi+edx*2-$02]
0048DECB 33D9 xor ebx,ecx
Process.pas.1653: end;
0048DECD 42 inc edx
Process.pas.1650: for I := 1 to length(key) do begin
0048DECE 48 dec eax
0048DECF 75E9 jnz $0048deba
Process.pas.1654: end; { HashOf }
0048DED1 8BC3 mov eax,ebx
这段代码似乎比Gabr的代码包含更多的汇编代码。
时间很重要。我是否可以做些什么来改进我编写的Pascal代码或者生成的汇编代码?
跟进。
最终我选择了基于SysUtils.HashNameMBCS的HashOf函数。它似乎为Unicode字符串提供了良好的哈希分布,并且速度相当快。
是的,生成了很多汇编代码,但是生成它的Delphi代码非常简单,只使用位移操作,所以很难相信它不会很快。