Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@milseman
Last active October 15, 2018 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milseman/9b579ab001f12676b15b40b1b87e9143 to your computer and use it in GitHub Desktop.
Save milseman/9b579ab001f12676b15b40b1b87e9143 to your computer and use it in GitHub Desktop.
Extracted from Substring.swift benchmark
print("start")
public var i = 0
// @inline(never)
// public func blackHole<T>(_ x: T) {
// i += 1
// }
@inline(never)
public func blackHole(_ x: Bool) {
i += x ? 1 : 0
}
@inline(never)
public func blackHole<C: Collection>(_ x: C) {
i += x.isEmpty ? 1 : 0
}
@inline(never)
public func blackHole<T>(_ x: UnsafeMutablePointer<T>) {
i += UInt(bitPattern: x) % 2 == 0 ? 1 : 0
}
@inline(never)
public func CheckResults(_ x: Bool) {
guard x else { fatalError() }
}
// import TestsUtils
// public let SubstringTest = [
// BenchmarkInfo(name: "EqualStringSubstring", runFunction: run_EqualStringSubstring, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "EqualSubstringString", runFunction: run_EqualSubstringString, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "EqualSubstringSubstring", runFunction: run_EqualSubstringSubstring, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "EqualSubstringSubstringGenericEquatable", runFunction: run_EqualSubstringSubstringGenericEquatable, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "LessSubstringSubstring", runFunction: run_LessSubstringSubstring, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "LessSubstringSubstringGenericComparable", runFunction: run_LessSubstringSubstringGenericComparable, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "StringFromLongWholeSubstring", runFunction: run_StringFromLongWholeSubstring, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "StringFromLongWholeSubstringGeneric", runFunction: run_StringFromLongWholeSubstringGeneric, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "SubstringComparable", runFunction: run_SubstringComparable, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "SubstringEqualString", runFunction: run_SubstringEqualString, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "SubstringEquatable", runFunction: run_SubstringEquatable, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "SubstringFromLongString", runFunction: run_SubstringFromLongString, tags: [.validation, .api, .String]),
// BenchmarkInfo(name: "SubstringFromLongStringGeneric", runFunction: run_SubstringFromLongStringGeneric, tags: [.validation, .api, .String]),
// ]
// A string that doesn't fit in small string storage and doesn't fit in Latin-1
let longWide = "fα½’asα½’odα½’ijα½’adα½’olα½’sjα½’alα½’sdα½’jlα½’asα½’dfα½’ijα½’liα½’sdα½’jΓΈα½’slα½’diα½’alα½’iα½’"
@inline(never)
public func run_SubstringFromLongString(_ N: Int) {
var s = longWide
s += "!" // ensure the string has a real buffer
for _ in 1...N*500 {
blackHole(Substring(s))
}
}
func create<T : RangeReplaceableCollection, U : Collection>(
_: T.Type, from source: U
) where T.Element == U.Element {
blackHole(T(source))
}
@inline(never)
public func run_SubstringFromLongStringGeneric(_ N: Int) {
var s = longWide
s += "!" // ensure the string has a real buffer
for _ in 1...N*500 {
create(Substring.self, from: s)
}
}
@inline(never)
public func run_StringFromLongWholeSubstring(_ N: Int) {
var s0 = longWide
s0 += "!" // ensure the string has a real buffer
let s = Substring(s0)
for _ in 1...N*500 {
blackHole(String(s))
}
}
@inline(never)
public func run_StringFromLongWholeSubstringGeneric(_ N: Int) {
var s0 = longWide
s0 += "!" // ensure the string has a real buffer
let s = Substring(s0)
for _ in 1...N*500 {
create(String.self, from: s)
}
}
private func equivalentWithDistinctBuffers() -> (String, Substring) {
var s0 = longWide
withUnsafeMutablePointer(to: &s0) { blackHole($0) }
s0 += "!"
// These two should be equal but with distinct buffers, both refcounted.
let a = Substring(s0).dropFirst()
let b = String(a)
return (b, a)
}
@inline(never)
public func run_EqualStringSubstring(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
blackHole(a == b)
}
}
@inline(never)
public func run_EqualSubstringString(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
blackHole(b == a)
}
}
@inline(never)
public func run_EqualSubstringSubstring(_ N: Int) {
let (_, a) = equivalentWithDistinctBuffers()
let (_, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
blackHole(a == b)
}
}
@inline(never)
public func run_EqualSubstringSubstringGenericEquatable(_ N: Int) {
let (_, a) = equivalentWithDistinctBuffers()
let (_, b) = equivalentWithDistinctBuffers()
func check<T>(_ x: T, _ y: T) where T : Equatable {
blackHole(x == y)
}
for _ in 1...N*500 {
check(a, b)
}
}
/*
func checkEqual<T, U>(_ x: T, _ y: U)
where T : StringProtocol, U : StringProtocol {
blackHole(x == y)
}
@inline(never)
public func run _EqualStringSubstringGenericStringProtocol(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
checkEqual(a, b)
}
}
@inline(never)
public func run _EqualSubstringStringGenericStringProtocol(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
checkEqual(b, a)
}
}
@inline(never)
public func run _EqualSubstringSubstringGenericStringProtocol(_ N: Int) {
let (_, a) = equivalentWithDistinctBuffers()
let (_, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
checkEqual(a, b)
}
}
*/
//===----------------------------------------------------------------------===//
/*
@inline(never)
public func run _LessStringSubstring(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
blackHole(a < b)
}
}
@inline(never)
public func run _LessSubstringString(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
blackHole(b < a)
}
}
*/
@inline(never)
public func run_LessSubstringSubstring(_ N: Int) {
let (_, a) = equivalentWithDistinctBuffers()
let (_, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
blackHole(a < b)
}
}
@inline(never)
public func run_LessSubstringSubstringGenericComparable(_ N: Int) {
let (_, a) = equivalentWithDistinctBuffers()
let (_, b) = equivalentWithDistinctBuffers()
func check<T>(_ x: T, _ y: T) where T : Comparable {
blackHole(x < y)
}
for _ in 1...N*500 {
check(a, b)
}
}
@inline(never)
public func run_SubstringEquatable(_ N: Int) {
var string = "pen,pineapple,apple,pen"
string += ",βœ’οΈ,🍍,🍏,βœ’οΈ"
let substrings = string.split(separator: ",")
var count = 0
for _ in 1...N*500 {
for s in substrings {
if substrings.contains(s) { count = count &+ 1 }
}
}
CheckResults(count == 8*N*500)
}
@inline(never)
public func run_SubstringEqualString(_ N: Int) {
var string = "pen,pineapple,apple,pen"
string += ",βœ’οΈ,🍍,🍏,βœ’οΈ"
let substrings = string.split(separator: ",")
let pineapple = "pineapple"
let apple = "🍏"
var count = 0
for _ in 1...N*500 {
for s in substrings {
if s == pineapple || s == apple { count = count &+ 1 }
}
}
CheckResults(count == 2*N*500)
}
@inline(never)
public func run_SubstringComparable(_ N: Int) {
var string = "pen,pineapple,apple,pen"
string += ",βœ’οΈ,🍍,🍏,βœ’οΈ"
let substrings = string.split(separator: ",")
let comparison = substrings + ["PPAP"]
var count = 0
for _ in 1...N*500 {
if substrings.lexicographicallyPrecedes(comparison) {
count = count &+ 1
}
}
CheckResults(count == N*500)
}
/*
func checkLess<T, U>(_ x: T, _ y: U)
where T : StringProtocol, U : StringProtocol {
blackHole(x < y)
}
@inline(never)
public func run _LessStringSubstringGenericStringProtocol(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
checkLess(a, b)
}
}
@inline(never)
public func run _LessSubstringStringGenericStringProtocol(_ N: Int) {
let (a, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
checkLess(b, a)
}
}
@inline(never)
public func run _LessSubstringSubstringGenericStringProtocol(_ N: Int) {
let (_, a) = equivalentWithDistinctBuffers()
let (_, b) = equivalentWithDistinctBuffers()
for _ in 1...N*500 {
checkLess(a, b)
}
}
*/
import Dispatch
func time<T>(_ _caller : String = #function, _ block: () -> T) -> T {
let start = DispatchTime.now()
let res = block()
let end = DispatchTime.now()
let milliseconds = (end.uptimeNanoseconds - start.uptimeNanoseconds) / 1_000_000
print("\(_caller)\t\(milliseconds)")
// print("result: \(res)")
return res
}
let N = 1_000
print("Running...")
time("EqualStringSubstring") {
run_EqualStringSubstring(N * 32)
}
time("EqualSubstringString") {
run_EqualSubstringString(N * 20)
}
time("EqualSubstringSubstring") {
run_EqualSubstringSubstring(N * 20)
}
time("EqualSubstringSubstringGenericEquatable") {
run_EqualSubstringSubstringGenericEquatable(N * 20)
}
time("LessSubstringSubstring") {
run_LessSubstringSubstring(N * 20)
}
time("LessSubstringSubstringGenericComparable") {
run_LessSubstringSubstringGenericComparable(N * 20)
}
time("SubstringComparable") {
run_SubstringComparable(N * 8)
}
time("SubstringEqualString") {
run_SubstringEqualString(N / 4)
}
time("SubstringEquatable") {
run_SubstringEquatable(N / 8)
}
time("StringFromLongWholeSubstringGeneric") {
run_StringFromLongWholeSubstringGeneric(N * 4)
}
time("StringFromLongWholeSubstring ") {
run_StringFromLongWholeSubstring(N * 4)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment