Skip to content

[DO NOT MERGE][benchmark] Modernize benchmark definitions #39331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 35 additions & 29 deletions benchmark/single-source/Ackermann.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,44 @@
// for performance measuring.
import TestsUtils

public let Ackermann = BenchmarkInfo(
name: "Ackermann",
runFunction: run_Ackermann,
tags: [.algorithm])
public let benchmarks: [Benchmark] = [
Ackermann()
]

func ackermann(_ M: Int, _ N : Int) -> Int {
if (M == 0) { return N + 1 }
if (N == 0) { return ackermann(M - 1, 1) }
return ackermann(M - 1, ackermann(M, N - 1))
}

@inline(never)
func Ackermann(_ M: Int, _ N : Int) -> Int {
// This if prevents optimizer from computing return value of Ackermann(3,9)
// at compile time.
if False() { return 0 }
if (M == 0) { return N + 1 }
if (N == 0) { return ackermann(M - 1, 1) }
return ackermann(M - 1, ackermann(M, N - 1))
}
struct Ackermann: Benchmark {
var name: String { "Ackermann" }
var tags: Tags { [.algorithm] }

let ref_result = [5, 13, 29, 61, 125, 253, 509, 1021, 2045, 4093, 8189, 16381, 32765, 65533, 131069]
let ref_result = [
5, 13, 29, 61, 125, 253, 509, 1021, 2045,
4093, 8189, 16381, 32765, 65533, 131069
]

@inline(never)
public func run_Ackermann(_ N: Int) {
let (m, n) = (3, 6)
var result = 0
for _ in 1...N {
result = Ackermann(m, n)
if result != ref_result[n] {
break
func run(iterations: Int) {
let (m, n) = (3, 6)
var result = 0
for _ in 1 ... iterations {
result = ackermann(m, n)
if result != ref_result[n] {
break
}
}
check(result == ref_result[n])
}

@inline(never)
func ackermann(_ m: Int, _ n : Int) -> Int {
// This if prevents optimizer from computing the return value at compile
// time.
if getFalse() { return 0 }
if m == 0 { return n + 1 }
if n == 0 { return ackermann(m - 1, 1) }
return ackermann(m - 1, ackermann(m, n - 1))
}

func _ackermann(_ m: Int, _ n : Int) -> Int {
if m == 0 { return n + 1 }
if n == 0 { return ackermann(m - 1, 1) }
return ackermann(m - 1, ackermann(m, n - 1))
}
CheckResults(result == ref_result[n])
}
205 changes: 121 additions & 84 deletions benchmark/single-source/AngryPhonebook.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,78 +14,6 @@
// to test uppercase and lowercase ASCII string fast paths.
import TestsUtils

let t: [BenchmarkCategory] = [.validation, .api, .String]

public let AngryPhonebook = [
BenchmarkInfo(
name: "AngryPhonebook",
runFunction: run_AngryPhonebook,
tags: t,
legacyFactor: 7),

// Small String Workloads
BenchmarkInfo(
name: "AngryPhonebook.ASCII2.Small",
runFunction: { angryPhonebook($0*10, ascii) },
tags: t,
setUpFunction: { blackHole(ascii) }),
BenchmarkInfo(
name: "AngryPhonebook.Strasse.Small",
runFunction: { angryPhonebook($0, strasse) },
tags: t,
setUpFunction: { blackHole(strasse) }),
BenchmarkInfo(
name: "AngryPhonebook.Armenian.Small",
runFunction: { angryPhonebook($0, armenian) },
tags: t,
setUpFunction: { blackHole(armenian) }),
BenchmarkInfo(
name: "AngryPhonebook.Cyrillic.Small",
runFunction: { angryPhonebook($0, cyrillic) },
tags: t,
setUpFunction: { blackHole(cyrillic) }),

// Regular String Workloads
BenchmarkInfo(
name: "AngryPhonebook.ASCII2",
runFunction: { angryPhonebook($0*10, precomposed: longASCII) },
tags: t,
setUpFunction: { blackHole(longASCII) }),
BenchmarkInfo(
name: "AngryPhonebook.Strasse",
runFunction: { angryPhonebook($0, precomposed: longStrasse) },
tags: t,
setUpFunction: { blackHole(longStrasse) }),
BenchmarkInfo(
name: "AngryPhonebook.Armenian",
runFunction: { angryPhonebook($0, precomposed: longArmenian) },
tags: t,
setUpFunction: { blackHole(longArmenian) }),
BenchmarkInfo(
name: "AngryPhonebook.Cyrillic",
runFunction: { angryPhonebook($0, precomposed: longCyrillic) },
tags: t,
setUpFunction: { blackHole(longCyrillic) })
]

let words = [
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph",
"Charles", "Thomas", "Christopher", "Daniel", "Matthew", "Donald", "Anthony",
"Paul", "Mark", "George", "Steven", "Kenneth", "Andrew", "Edward", "Brian",
"Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Gary", "Ryan",
"Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Frank"]

@inline(never)
public func run_AngryPhonebook(_ N: Int) {
// Permute the names.
for _ in 1...N {
for firstname in words {
for lastname in words {
_ = (firstname.uppercased(), lastname.lowercased())
}
}
}
}

// Workloads for various scripts. Always 20 names for 400 pairings.
// To keep the performance of various scripts roughly comparable, aim for
Expand All @@ -103,6 +31,13 @@ public func run_AngryPhonebook(_ N: Int) {
// armenian | 232 B | 232 B | longArmenian | 10478 B | 11676 B
// cyrillic | 238 B | 238 B | longCyrillic | 10718 B | 11916 B

let words = [
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph",
"Charles", "Thomas", "Christopher", "Daniel", "Matthew", "Donald", "Anthony",
"Paul", "Mark", "George", "Steven", "Kenneth", "Andrew", "Edward", "Brian",
"Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Gary", "Ryan",
"Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Frank"]

let ascii = Array(words.prefix(20))
// Pathological case, uppercase: ß -> SS
let strasse = Array(repeating: "Straße", count: 20)
Expand Down Expand Up @@ -131,22 +66,124 @@ let longStrasse = phonebook(strasse)
let longArmenian = phonebook(armenian)
let longCyrillic = phonebook(cyrillic)

@inline(never)
public func angryPhonebook(_ N: Int, _ names: [String]) {
assert(names.count == 20)
// Permute the names.
for _ in 1...N {
for firstname in names {
for lastname in names {
blackHole((firstname.uppercased(), lastname.lowercased()))

struct LegacyAngryPhonebook: Benchmark {
let name: String

init(name: String) {
self.name = name
}

var tags: Tags { [.validation, .api, .String] }
var legacyFactor: Int? { 7 }

func run(iterations: Int) {
run_AngryPhonebook(iterations)
}

@inline(never)
@usableFromInline
func run_AngryPhonebook(_ iterations: Int) {
// Permute the names.
for _ in 1...iterations {
for firstname in words {
for lastname in words {
_ = (firstname.uppercased(), lastname.lowercased())
}
}
}
}
}

struct AngryPhonebook: Benchmark {
let name: String
let input: [String]
let factor: Int

init(name: String, input: [String], factor: Int = 1) {
self.name = name
self.input = input
self.factor = factor
}

var tags: Tags { [.validation, .api, .String] }

func run(iterations: Int) {
Self.angryPhonebook(factor * iterations, input)
}

@inline(never)
@usableFromInline
static func angryPhonebook(_ iterations: Int, _ names: [String]) {
assert(names.count == 20)
// Permute the names.
for _ in 1...iterations {
for firstname in names {
for lastname in names {
blackHole((firstname.uppercased(), lastname.lowercased()))
}
}
}
}
}

@inline(never)
public func angryPhonebook(_ N: Int, precomposed names: String) {
for _ in 1...N {
blackHole((names.uppercased(), names.lowercased()))
struct PrecomposedAngryPhonebook: Benchmark {
let name: String
let input: String
let factor: Int

init(name: String, input: String, factor: Int = 1) {
self.name = name
self.input = input
self.factor = factor
}

var tags: Tags { [.validation, .api, .String] }

func run(iterations: Int) {
Self.angryPhonebook(factor * iterations, input)
}

@inline(never)
@usableFromInline
static func angryPhonebook(_ iterations: Int, _ names: String) {
for _ in 1...iterations {
blackHole((names.uppercased(), names.lowercased()))
}
}
}

public let benchmarks: [Benchmark] = [
LegacyAngryPhonebook(name: "AngryPhonebook"),

// Small String Workloads
AngryPhonebook(
name: "AngryPhonebook.ASCII2.Small",
input: ascii,
factor: 10),
AngryPhonebook(
name: "AngryPhonebook.Strasse.Small",
input: strasse),
AngryPhonebook(
name: "AngryPhonebook.Armenian.Small",
input: armenian),
AngryPhonebook(
name: "AngryPhonebook.Cyrillic.Small",
input: cyrillic),

// Regular String Workloads
PrecomposedAngryPhonebook(
name: "AngryPhonebook.ASCII2",
input: longASCII,
factor: 10),
PrecomposedAngryPhonebook(
name: "AngryPhonebook.Strasse",
input: longStrasse),
PrecomposedAngryPhonebook(
name: "AngryPhonebook.Armenian",
input: longArmenian),
PrecomposedAngryPhonebook(
name: "AngryPhonebook.Cyrillic",
input: longCyrillic),
]

Loading