Browse Source

Merge pull request #767 from valeriyvan/checksum

Refactors Data.checksum() increasing performance 5 times
Marcin Krzyzanowski 5 years ago
parent
commit
c65b43866b

+ 3 - 6
Sources/CryptoSwift/Foundation/Data+Extension.swift

@@ -18,13 +18,10 @@ import Foundation
 extension Data {
   /// Two octet checksum as defined in RFC-4880. Sum of all octets, mod 65536
   public func checksum() -> UInt16 {
-    var s: UInt32 = 0
-    let bytesArray = bytes
-    for i in 0 ..< bytesArray.count {
-      s = s + UInt32(bytesArray[i])
+    let s = self.withUnsafeBytes { buf in
+        return buf.lazy.map(UInt32.init).reduce(UInt32(0), +)
     }
-    s = s % 65536
-    return UInt16(s)
+    return UInt16(s % 65535)
   }
 
   public func md5() -> Data {

+ 14 - 0
Tests/CryptoSwiftTests/DigestTests.swift

@@ -220,6 +220,20 @@ final class DigestTests: XCTestCase {
     XCTAssert(data.checksum() == 0x96, "Invalid checksum")
   }
 
+  func testChecksumPerformance() {
+    let len = 1_000_000
+    let a = [UInt8](unsafeUninitializedCapacity: len) { buf, count in
+      for i in 0..<len {
+        buf[i] = UInt8.random(in: 0...UInt8.max)
+      }
+      count = len
+    }
+    let data: Data = Data(bytes: UnsafePointer<UInt8>(a), count: len)
+    self.measure {
+      _ = data.checksum()
+    }
+  }
+
   func testSHAPartialUpdates() {
     do {
       let testSize = 1024 * 1024 * 5