Tôi đang cần hàm băm nhanh nhất có thể trong Delphi 2009 sẽ tạo ra các giá trị băm từ một chuỗi Unicode sẽ phân phối khá ngẫu nhiên vào các thùng.Chức năng băm Unicode hiệu quả nhất cho Delphi 2009
tôi bắt đầu với HashOf chức năng Gabr 's từ GpStringHash:
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 }
Nhưng tôi thấy rằng điều này đã không tạo ra số tốt từ chuỗi Unicode. Tôi lưu ý rằng thói quen Gabr của chưa được cập nhật để Delphi 2009.
Sau đó, tôi phát hiện ra HashNameMBCS trong SysUtils của Delphi 2009 và dịch nó với chức năng đơn giản này (nơi "chuỗi" là một Delphi 2009 Unicode string):
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 }
tôi nghĩ đây là khá tốt cho đến khi tôi nhìn vào cửa sổ CPU và thấy mã lắp ráp nó tạo ra:
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
Điều này dường như chứa khá nhiều mã lắp ráp nhiều hơn so với mã Gabr của.
Tốc độ là bản chất. Có bất cứ điều gì tôi có thể làm để cải thiện hoặc mã pascal tôi đã viết hoặc lắp ráp mã của tôi tạo ra?
Theo dõi.
Cuối cùng tôi đã đi với hàm HashOf dựa trên SysUtils.HashNameMBCS. Nó dường như cung cấp cho một phân phối băm tốt cho chuỗi Unicode, và dường như khá nhanh.
Có, có rất nhiều mã trình tạo ra, nhưng mã Delphi tạo ra nó rất đơn giản và chỉ sử dụng thao tác bit-shift, vì vậy thật khó để tin rằng nó sẽ không nhanh.
Trong HashOf cuối cùng của bạn, tôi nên đi từ 1 đến Độ dài (khóa). – gabr
@gabr: Cảm ơn. Tôi bây giờ thấy tôi đã viết "followup" thậm chí không nhận ra rằng tôi đã kết thúc bằng cách sử dụng cùng một chức năng câu hỏi của tôi là về, ngoại trừ tôi đã thực hiện các sai lầm trong followup của tôi. Tôi sẽ viết lại điều đó. – lkessler