.net 选择哈希函数以获得最佳性能

.net 选择哈希函数以获得最佳性能,.net,.net-4.0,hash,.net,.net 4.0,Hash,我需要比较网络上的许多文件(有些可能是大的,有些是小的)。 因此,我计划对每个客户端上的每个文件进行散列,并仅通过网络发送散列值。 这里的主要目标是性能。这意味着最小的网络流量。安全不是问题。 也应该有“零”冲突,因为我不想错误地认为两个不同的文件是相同的。也就是说,我知道理论上总是会有碰撞,我只希望实际遇到它们的机会是绝对可以忽略不计的 所以我的问题是:哪个.net哈希函数最适合这个任务 我正在考虑使用缓冲读取器和MD5CryptoServiceProvider(因为CNG可能不适用于所有客户

我需要比较网络上的许多文件(有些可能是大的,有些是小的)。 因此,我计划对每个客户端上的每个文件进行散列,并仅通过网络发送散列值。
这里的主要目标是性能。这意味着最小的网络流量。安全不是问题。
<强>也应该有“零”冲突,因为我不想错误地认为两个不同的文件是相同的。也就是说,我知道理论上总是会有碰撞,我只希望实际遇到它们的机会是绝对可以忽略不计的

所以我的问题是:哪个.net哈希函数最适合这个任务

我正在考虑使用缓冲读取器和
MD5CryptoServiceProvider
(因为CNG可能不适用于所有客户端)


有没有办法获得比这更好的性能?(可能使用一些外部库?

哈希函数不是为了速度而构建的,因此它们不适合这份工作。在这种情况下,它们的优势(加密安全性)也无关紧要


您应该考虑使用CRC或其他校验和函数;有一个常用的列表。有现成的实现。

我相信您误解了本例中哈希的用途

这是有一个快速的“这些是不一样的”检查。哈希不能告诉你两件事是否相等,因为它们会发生冲突

因此,考虑到一个简单的CRC很少会发生冲突,而且它在大量文件上会更快,这是一个更好的解决方案

如果两个哈希或CRC相同,您的反应应该完全相同:通过实际内容验证相等性。您甚至可以在CRC匹配后,对大小相等的子集进行哈希/CRC,并检查文件大小,以进行快速的“排除”检查



如果您希望有许多相等的文件,哈希仍然不能消除检查其他文件的需要,但它会减少需要。你还需要做其他的检查。散列相等,加上文件长度匹配,再加上部分散列相等(例如,对文件的第一个
x
字节进行散列)就足够了,这取决于您的需要。

这取决于您拥有的文件数

冲突概率
p(冲突)=c/2^N
(在完美的哈希函数中),其中
c
是消息(文件)的数量,
N
是冲突算法中的位数

由于现实世界中的散列函数并不完美,所以您有两个选择:优化速度和优化冲突避免

在第一种情况下,您需要使用。CRC32非常常见,但取决于您拥有的文件数量,可能还不够:您保证会在约43亿条消息(32个有效位)时发生冲突,但实际上,您可能会在约1000万条消息时遇到第一次冲突。CRC32有非常快速的实现(SSE 4.2甚至有一个硬件指令)。CRC64发生冲突的可能性要低得多,但并未得到广泛使用,因此,如果您希望比CRC32避免更多的冲突,最好查看加密哈希函数


如果您想避免冲突,同时牺牲速度,您将需要加密哈希函数,其中MD5(128位)、SHA-1(160位)和SHA-2(通常是SHA-256或SHA-512)是使用最广泛且实现速度最快的函数。MD5提供了非常高效的哈希冲突查找算法,但如果您输入随机消息,您将获得在合理时间内运行时所获得的最接近
P(冲突)=c/2^128

我也遇到过类似情况,需要.NET哈希算法。在速度比安全性更重要的服务器响应缓存中,我需要它。当我到达这个线程时,我注意到关于算法选择和32位与64位执行的性能差异的猜测。为了将一些科学引入这场辩论,我创建了一些代码来实际测试一些可用的算法。我决定测试内置的MD5、SHA1、SHA256和SHA512算法。我还包括来自的CRC32实现和来自的CRC64实现。我对~115MB文件的结果如下:

Stopwatch timer = new Stopwatch();
Force.Crc32.Crc32Algorithm hasherCRC32 = new Force.Crc32.Crc32Algorithm();
System.Security.Cryptography.MD5Cng hasherMD5 = new System.Security.Cryptography.MD5Cng();
System.Security.Cryptography.SHA1Cng hasherSHA1 = new System.Security.Cryptography.SHA1Cng();
System.Security.Cryptography.SHA256Cng hasherSHA256 = new System.Security.Cryptography.SHA256Cng();
System.Security.Cryptography.SHA512Cng hasherSHA512 = new System.Security.Cryptography.SHA512Cng();
String result = "";
String rate = "";

Status.Text += "Running in " + ((IntPtr.Size == 8) ? "64" : "32") + "-bit mode.<br /><br />";

Status.Text += "Warm-up phase:<br />";

timer.Restart();
result = BitConverter.ToUInt32(hasherCRC32.ComputeHash(ImageUploader.FileBytes), 0).ToString("X8");
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "CRC32: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = DamienG.Security.Cryptography.Crc64Iso.Compute(ImageUploader.FileBytes).ToString("X16");
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "CRC64: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherMD5.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "MD5: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherSHA1.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "SHA1: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherSHA256.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "SHA256: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherSHA512.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "SHA512: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

Status.Text += "<br />Final run:<br />";

timer.Restart();
result = BitConverter.ToUInt32(hasherCRC32.ComputeHash(ImageUploader.FileBytes), 0).ToString("X8");
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "CRC32: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = DamienG.Security.Cryptography.Crc64Iso.Compute(ImageUploader.FileBytes).ToString("X16");
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "CRC64: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherMD5.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "MD5: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherSHA1.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "SHA1: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherSHA256.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "SHA256: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";

timer.Restart();
result = Convert.ToBase64String(hasherSHA512.ComputeHash(ImageUploader.FileBytes));
timer.Stop();
rate = ((double)ImageUploader.FileBytes.Length / timer.ElapsedMilliseconds / 1.024 / 1024).ToString("0");
Status.Text += "SHA512: " + rate + " MiB/s [" + result + "] in " + timer.ElapsedMilliseconds + "ms" + ".<br />";
以32位模式运行

预热阶段

CRC32:296 MiB/s[9C54580A]在390ms内

CRC64:95 MiB/s[636BCF1455BC885A]在1212ms内

MD5:191 MiB/s[mm/JVFusWMKcT/p+IR4BjQ==]在604ms中

SHA1:165 MiB/s[WSFkGbnYte5EXb7kgp1kqbi2…]在699ms内

1240ms中的SHA256:93 MiB/s[USKMHQmfMil8/KL/ASyE6rm/…]

SHA512:47 MiB/s[Cp9cazN7WsydTPn+k4Xu359M…]在2464毫秒内

最终运行

CRC32:279 MiB/s[9C54580A]在414ms中

CRC64:96 MiB/s[636BCF1455BC885A]在1203ms内

588ms中的MD5:197 MiB/s[mm/JVFusWMKcT/p+IR4BjQ==]

SHA1:164 MiB/s[WSFkGbnYte5EXb7kgp1kqbi2…]在707ms内

SHA256:96 MiB/s[USKMHQmfMil8/KL/ASyE6rm/…]在1200ms内

2441ms内SHA512:47 MiB/s[Cp9cazN7WsydTPn+k4Xu359M…]


在64位模式下运行

预热阶段

CRC32:310 MiB/s[9C54580A]在373ms内

CRC64:117 MiB/s[636BCF1455BC885A]在986ms中

584ms中的MD5:198 MiB/s[mm/JVFusWMKcT/p+IR4BjQ==]

SHA1:184 MiB/s[WSFkGbnYte5EXb7kgp1kqbi2…]在627ms内

1112ms中的SHA256:104 MiB/s[USKMHQmfMil8/KL/ASyE6rm/…]

778ms中的SHA512:149 MiB/s[Cp9cazN7WsydTPn+k4Xu359M…]

最终运行

CRC32:396ms中的292 MiB/s[9C54580A]

CRC64:119 MiB/s[636BCF1455BC885A]在975ms内

MD5:199 MiB/s[mm/JVFusWMKcT/p+IR4BjQ==]在582ms内

SHA1:192 MiB/s[WSFkGbnYte5EXb7kgp1kqbi2…]在60中
   // Returns an updated CRC32
  function UpdateCrc32(CurByte: Byte; CurCrc: Cardinal): Cardinal; inline;
  begin
    UpdateCrc32 := Crc32Table[Byte(CurCrc xor CurByte)] xor (CurCrc shr 8);
  end;
@calc_crc32:
    xor    dl,[esi]
    mov    al,dl
    shr    edx,8
    xor    edx,dword ptr [edi+eax*4]
    inc    esi
    loop   @calc_crc32
    xor    dl,bl
    shr    rbx,8
    mov    al,dl
    shr    edx,8
    xor    edx,dword ptr [r8+rax*4]
    function CalcCRC32(const B; Size: NativeUINT;
    const 
      InitialValue: Cardinal = CRC32_INIT): Cardinal;
    var
      C: Cardinal;
      P: PAnsiChar;
      i: NativeUINT;
    begin
      C := InitialValue;
      if Size > 0 then
      begin
        P := @B;
        for i := 0 to Size - 1 do
          C := UpdateCrc32(Byte(P[i]), C);
      end;
      Result := C;
    end;
    CRC32.pas.78: begin
                                    push esi
                                    push edi
    CRC32.pas.80: if Size > 0 then
                                    test edx,edx
                                    jbe $00500601
    CRC32.pas.82: P := @B;
                                    mov edi,eax
    CRC32.pas.83: for i := 0 to Size - 1 do
                                    mov eax,edx
                                    dec eax
                                    test eax,eax
                                    jb $00500601
                                    inc eax
                                    xor esi,esi
    CRC32.pas.84: C := UpdateCrc32(Byte(P[i]), C);
                                    movzx edx,[edi+esi]
                                    xor dl,cl
                                    movzx edx,dl
                                    mov edx,[edx*4+$517dec]
                                    shr ecx,$08
                                    xor edx,ecx
                                    mov ecx,edx
                                    inc esi
    CRC32.pas.83: for i := 0 to Size - 1 do
                                    dec eax
                                    jnz $005005e6
    CRC32.pas.86: Result := C;
                                    mov eax,ecx
    CRC32.pas.87: end;
                                    pop edi
                                    pop esi
                                    ret
             586
            .model flat, stdcall 
            .xmm
            .data
            .code
        CRC32 proc sizeOfFile:DWORD, file:DWORD
            push    esi
            push    ecx
            push    edx

            mov esi, file
            xor edx, edx
            or  eax, -1
            mov ecx, sizeOfFile
    
        CRC32_loop:
            mov dl, byte ptr [esi]
            xor dl, al
            shr eax, 8
            xor eax, dword ptr [crc32_table + 4*edx]
            inc esi
            dec ecx
            jnz CRC32_loop
    
            not eax
    
            pop edx
            pop ecx
            pop esi
            ret
    
; MD5_386.Asm   -  386 optimized helper routine for calculating
;                  MD Message-Digest values
; written 2/2/94 by
;
; Peter Sawatzki
; Buchenhof 3
; D58091 Hagen, Germany Fed Rep
;
; EMail: Peter@Sawatzki.de
; EMail: 100031.3002@compuserve.com
; WWW:   http://www.sawatzki.de
;
;
; original C Source was found in Dr. Dobbs Journal Sep 91
; MD5 algorithm from RSA Data Security, Inc.

.386
.MODEL FLAT
.CODE

R1 = ESi
R2 = EDi

FF Macro a,b,c,d,x,s,ac
; a:= ROL (a+x+ac + (b And c Or Not b And d), s) + b
  Add a, [EBp+(4*x)]
  Add a, ac
  Mov R1, b
  Not R1
  And R1, d
  Mov R2, c
  And R2, b
  Or  R1, R2
  Add a, R1
  Rol a, s
  Add a, b
EndM

GG Macro a,b,c,d,x,s,ac
; a:= ROL (a+x+ac + (b And d Or c And Not d), s) + b
  Add a, [EBp+(4*x)]
  Add a, ac
  Mov R1, d
  Not R1
  And R1, c
  Mov R2, d
  And R2, b
  Or  R1, R2
  Add a, R1
  Rol a, s
  Add a, b
EndM

HH Macro a,b,c,d,x,s,ac
; a:= ROL (a+x+ac + (b Xor c Xor d), s) + b
  Add a, [EBp+(4*x)]
  Add a, ac
  Mov R1, d
  Xor R1, c
  Xor R1, b
  Add a, R1
  Rol a, s
  Add a, b
EndM

II Macro a,b,c,d,x,s,ac
; a:= ROL (a+x+ac + (c Xor (b Or Not d)), s) + b
  Add a, [EBp+(4*x)]
  Add a, ac
  Mov R1, d
  Not R1
  Or  R1, b
  Xor R1, c
  Add a, R1
  Rol a, s
  Add a, b
EndM

Transform Proc
Public Transform
;Procedure Transform (Var Accu; Const Buf); Register;

; save registers that Delphi requires to be restored
  Push EBx
  Push ESi
  Push EDi
  Push EBp

  Mov EBp, EDx ; Buf -> EBp
  Push EAx     ; Accu -> Stack
  Mov EDx, [EAx+12]
  Mov ECx, [EAx+8]
  Mov EBx, [EAx+4]
  Mov EAx, [EAx]

  FF EAx,EBx,ECx,EDx,  0,  7, 0d76aa478h  ; 1
  FF EDx,EAx,EBx,ECx,  1, 12, 0e8c7b756h  ; 2
  FF ECx,EDx,EAx,EBx,  2, 17, 0242070dbh  ; 3
  FF EBx,ECx,EDx,EAx,  3, 22, 0c1bdceeeh  ; 4
  FF EAx,EBx,ECx,EDx,  4,  7, 0f57c0fafh  ; 5
  FF EDx,EAx,EBx,ECx,  5, 12, 04787c62ah  ; 6
  FF ECx,EDx,EAx,EBx,  6, 17, 0a8304613h  ; 7
  FF EBx,ECx,EDx,EAx,  7, 22, 0fd469501h  ; 8
  FF EAx,EBx,ECx,EDx,  8,  7, 0698098d8h  ; 9
  FF EDx,EAx,EBx,ECx,  9, 12, 08b44f7afh  ; 10
  FF ECx,EDx,EAx,EBx, 10, 17, 0ffff5bb1h  ; 11
  FF EBx,ECx,EDx,EAx, 11, 22, 0895cd7beh  ; 12
  FF EAx,EBx,ECx,EDx, 12,  7, 06b901122h  ; 13
  FF EDx,EAx,EBx,ECx, 13, 12, 0fd987193h  ; 14
  FF ECx,EDx,EAx,EBx, 14, 17, 0a679438eh  ; 15
  FF EBx,ECx,EDx,EAx, 15, 22, 049b40821h  ; 16

  GG EAx,EBx,ECx,EDx,  1,  5, 0f61e2562h  ; 17
  GG EDx,EAx,EBx,ECx,  6,  9, 0c040b340h  ; 18
  GG ECx,EDx,EAx,EBx, 11, 14, 0265e5a51h  ; 19
  GG EBx,ECx,EDx,EAx,  0, 20, 0e9b6c7aah  ; 20
  GG EAx,EBx,ECx,EDx,  5,  5, 0d62f105dh  ; 21
  GG EDx,EAx,EBx,ECx, 10,  9, 002441453h  ; 22
  GG ECx,EDx,EAx,EBx, 15, 14, 0d8a1e681h  ; 23
  GG EBx,ECx,EDx,EAx,  4, 20, 0e7d3fbc8h  ; 24
  GG EAx,EBx,ECx,EDx,  9,  5, 021e1cde6h  ; 25
  GG EDx,EAx,EBx,ECx, 14,  9, 0c33707d6h  ; 26
  GG ECx,EDx,EAx,EBx,  3, 14, 0f4d50d87h  ; 27
  GG EBx,ECx,EDx,EAx,  8, 20, 0455a14edh  ; 28
  GG EAx,EBx,ECx,EDx, 13,  5, 0a9e3e905h  ; 29
  GG EDx,EAx,EBx,ECx,  2,  9, 0fcefa3f8h  ; 30
  GG ECx,EDx,EAx,EBx,  7, 14, 0676f02d9h  ; 31
  GG EBx,ECx,EDx,EAx, 12, 20, 08d2a4c8ah  ; 32

  HH EAx,EBx,ECx,EDx,  5,  4, 0fffa3942h  ; 33
  HH EDx,EAx,EBx,ECx,  8, 11, 08771f681h  ; 34
  HH ECx,EDx,EAx,EBx, 11, 16, 06d9d6122h  ; 35
  HH EBx,ECx,EDx,EAx, 14, 23, 0fde5380ch  ; 36
  HH EAx,EBx,ECx,EDx,  1,  4, 0a4beea44h  ; 37
  HH EDx,EAx,EBx,ECx,  4, 11, 04bdecfa9h  ; 38
  HH ECx,EDx,EAx,EBx,  7, 16, 0f6bb4b60h  ; 39
  HH EBx,ECx,EDx,EAx, 10, 23, 0bebfbc70h  ; 40
  HH EAx,EBx,ECx,EDx, 13,  4, 0289b7ec6h  ; 41
  HH EDx,EAx,EBx,ECx,  0, 11, 0eaa127fah  ; 42
  HH ECx,EDx,EAx,EBx,  3, 16, 0d4ef3085h  ; 43
  HH EBx,ECx,EDx,EAx,  6, 23, 004881d05h  ; 44
  HH EAx,EBx,ECx,EDx,  9,  4, 0d9d4d039h  ; 45
  HH EDx,EAx,EBx,ECx, 12, 11, 0e6db99e5h  ; 46
  HH ECx,EDx,EAx,EBx, 15, 16, 01fa27cf8h  ; 47
  HH EBx,ECx,EDx,EAx,  2, 23, 0c4ac5665h  ; 48

  II EAx,EBx,ECx,EDx,  0,  6, 0f4292244h  ; 49
  II EDx,EAx,EBx,ECx,  7, 10, 0432aff97h  ; 50
  II ECx,EDx,EAx,EBx, 14, 15, 0ab9423a7h  ; 51
  II EBx,ECx,EDx,EAx,  5, 21, 0fc93a039h  ; 52
  II EAx,EBx,ECx,EDx, 12,  6, 0655b59c3h  ; 53
  II EDx,EAx,EBx,ECx,  3, 10, 08f0ccc92h  ; 54
  II ECx,EDx,EAx,EBx, 10, 15, 0ffeff47dh  ; 55
  II EBx,ECx,EDx,EAx,  1, 21, 085845dd1h  ; 56
  II EAx,EBx,ECx,EDx,  8,  6, 06fa87e4fh  ; 57
  II EDx,EAx,EBx,ECx, 15, 10, 0fe2ce6e0h  ; 58
  II ECx,EDx,EAx,EBx,  6, 15, 0a3014314h  ; 59
  II EBx,ECx,EDx,EAx, 13, 21, 04e0811a1h  ; 60
  II EAx,EBx,ECx,EDx,  4,  6, 0f7537e82h  ; 61
  II EDx,EAx,EBx,ECx, 11, 10, 0bd3af235h  ; 62
  II ECx,EDx,EAx,EBx,  2, 15, 02ad7d2bbh  ; 63
  II EBx,ECx,EDx,EAx,  9, 21, 0eb86d391h  ; 64

  Pop ESi            ; get Accu from stack
  Add [ESi],    EAx
  Add [ESi+4],  EBx
  Add [ESi+8],  ECx
  Add [ESi+12], EDx

; restore registers for Delphi
  Pop EBp
  Pop EDi
  Pop ESi
  Pop EBx

  Ret
  Transform EndP

  End
    procedure CiphersMD5Update(var Context: TMD5Ctx; const ChkBuf; len:         UInt32);
    var
      BufPtr: ^Byte;
      Left: UInt32;
    begin
      If Context.Count[0] + UInt32(len) shl 3 < Context.Count[0] then
        Inc(Context.Count[1]);
      Inc(Context.Count[0], UInt32(len) shl 3);
      Inc(Context.Count[1], UInt32(len) shr 29);
    
      BufPtr := @ChkBuf;
      if Context.BLen > 0 then
      begin
        Left := 64 - Context.BLen;
        if Left > len then
          Left := len;
        Move(BufPtr^, Context.Buffer[Context.BLen], Left);
        Inc(Context.BLen, Left);
        Inc(BufPtr, Left);
        If Context.BLen < 64 then
          Exit;
        Transform(Context.State, @Context.Buffer);
        Context.BLen := 0;
        Dec(len, Left)
      end;
      while len >= 64 do
      begin
        Transform(Context.State, BufPtr);
        Inc(BufPtr, 64);
        Dec(len, 64)
      end;
      if len > 0 then
      begin
        Context.BLen := len;
        Move(BufPtr^, Context.Buffer[0], Context.BLen)
      end
    end;

    
      function crc32csse42(crc: cardinal; buf: Pointer; len: NativeUInt): cardinal;
      asm // ecx=crc, rdx=buf, r8=len
        .NOFRAME
        mov eax,ecx
        not eax
        test r8,r8;   jz @0
        test rdx,rdx; jz @0
 @7:    test rdx,7;   jz @8 // align to 8 bytes boundary
        crc32 eax,byte ptr [rdx]
        inc rdx
        dec r8;     jz @0
        test rdx,7; jnz @7
 @8:    mov rcx,r8
        shr r8,3
        jz @2
 @1:    crc32 eax,qword ptr [rdx] // calculate CRC of 8 bytes, aligned
        dec r8
        lea rdx,rdx+8
        jnz @1
 @2:    // less than 8 bytes remaining
        and rcx,7; jz @0
        cmp rcx,4; jb @4
        crc32 eax,dword ptr [rdx] // calculate CRC of 4 bytes
        sub rcx,4
        lea rdx,rdx+4
        jz @0
@4:     // less than 4 bytes remaining
        crc32 eax,byte ptr [rdx]
        dec rcx; jz @0
        crc32 eax,byte ptr [rdx+1]
        dec rcx; jz @0
        crc32 eax,byte ptr [rdx+2]
@0:     not eax
      end;
        Legend:
        (1) 5b x 5000, AMD FX-8320, PHP5
        (2) 5000b x 5000, AMD FX-8320, PHP5

PHP hash              (1)            (2)
--------         ------------   ------------
md2              0.021267 sec   2.602651 sec
md4              0.002684 sec   0.035243 sec
md5              0.002570 sec   0.055548 sec
sha1             0.003346 sec   0.106432 sec
sha224           0.004945 sec   0.210954 sec
sha256           0.004735 sec   0.238030 sec
sha384           0.005848 sec   0.144015 sec
sha512           0.006085 sec   0.142884 sec
ripemd128        0.003385 sec   0.120959 sec
ripemd160        0.004164 sec   0.174045 sec
ripemd256        0.003487 sec   0.121477 sec
ripemd320        0.004206 sec   0.177473 sec
whirlpool        0.009713 sec   0.509682 sec
tiger128,3       0.003414 sec   0.059028 sec
tiger160,3       0.004354 sec   0.059335 sec
tiger192,3       0.003379 sec   0.058891 sec
tiger128,4       0.003514 sec   0.073468 sec
tiger160,4       0.003602 sec   0.072329 sec
tiger192,4       0.003507 sec   0.071856 sec
snefru           0.022101 sec   1.190888 sec
snefru256        0.021972 sec   1.217704 sec
gost             0.013961 sec   0.653600 sec
adler32          0.001459 sec   0.038849 sec
crc32            0.001429 sec   0.068742 sec
crc32b           0.001553 sec   0.063308 sec
fnv132           0.001431 sec   0.038256 sec
fnv164           0.001586 sec   0.060622 sec
joaat            0.001569 sec   0.062947 sec
haval128,3       0.006747 sec   0.174759 sec
haval160,3       0.005810 sec   0.166154 sec
haval192,3       0.006129 sec   0.168382 sec
haval224,3       0.005918 sec   0.166792 sec
haval256,3       0.006119 sec   0.173360 sec
haval128,4       0.007364 sec   0.233829 sec
haval160,4       0.007917 sec   0.240273 sec
haval192,4       0.007676 sec   0.245864 sec
haval224,4       0.007580 sec   0.245249 sec
haval256,4       0.007442 sec   0.241091 sec
haval128,5       0.008651 sec   0.281248 sec
haval160,5       0.009304 sec   0.278619 sec
haval192,5       0.008972 sec   0.281235 sec
haval224,5       0.008917 sec   0.274923 sec
haval256,5       0.008853 sec   0.282171 sec
        Legend:
        (1) 5b x 5000, Intel Core i5-6600, PHP7
        (2) 5000b x 5000, Intel Core i5-6600, PHP7


PHP hash           (1)            (2)
---------    ------------    ------------
md2          0.016131 sec    2.308100 sec
md4          0.001218 sec    0.040803 sec
md5          0.001284 sec    0.046208 sec
sha1         0.001499 sec    0.050259 sec
sha224       0.002683 sec    0.120510 sec
sha256       0.002297 sec    0.119602 sec
sha384       0.002792 sec    0.080670 sec
ripemd128    0.001984 sec    0.094280 sec
ripemd160    0.002514 sec    0.128295 sec
ripemd256    0.002015 sec    0.093887 sec
ripemd320    0.002748 sec    0.128955 sec
whirlpool    0.003402 sec    0.271102 sec
tiger128,3   0.001282 sec    0.038638 sec
tiger160,3   0.001305 sec    0.037155 sec
tiger192,3   0.001309 sec    0.037684 sec
tiger128,4   0.001618 sec    0.050690 sec
tiger160,4   0.001571 sec    0.049656 sec
tiger192,4   0.001711 sec    0.050682 sec
snefru       0.010949 sec    0.865108 sec
snefru256    0.011587 sec    0.867685 sec
gost         0.008968 sec    0.449647 sec
adler32      0.000588 sec    0.014345 sec
crc32        0.000609 sec    0.079202 sec
crc32b       0.000636 sec    0.074408 sec
fnv132       0.000570 sec    0.028157 sec
fnv164       0.000566 sec    0.028776 sec
joaat        0.000623 sec    0.042127 sec
haval128,3   0.002972 sec    0.084010 sec
haval160,3   0.002968 sec    0.083213 sec
haval192,3   0.002943 sec    0.082217 sec
haval224,3   0.002798 sec    0.084726 sec
haval256,3   0.002995 sec    0.082568 sec
haval128,4   0.003659 sec    0.112680 sec
haval160,4   0.003858 sec    0.111462 sec
haval192,4   0.003526 sec    0.112510 sec
haval224,4   0.003671 sec    0.111656 sec
haval256,4   0.003636 sec    0.111236 sec
haval128,5   0.004488 sec    0.140130 sec
haval160,5   0.005095 sec    0.137777 sec
haval192,5   0.004117 sec    0.140711 sec
haval224,5   0.004311 sec    0.139564 sec
haval256,5   0.004382 sec    0.138345 sec
Legend:
 (1) OpenSSL 1.1.0 on Intel Core i5-6600, number of 16-bytes messages processed in 3 seconds
 (2) OpenSSL 1.1.0 on Intel Core i5-6600, number of 8192-bytes messages processed in 3 seconds


Algorighm              (1)            (2)
---------         ---------      ----------
md4               50390.16k      817875.48k
md5              115875.35k      680700.59k
sha1             118158.30k      995986.09k
ripemd160         30308.79k      213224.11k
whirlpool         39605.02k      182072.66k
      Legend:
        (1) Delphi, 5b x 5000 iterations
        (2) Delphi, 5000b x 5000 iterations

Algorighm                  (1)                     (2)
---------------      --------------         --------------
md2                  0.0381010 secs         5.8495807 secs
md5                  0.0005015 secs         0.0376252 secs
sha1                 0.0050118 secs         0.1830871 secs
crc32               >0.0000001 secs         0.0581535 secs
crc32c (intel hw)   >0.0000001 secs         0.0055349 secs
<?
 define (TRAILING_ZEROS, 6);
 $strlens = array(5, 30, 90, 1000, 5000);
 $hashes = hash_algos();

 function generate_bytes($len)
 {
   if (function_exists('random_bytes')) {$fn='random_bytes';$str = random_bytes($len);} else // for php 5
   if (function_exists('openssl_random_pseudo_bytes')) {$fn='openssl_random_pseudo_bytes';$str = openssl_random_pseudo_bytes($strlen);} else // for php 7
   {
        flush();
        ob_start () ;
        phpinfo () ;
        $str = str_pad(substr(ob_get_contents (), 0, $len), $len) ;
        ob_end_clean () ;
        $fn = 'phpinfo';
   }
   return array(0=>$str, 1=>$fn);
 }

 foreach ($strlens as $strlen)
 {

 $loops = 5000;
 echo "<h1>$loops iterations on $strlen bytes message</h1>".PHP_EOL;
 echo '<p>';
 $r = generate_bytes($strlen);
 $str = $r[0];
 $gotlen = strlen($str);
 while ($gotlen < $strlen)
 {
   // for some uncodumented reason, the  openssl_random_pseudo_bytes returned less bytes than needed
   $left = $strlen-$gotlen;
   echo "The ".$r[1]."() function returned $left byes less, trying again to get these remaining bytes only<br>";
   $r = generate_bytes($left);
   $str.= $r[0];
   $gotlen = strlen($str);
 };

 echo "Got the whole string of ".strlen($str)." bytes!";
 echo '</p>';
 echo PHP_EOL;
 echo "<pre>";

 foreach ($hashes as $hash)
 {
        $tss = microtime(true);
        for($i=0; $i<$loops; $i++)
        {
                $x = hash($hash, $str, true);
        }
        $tse = microtime(true);
        echo "\n".str_pad($hash, 15, ' ')."\t" . str_pad(round($tse-$tss, TRAILING_ZEROS), TRAILING_ZEROS+2, '0') . " sec \t" . bin2hex($x);
 }

 echo PHP_EOL."</pre>".PHP_EOL;
 flush();
 }
?>
Suj5_RxNfIq4u-36o03afg
StRL3WgcNM6AjTSW4ozf8g
i4Ev9nJNFpmf928PrkWbIw
b_GE6cp9c-PT_PLwwYbDXQ
Znci1Nj3HprfFLa0cQNi5g
6ns__XWR7xlsvPgGwZJLBQ
9_Yse6hFEyzgl5y5fnZaUg
LYoIQyhNpmAHqY4r-fgZXg
Y1fVl2rBaan0sKz-qrb8lQ
CiLmDZwUVNW09fQaTv_qSg
easjBIYq27dijGr2o01-5Q