Skip to content

Commit f890cfb

Browse files
authored
Merge pull request #25309 from Armenm/SR-10855-non-ascii-angryphonebook
[benchmark] SR-10855: Added non-ASCII characters to String benchmarking
2 parents 06fd9c4 + 6c97101 commit f890cfb

File tree

1 file changed

+117
-5
lines changed

1 file changed

+117
-5
lines changed

benchmark/single-source/AngryPhonebook.swift

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,59 @@
1414
// to test uppercase and lowercase ASCII string fast paths.
1515
import TestsUtils
1616

17-
public let AngryPhonebook = BenchmarkInfo(
18-
name: "AngryPhonebook",
19-
runFunction: run_AngryPhonebook,
20-
tags: [.validation, .api, .String],
21-
legacyFactor: 7)
17+
let t: [BenchmarkCategory] = [.validation, .api, .String]
18+
19+
public let AngryPhonebook = [
20+
BenchmarkInfo(
21+
name: "AngryPhonebook",
22+
runFunction: run_AngryPhonebook,
23+
tags: t,
24+
legacyFactor: 7),
25+
26+
// Small String Workloads
27+
BenchmarkInfo(
28+
name: "AngryPhonebook.ASCII.Small",
29+
runFunction: { angryPhonebook($0, ascii) },
30+
tags: t,
31+
setUpFunction: { blackHole(ascii) }),
32+
BenchmarkInfo(
33+
name: "AngryPhonebook.Strasse.Small",
34+
runFunction: { angryPhonebook($0, strasse) },
35+
tags: t,
36+
setUpFunction: { blackHole(strasse) }),
37+
BenchmarkInfo(
38+
name: "AngryPhonebook.Armenian.Small",
39+
runFunction: { angryPhonebook($0, armenian) },
40+
tags: t,
41+
setUpFunction: { blackHole(armenian) }),
42+
BenchmarkInfo(
43+
name: "AngryPhonebook.Cyrillic.Small",
44+
runFunction: { angryPhonebook($0, cyrillic) },
45+
tags: t,
46+
setUpFunction: { blackHole(cyrillic) }),
47+
48+
// Regular String Workloads
49+
BenchmarkInfo(
50+
name: "AngryPhonebook.ASCII",
51+
runFunction: { angryPhonebook($0, precomposed: longASCII) },
52+
tags: t,
53+
setUpFunction: { blackHole(longASCII) }),
54+
BenchmarkInfo(
55+
name: "AngryPhonebook.Strasse",
56+
runFunction: { angryPhonebook($0, precomposed: longStrasse) },
57+
tags: t,
58+
setUpFunction: { blackHole(longStrasse) }),
59+
BenchmarkInfo(
60+
name: "AngryPhonebook.Armenian",
61+
runFunction: { angryPhonebook($0, precomposed: longArmenian) },
62+
tags: t,
63+
setUpFunction: { blackHole(longArmenian) }),
64+
BenchmarkInfo(
65+
name: "AngryPhonebook.Cyrillic",
66+
runFunction: { angryPhonebook($0, precomposed: longCyrillic) },
67+
tags: t,
68+
setUpFunction: { blackHole(longCyrillic) })
69+
]
2270

2371
let words = [
2472
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph",
@@ -38,3 +86,67 @@ public func run_AngryPhonebook(_ N: Int) {
3886
}
3987
}
4088
}
89+
90+
// Workloads for various scripts. Always 20 names for 400 pairings.
91+
// To keep the performance of various scripts roughly comparable, aim for
92+
// a total length of approximately 120 characters.
93+
// E.g.: `ascii.joined(separator: "").count == 124`
94+
// Every name should fit in 15-bytes UTF-8 encoded, to excercise the small
95+
// string optimization.
96+
// E.g.: `armenian.allSatisfy { $0._guts.isSmall } == true`
97+
98+
// Workload Size Statistics
99+
// SMALL | UTF-8 | UTF-16 | REGULAR | UTF-8 | UTF-16
100+
// ---------|-------|--------|--------------|---------|--------
101+
// ascii | 124 B | 248 B | longASCII | 6158 B | 12316 B
102+
// strasse | 140 B | 240 B | longStrasse | 6798 B | 11996 B
103+
// armenian | 232 B | 232 B | longArmenian | 10478 B | 11676 B
104+
// cyrillic | 238 B | 238 B | longCyrillic | 10718 B | 11916 B
105+
106+
let ascii = Array(words.prefix(20))
107+
// Pathological case, uppercase: ß -> SS
108+
let strasse = Array(repeating: "Straße", count: 20)
109+
110+
let armenian = [
111+
"Արմեն", "Աննա", "Հարութ", "Միքայել", "Մարիա", "Դավիթ", "Վարդան",
112+
"Նարինե", "Տիգրան", "Տաթևիկ", "Թագուհի", "Թամարա", "Ազնաուր", "Գրիգոր",
113+
"Կոմիտաս", "Հայկ", "Գառնիկ", "Վահրամ", "Վահագն", "Գևորգ"]
114+
115+
let cyrillic = [
116+
"Ульяна", "Аркадий", "Аня", "Даниил", "Дмитрий", "Эдуард", "Юрій", "Давид",
117+
"Анна", "Дмитрий", "Евгений", "Борис", "Ксения", "Артур", "Аполлон",
118+
"Соломон", "Николай", "Кристи", "Надежда", "Спартак"]
119+
120+
/// Precompose the phonebook into one large string of comma separated names.
121+
func phonebook(_ names: [String]) -> String {
122+
names.map { firstName in
123+
names.map { lastName in
124+
firstName + " " + lastName
125+
}.joined(separator: ", ")
126+
}.joined(separator: ", ")
127+
}
128+
129+
let longASCII = phonebook(ascii)
130+
let longStrasse = phonebook(strasse)
131+
let longArmenian = phonebook(armenian)
132+
let longCyrillic = phonebook(cyrillic)
133+
134+
@inline(never)
135+
public func angryPhonebook(_ N: Int, _ names: [String]) {
136+
assert(names.count == 20)
137+
// Permute the names.
138+
for _ in 1...N {
139+
for firstname in names {
140+
for lastname in names {
141+
blackHole((firstname.uppercased(), lastname.lowercased()))
142+
}
143+
}
144+
}
145+
}
146+
147+
@inline(never)
148+
public func angryPhonebook(_ N: Int, precomposed names: String) {
149+
for _ in 1...N {
150+
blackHole((names.uppercased(), names.lowercased()))
151+
}
152+
}

0 commit comments

Comments
 (0)