Browse Source

Improve speed of Hash.prepare

Marcin Krzyżanowski 10 years ago
parent
commit
5efc575d9f

+ 13 - 0
CryptoSwift.xcodeproj/project.pbxproj

@@ -135,6 +135,7 @@
 		7552614D1993051E000D2B20 /* Hash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Hash.swift; sourceTree = "<group>"; };
 		7552614D1993051E000D2B20 /* Hash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Hash.swift; sourceTree = "<group>"; };
 		755FB1D9199E347D00475437 /* ExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionsTest.swift; sourceTree = "<group>"; };
 		755FB1D9199E347D00475437 /* ExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionsTest.swift; sourceTree = "<group>"; };
 		7563B2E719B14D4300B152CD /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		7563B2E719B14D4300B152CD /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
+		756BFDCA1A82B87300B9D9A4 /* Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bridging.h; sourceTree = "<group>"; };
 		757DA24E1A4E59F2002BA3EF /* PKCS7.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PKCS7.swift; sourceTree = "<group>"; };
 		757DA24E1A4E59F2002BA3EF /* PKCS7.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PKCS7.swift; sourceTree = "<group>"; };
 		757DA2501A4E5E95002BA3EF /* PaddingMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingMode.swift; sourceTree = "<group>"; };
 		757DA2501A4E5E95002BA3EF /* PaddingMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingMode.swift; sourceTree = "<group>"; };
 		757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingTests.swift; sourceTree = "<group>"; };
 		757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaddingTests.swift; sourceTree = "<group>"; };
@@ -261,6 +262,7 @@
 				757DA2581A4ED4D7002BA3EF /* ChaCha20Tests.swift */,
 				757DA2581A4ED4D7002BA3EF /* ChaCha20Tests.swift */,
 				755FB1D9199E347D00475437 /* ExtensionsTest.swift */,
 				755FB1D9199E347D00475437 /* ExtensionsTest.swift */,
 				757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */,
 				757DA2521A4ED0A4002BA3EF /* PaddingTests.swift */,
+				756BFDCA1A82B87300B9D9A4 /* Bridging.h */,
 				754BE46519693E190098E6F3 /* Supporting Files */,
 				754BE46519693E190098E6F3 /* Supporting Files */,
 			);
 			);
 			path = CryptoSwiftTests;
 			path = CryptoSwiftTests;
@@ -592,6 +594,8 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_UNROLL_LOOPS = YES;
 				HEADER_SEARCH_PATHS = (
 				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"/Applications/Xcode6-Beta3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
 					"/Applications/Xcode6-Beta3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
@@ -600,8 +604,10 @@
 				INFOPLIST_FILE = CryptoSwift/Info.plist;
 				INFOPLIST_FILE = CryptoSwift/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LLVM_LTO = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
 				SKIP_INSTALL = YES;
+				SWIFT_OPTIMIZATION_LEVEL = "-Ounchecked";
 			};
 			};
 			name = Release;
 			name = Release;
 		};
 		};
@@ -623,8 +629,10 @@
 				);
 				);
 				INFOPLIST_FILE = CryptoSwiftTests/Info.plist;
 				INFOPLIST_FILE = CryptoSwiftTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LLVM_LTO = NO;
 				METAL_ENABLE_DEBUG_INFO = YES;
 				METAL_ENABLE_DEBUG_INFO = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OBJC_BRIDGING_HEADER = CryptoSwiftTests/Bridging.h;
 			};
 			};
 			name = Debug;
 			name = Debug;
 		};
 		};
@@ -635,6 +643,8 @@
 					"$(SDKROOT)/Developer/Library/Frameworks",
 					"$(SDKROOT)/Developer/Library/Frameworks",
 					"$(inherited)",
 					"$(inherited)",
 				);
 				);
+				GCC_OPTIMIZATION_LEVEL = fast;
+				GCC_UNROLL_LOOPS = YES;
 				HEADER_SEARCH_PATHS = (
 				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"/Applications/Xcode6-Beta3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
 					"/Applications/Xcode6-Beta3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
@@ -642,8 +652,11 @@
 				);
 				);
 				INFOPLIST_FILE = CryptoSwiftTests/Info.plist;
 				INFOPLIST_FILE = CryptoSwiftTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LLVM_LTO = YES;
 				METAL_ENABLE_DEBUG_INFO = NO;
 				METAL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OBJC_BRIDGING_HEADER = CryptoSwiftTests/Bridging.h;
+				SWIFT_OPTIMIZATION_LEVEL = "-Ounchecked";
 			};
 			};
 			name = Release;
 			name = Release;
 		};
 		};

+ 7 - 2
CryptoSwift/CryptoHashBase.swift

@@ -24,9 +24,14 @@ class HashBase {
         tmpMessage.appendBytes([0x80]) // append one bit (Byte with one bit) to message
         tmpMessage.appendBytes([0x80]) // append one bit (Byte with one bit) to message
         
         
         // append "0" bit until message length in bits ≡ 448 (mod 512)
         // append "0" bit until message length in bits ≡ 448 (mod 512)
-        while tmpMessage.length % len != (len - 8) {
-            tmpMessage.appendBytes([0x00])
+        var msgLength = tmpMessage.length;
+        var counter = 0;
+        while msgLength % len != (len - 8) {
+            counter++
+            msgLength++
         }
         }
+        var bufZeros = UnsafeMutablePointer<Byte>(calloc(UInt(counter), UInt(sizeof(Byte))))
+        tmpMessage.appendBytes(bufZeros, length: counter)
         
         
         return tmpMessage
         return tmpMessage
     }
     }

+ 2 - 1
CryptoSwift/MD5.swift

@@ -50,8 +50,9 @@ class MD5 : CryptoSwift.HashBase {
         // Process the message in successive 512-bit chunks:
         // Process the message in successive 512-bit chunks:
         let chunkSizeBytes = 512 / 8 // 64
         let chunkSizeBytes = 512 / 8 // 64
         var leftMessageBytes = tmpMessage.length
         var leftMessageBytes = tmpMessage.length
-        for var i = 0; i < tmpMessage.length; i = i + chunkSizeBytes, leftMessageBytes -= chunkSizeBytes {
+        for (var i = 0; i < tmpMessage.length; i = i + chunkSizeBytes, leftMessageBytes -= chunkSizeBytes) {
             let chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
             let chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
+            let bytes = tmpMessage.bytes;
             
             
             // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
             // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
             var M:[UInt32] = [UInt32](count: 16, repeatedValue: 0)
             var M:[UInt32] = [UInt32](count: 16, repeatedValue: 0)

+ 14 - 0
CryptoSwiftTests/Bridging.h

@@ -0,0 +1,14 @@
+//
+//  Bridging.h
+//  CryptoSwift
+//
+//  Created by Marcin Krzyzanowski on 04/02/15.
+//  Copyright (c) 2015 Marcin Krzyzanowski. All rights reserved.
+//
+
+#ifndef CryptoSwift_Bridging_h
+#define CryptoSwift_Bridging_h
+
+#import <CommonCrypto/CommonCrypto.h>
+
+#endif

+ 32 - 0
CryptoSwiftTests/HashTests.swift

@@ -74,6 +74,38 @@ class CryptoSwiftTests: XCTestCase {
         }
         }
     }
     }
     
     
+    func testMD5PerformanceSwift() {
+        self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
+            let buf = UnsafeMutablePointer<Byte>(calloc(2048, UInt(sizeof(Byte))))
+            let data = NSData(bytes: buf, length: 2048)
+            self.startMeasuring()
+            for _ in [0...1000] {
+                Hash.md5(data).calculate()
+            }
+            self.stopMeasuring()
+            buf.dealloc(1024)
+            buf.destroy()
+        })
+    }
+    
+    func testMD5PerformanceCommonCrypto() {
+        self.measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, forBlock: { () -> Void in
+            let buf = UnsafeMutablePointer<Byte>(calloc(2048, UInt(sizeof(Byte))))
+            let data = NSData(bytes: buf, length: 2048)
+            self.startMeasuring()
+            for _ in [0...1000] {
+                var outbuf = UnsafeMutablePointer<UInt8>.alloc(Int(CC_MD5_DIGEST_LENGTH))
+                CC_MD5(data.bytes, CC_LONG(data.length), outbuf)
+                let output = NSData(bytes: outbuf, length: Int(CC_MD5_DIGEST_LENGTH));
+                outbuf.dealloc(Int(CC_MD5_DIGEST_LENGTH))
+                outbuf.destroy()
+            }
+            self.stopMeasuring()
+            buf.dealloc(1024)
+            buf.destroy()
+        })
+    }
+    
     func testSHA1() {
     func testSHA1() {
         var data:NSData = NSData(bytes: [0x31, 0x32, 0x33] as [Byte], length: 3)
         var data:NSData = NSData(bytes: [0x31, 0x32, 0x33] as [Byte], length: 3)
         if let hash = data.sha1() {
         if let hash = data.sha1() {