Last active
July 6, 2020 22:34
-
-
Save pitfield/69cafdc05d0e9aed2501346f4cc74b14 to your computer and use it in GitHub Desktop.
Swift bitshift operators << and >> are surprisingly slow in unoptimized builds.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// BitshiftBenchmark | |
// | |
// Copyright 2020 David Pitfield | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// | |
// TL;DR: The Swift << and >> operators are about 10,000 times slower in unoptimized builds than | |
// they are for optimized builds (SWIFT_OPTIMIZATION_LEVEL=-O). | |
// | |
// DETAILS: This gist benchmarks the performance of the Swift << and >> operators by timing two | |
// computations: one that uses << and >>, and another, of similar form, that does not. | |
// The benchmark was run on both unoptimized builds (SWIFT_OPTIMIZATION_LEVEL=-Onone) and | |
// optimized builds (SWIFT_OPTIMIZATION_LEVEL=-O). | |
// | |
// (In Xcode, SWIFT_OPTIMIZATION_LEVEL corresponds to Swift Compiler - Code Generation > | |
// Optimization Level.) | |
// | |
// RESULTS (2017 iMac, 3.5 GHz Quad-Core Intel Core i5, Xcode 11.5): | |
// | |
// Output for SWIFT_OPTIMIZATION_LEVEL=-Onone (no optimization): | |
// | |
// iteration count: 1000000 | |
// | |
// 4c8f2f2d8x 1013.445 ms rotate right by 5 bits | |
// b7a5a4f48x 433.382 ms placebo | |
// 580.063 ms net cost of rotate right by 5 bits vs. placebo (1000000 iterations) | |
// | |
// Output for SWIFT_OPTIMIZATION_LEVEL=-O (optimize for speed): | |
// | |
// iteration count: 1000000 | |
// | |
// 4c8f2f2d8x 0.709 ms rotate right by 5 bits | |
// b7a5a4f48x 0.649 ms placebo | |
// 0.060 ms net cost of rotate right by 5 bits vs. placebo (1000000 iterations) | |
// | |
// CONCLUSION: The Swift bitshift operators are about 10,000 times (580 / 0.06) slower in unoptimized | |
// builds than optimized builds. | |
import Foundation | |
func time(_ message: String, operation: () -> UInt32) -> Double { | |
let start = Date() | |
let result = operation() | |
let elapsed = Date().timeIntervalSince(start) * 1000 | |
print(String(format: "%0x8x %9.3f ms", result, elapsed) + " " + message) | |
return elapsed | |
} | |
let iterationCount = 1_000_000 | |
print("iteration count: \(iterationCount)") | |
print() | |
let rotrElapsed = time("rotate right by 5 bits") { | |
var a: UInt32 = 0x12345678 | |
for _ in 0..<iterationCount { | |
a = a &+ ((a >> 5) | (a << 27)) | |
} | |
return a // emit the result to prevent compiler from optimizing out its computation | |
} | |
let placeboElapsed = time("placebo") { | |
var a: UInt32 = 0x12345678 | |
for _ in 0..<iterationCount { | |
a = a &+ (a | 0x5a5a5a5a) | |
} | |
return a // emit the result to prevent compiler from optimizing out its computation | |
} | |
print(String(format: " %9.3f ms", rotrElapsed - placeboElapsed) + | |
" net cost of rotate right by 5 bits over placebo (\(iterationCount) iterations)") | |
print() | |
// EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment