소스 검색

Rewrite loop to get better performance (Swift is odd)

Marcin Krzyżanowski 8 년 전
부모
커밋
39e051252b
2개의 변경된 파일41개의 추가작업 그리고 31개의 파일을 삭제
  1. 14 11
      Sources/CryptoSwift/SHA1.swift
  2. 27 20
      Sources/CryptoSwift/SHA2.swift

+ 14 - 11
Sources/CryptoSwift/SHA1.swift

@@ -9,11 +9,11 @@
 public final class SHA1: DigestType {
     static let digestLength:Int = 20 // 160 / 8
     static let blockSize: Int = 64
-    fileprivate static let hashInitialValue: Array<UInt32> = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
+    fileprivate static let hashInitialValue: ContiguousArray<UInt32> = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
 
     fileprivate var accumulated = Array<UInt8>()
     fileprivate var accumulatedLength: Int = 0
-    fileprivate var accumulatedHash: Array<UInt32> = SHA1.hashInitialValue
+    fileprivate var accumulatedHash: ContiguousArray<UInt32> = SHA1.hashInitialValue
 
     public init() {
 
@@ -27,12 +27,12 @@ public final class SHA1: DigestType {
         }
     }
 
-    fileprivate func process(block chunk: ArraySlice<UInt8>, currentHash hh: inout Array<UInt32>) {
+    fileprivate func process(block chunk: ArraySlice<UInt8>, currentHash hh: inout ContiguousArray<UInt32>) {
         // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15, big-endian
         // Extend the sixteen 32-bit words into eighty 32-bit words:
-        var M:Array<UInt32> = Array<UInt32>(repeating: 0, count: 80)
+        var M = ContiguousArray<UInt32>(repeating: 0, count: 80)
         for x in 0..<M.count {
-            switch (x) {
+            switch x {
             case 0...15:
                 let start = chunk.startIndex.advanced(by: x * 4) // * MemoryLayout<UInt32>.size
                 M[x] = UInt32(bytes: chunk, fromIndex: start)
@@ -115,12 +115,15 @@ extension SHA1: Updatable {
         }
 
         // output current hash
-        var result = Array<UInt8>()
-        result.reserveCapacity(SHA1.digestLength)
-
-        for hElement in self.accumulatedHash {
-            let h = hElement.bigEndian
-            result += [UInt8(h & 0xff), UInt8((h >> 8) & 0xff), UInt8((h >> 16) & 0xff), UInt8((h >> 24) & 0xff)]
+        var result = Array<UInt8>(repeating: 0, count: SHA1.digestLength)
+        var pos = 0
+        for idx in 0..<self.accumulatedHash.count {
+            let h = self.accumulatedHash[idx].bigEndian
+            result[pos]     = UInt8(h & 0xff)
+            result[pos + 1] = UInt8((h >> 8) & 0xff)
+            result[pos + 2] = UInt8((h >> 16) & 0xff)
+            result[pos + 3] = UInt8((h >> 24) & 0xff)
+            pos += 4
         }
 
         // reset hash value for instance

+ 27 - 20
Sources/CryptoSwift/SHA2.swift

@@ -82,14 +82,14 @@ public final class SHA2: DigestType {
             }
         }
 
-        fileprivate func resultingArray<T>(_ hh:[T]) -> ArraySlice<T> {
+        fileprivate var finalLength: Int {
             switch (self) {
             case .sha224:
-                return hh[0..<7]
+                return 7
             case .sha384:
-                return hh[0..<6]
+                return 6
             default:
-                return ArraySlice(hh)
+                return Int.max
             }
         }
     }
@@ -285,24 +285,31 @@ extension SHA2: Updatable {
         }
 
         // output current hash
-        var result = Array<UInt8>()
-        result.reserveCapacity(self.variant.digestLength)
-
+        var result = Array<UInt8>(repeating: 0, count: self.variant.digestLength)
         switch self.variant {
             case .sha224, .sha256:
-                self.variant.resultingArray(self.accumulatedHash32).forEach { //TODO: rename resultingArray -> resultSlice
-                    let item = $0.bigEndian
-                    result += [UInt8(item & 0xff), UInt8((item >> 8) & 0xff), UInt8((item >> 16) & 0xff), UInt8((item >> 24) & 0xff)]
-            }
+                var pos = 0
+                for idx in 0..<self.accumulatedHash32.count where idx < self.variant.finalLength {
+                    let h = self.accumulatedHash32[idx].bigEndian
+                    result[pos]     = UInt8(h & 0xff)
+                    result[pos + 1] = UInt8((h >> 8) & 0xff)
+                    result[pos + 2] = UInt8((h >> 16) & 0xff)
+                    result[pos + 3] = UInt8((h >> 24) & 0xff)
+                    pos += 4
+                }
             case .sha384, .sha512:
-                self.variant.resultingArray(self.accumulatedHash64).forEach {
-                    let item = $0.bigEndian
-                    var partialResult = Array<UInt8>()
-                    partialResult.reserveCapacity(8)
-                    for i in 0..<8 {
-                        partialResult.append(UInt8((item >> UInt64(8 * i)) & 0xff))
-                    }
-                    result += partialResult
+                var pos = 0
+                for idx in 0..<self.accumulatedHash64.count where idx < self.variant.finalLength {
+                    let h = self.accumulatedHash64[idx].bigEndian
+                    result[pos]     = UInt8(h & 0xff)
+                    result[pos + 1] = UInt8((h >> 8) & 0xff)
+                    result[pos + 2] = UInt8((h >> 16) & 0xff)
+                    result[pos + 3] = UInt8((h >> 24) & 0xff)
+                    result[pos + 4] = UInt8((h >> 32) & 0xff)
+                    result[pos + 5] = UInt8((h >> 40) & 0xff)
+                    result[pos + 6] = UInt8((h >> 48) & 0xff)
+                    result[pos + 7] = UInt8((h >> 56) & 0xff)
+                    pos += 8
                 }
         }
 
@@ -310,7 +317,7 @@ extension SHA2: Updatable {
         if isLast {
             switch self.variant {
             case .sha224, .sha256:
-                self.accumulatedHash32 = variant.h.map { UInt32($0) } //FIXME: UInt64 for process64
+                self.accumulatedHash32 = variant.h.lazy.map { UInt32($0) } //FIXME: UInt64 for process64
             case .sha384, .sha512:
                 self.accumulatedHash64 = variant.h
             }