Skip to content

Instantly share code, notes, and snippets.

@pitfield
Last active July 6, 2020 22:34
Show Gist options
  • Save pitfield/69cafdc05d0e9aed2501346f4cc74b14 to your computer and use it in GitHub Desktop.
Save pitfield/69cafdc05d0e9aed2501346f4cc74b14 to your computer and use it in GitHub Desktop.
Swift bitshift operators << and >> are surprisingly slow in unoptimized builds.
//
// 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