mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
153 lines
5.3 KiB
Swift
153 lines
5.3 KiB
Swift
//===--- AngryPhonebook.swift ---------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// This test is based on single-source/Phonebook, with
|
|
// to test uppercase and lowercase ASCII string fast paths.
|
|
import TestsUtils
|
|
|
|
let t: [BenchmarkCategory] = [.validation, .api, .String]
|
|
|
|
public let benchmarks = [
|
|
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
|
|
// a total length of approximately 120 characters.
|
|
// E.g.: `ascii.joined(separator: "").count == 124`
|
|
// Every name should fit in 15-bytes UTF-8 encoded, to exercise the small
|
|
// string optimization.
|
|
// E.g.: `armenian.allSatisfy { $0._guts.isSmall } == true`
|
|
|
|
// Workload Size Statistics
|
|
// SMALL | UTF-8 | UTF-16 | REGULAR | UTF-8 | UTF-16
|
|
// ---------|-------|--------|--------------|---------|--------
|
|
// ascii | 124 B | 248 B | longASCII | 6158 B | 12316 B
|
|
// strasse | 140 B | 240 B | longStrasse | 6798 B | 11996 B
|
|
// armenian | 232 B | 232 B | longArmenian | 10478 B | 11676 B
|
|
// cyrillic | 238 B | 238 B | longCyrillic | 10718 B | 11916 B
|
|
|
|
let ascii = Array(words.prefix(20))
|
|
// Pathological case, uppercase: ß -> SS
|
|
let strasse = Array(repeating: "Straße", count: 20)
|
|
|
|
let armenian = [
|
|
"Արմեն", "Աննա", "Հարութ", "Միքայել", "Մարիա", "Դավիթ", "Վարդան",
|
|
"Նարինե", "Տիգրան", "Տաթևիկ", "Թագուհի", "Թամարա", "Ազնաուր", "Գրիգոր",
|
|
"Կոմիտաս", "Հայկ", "Գառնիկ", "Վահրամ", "Վահագն", "Գևորգ"]
|
|
|
|
let cyrillic = [
|
|
"Ульяна", "Аркадий", "Аня", "Даниил", "Дмитрий", "Эдуард", "Юрій", "Давид",
|
|
"Анна", "Дмитрий", "Евгений", "Борис", "Ксения", "Артур", "Аполлон",
|
|
"Соломон", "Николай", "Кристи", "Надежда", "Спартак"]
|
|
|
|
/// Precompose the phonebook into one large string of comma separated names.
|
|
func phonebook(_ names: [String]) -> String {
|
|
names.map { firstName in
|
|
names.map { lastName in
|
|
firstName + " " + lastName
|
|
}.joined(separator: ", ")
|
|
}.joined(separator: ", ")
|
|
}
|
|
|
|
let longASCII = phonebook(ascii)
|
|
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()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@inline(never)
|
|
public func angryPhonebook(_ n: Int, precomposed names: String) {
|
|
for _ in 1...n {
|
|
blackHole((names.uppercased(), names.lowercased()))
|
|
}
|
|
}
|