Murmurhash 哈希算法
Murmurhash 哈希算法
MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。 由Austin Appleby在2008年发明, 并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。
Redis在实现字典时用到了两种不同的哈希算法,MurmurHash便是其中一种(另一种是djb),在Redis中应用十分广泛,包括数据库、集群、哈希键、阻塞操作等功能都用到了这个算法。发明算法的作者被邀到google工作,该算法最新版本是MurmurHash3,基于MurmurHash2改进了一些小瑕疵,使得速度更快,实现了32位(低延时)、128位HashKey,尤其对大块的数据,具有较高的平衡性与低碰撞率。
unit Grijjy.Hash;
{$INCLUDE 'Grijjy.inc'}
{$OVERFLOWCHECKS OFF} // required since overflow checks will fail (code works ok w/o checking on)
interface
type
{ Incremental Murmur-2 hash.
See https://sites.google.com/site/murmurhash/
Uses the CMurmurHash2A variant, which can be used incrementally.
The results are *not* the same as for goMurmurHash2 in Grijjy.SysUtils }
TgoHashMurmur2 = record
{$REGION 'Internal Declarations'}
private const
M = $5bd1e995;
R = 24;
private
FHash: Cardinal;
FTail: Cardinal;
FCount: Cardinal;
FSize: Cardinal;
private
class procedure Mix(var H, K: Cardinal); static; inline;
private
procedure MixTail(var AData: PByte; var ALength: Integer);
{$ENDREGION 'Internal Declarations'}
public
{ Starts a new hash.
Parameters:
ASeed: (optional) seed value for the hash.
This is identical to calling Reset. }
class function Create(const ASeed: Integer = 0): TgoHashMurmur2; static; inline;
{ Restarts the hash
Parameters:
ASeed: (optional) seed value for the hash.
This is identical to using Create. }
procedure Reset(const ASeed: Integer = 0); inline;
{ Updates the hash with new data.
Parameters:
AData: the data to hash
ALength: the size of the data in bytes. }
procedure Update(const AData; ALength: Integer);
{ Finishes the hash and returns the hash code.
Returns:
The hash code }
function Finish: Cardinal;
end;
implementation
{ TgoHashMurmur2 }
class function TgoHashMurmur2.Create(const ASeed: Integer): TgoHashMurmur2;
begin
Result.Reset(ASeed);
end;
function TgoHashMurmur2.Finish: Cardinal;
begin
Mix(FHash, FTail);
Mix(FHash, FSize);
FHash := FHash xor (FHash shr 13);
FHash := FHash * M;
FHash := FHash xor (FHash shr 15);
Result := FHash;
end;
class procedure TgoHashMurmur2.Mix(var H, K: Cardinal);
begin
K := K * M;
K := K xor (K shr R);
K := K * M;
H := H * M;
H := H xor K;
end;
procedure TgoHashMurmur2.MixTail(var AData: PByte; var ALength: Integer);
begin
while (ALength <> 0) and ((ALength < 4) or (FCount <> 0)) do
begin
FTail := FTail or (AData^ shl (FCount * 8));
Inc(AData);
Inc(FCount);
Dec(ALength);
if (FCount = 4) then
begin
Mix(FHash, FTail);
FTail := 0;
FCount := 0;
end;
end;
end;
procedure TgoHashMurmur2.Reset(const ASeed: Integer);
begin
FHash := ASeed;
FTail := 0;
FCount := 0;
FSize := 0;
end;
procedure TgoHashMurmur2.Update(const AData; ALength: Integer);
var
Data: PByte;
K: Cardinal;
begin
Inc(FSize, ALength);
Data := @AData;
MixTail(Data, ALength);
while (ALength >= 4) do
begin
K := PCardinal(Data)^;
Mix(FHash, K);
Inc(Data, 4);
Dec(ALength, 4);
end;
MixTail(Data, ALength);
end;
end.
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/14227995.html

浙公网安备 33010602011771号