14
14
// to test uppercase and lowercase ASCII string fast paths.
15
15
import TestsUtils
16
16
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
+ ]
22
70
23
71
let words = [
24
72
" James " , " John " , " Robert " , " Michael " , " William " , " David " , " Richard " , " Joseph " ,
@@ -38,3 +86,67 @@ public func run_AngryPhonebook(_ N: Int) {
38
86
}
39
87
}
40
88
}
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