Skip to content

Commit 8e0ef8b

Browse files
authored
Make time formatter produce uniform decimals (#81)
1 parent 7663e48 commit 8e0ef8b

File tree

4 files changed

+58
-38
lines changed

4 files changed

+58
-38
lines changed

Sources/Benchmark/BenchmarkColumn.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public struct BenchmarkColumn: Hashable {
6464
case .inverseTime:
6565
self.formatter = BenchmarkFormatter.inverseTime
6666
case .none:
67-
self.formatter = BenchmarkFormatter.number
67+
self.formatter = BenchmarkFormatter.real
6868
}
6969
}
7070
}
@@ -98,7 +98,8 @@ public struct BenchmarkColumn: Hashable {
9898
formatter: BenchmarkFormatter.stdPercentage)
9999
result["iterations"] = BenchmarkColumn(
100100
name: "iterations",
101-
value: { Double($0.measurements.count) })
101+
value: { Double($0.measurements.count) },
102+
formatter: BenchmarkFormatter.integer)
102103
result["warmup"] = BenchmarkColumn(
103104
name: "warmup",
104105
value: { $0.warmupMeasurements.sum },
@@ -208,7 +209,8 @@ public struct BenchmarkColumn: Hashable {
208209
return 0
209210
}
210211
},
211-
alignment: .right))
212+
alignment: .right,
213+
formatter: BenchmarkFormatter.integer))
212214
}
213215

214216
return columns

Sources/Benchmark/BenchmarkFormatter.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@
1616
public enum BenchmarkFormatter {
1717
public typealias Formatter = (Double, BenchmarkSettings) -> String
1818

19-
/// Just show a number, stripping ".0" if it's integer.
20-
public static let number: Formatter = { (value, settings) in
21-
let string = String(value)
22-
if string.hasSuffix(".0") {
23-
return String(string.dropLast(2))
24-
} else {
25-
return String(format: "%.3f", value)
26-
}
19+
/// Show an integer number without decimals.
20+
public static let integer: Formatter = { (value, settings) in
21+
return String(format: "%.0f", value)
22+
}
23+
24+
/// Show a real number with decimals.
25+
public static let real: Formatter = { (value, settings) in
26+
return String(format: "%.3f", value)
2727
}
2828

2929
/// Show number with the corresponding time unit.
3030
public static let time: Formatter = { (value, settings) in
31-
let num = number(value, settings)
31+
let num = real(value, settings)
3232
return "\(num) \(settings.timeUnit)"
3333
}
3434

3535
/// Show number with the corresponding inverse time unit.
3636
public static let inverseTime: Formatter = { (value, settings) in
37-
let num = number(value, settings)
37+
let num = real(value, settings)
3838
return "\(num) /\(settings.inverseTimeUnit)"
3939
}
4040

@@ -45,7 +45,7 @@ public enum BenchmarkFormatter {
4545

4646
/// Show value as plus or minus standard deviation.
4747
public static let std: Formatter = { (value, settings) in
48-
let num = number(value, settings)
48+
let num = real(value, settings)
4949
return "± \(num)"
5050
}
5151

Sources/Benchmark/BenchmarkSetting.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,24 @@ public struct TimeUnit: BenchmarkSetting {
7777
public init(_ value: Value) {
7878
self.value = value
7979
}
80-
public enum Value: String, ExpressibleByArgument {
80+
public enum Value: String, ExpressibleByArgument, CustomStringConvertible {
8181
case ns
8282
case us
8383
case ms
8484
case s
85+
86+
public var description: String {
87+
switch self {
88+
case .ns:
89+
return "ns"
90+
case .us:
91+
return "us"
92+
case .ms:
93+
return "ms"
94+
case .s:
95+
return " s"
96+
}
97+
}
8598
}
8699
}
87100

Tests/BenchmarkTests/BenchmarkReporterTests.swift

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,18 @@ final class BenchmarkReporterTests: XCTestCase {
6363
file: StaticString = #filePath,
6464
line: UInt = #line
6565
) {
66+
func trimmingTrailingWhitespace(_ string: String) -> String {
67+
String(string.reversed().drop(while: { $0.isWhitespace }).reversed())
68+
}
6669
let lines = Array(got.split(separator: "\n").map { String($0) })
6770
let expectedLines = expected.split(separator: "\n").map { String($0) }
6871
let actual = lines.map { $0.trimmingCharacters(in: .newlines) }
6972
.filter { !$0.isEmpty }
7073
XCTAssertEqual(expectedLines.count, actual.count, message(), file: file, line: line)
7174
for (expectedLine, actualLine) in zip(expectedLines, actual) {
72-
XCTAssertEqual(expectedLine, actualLine, message(), file: file, line: line)
75+
let trimmedExpectedLine = trimmingTrailingWhitespace(expectedLine)
76+
let trimmedActualLine = trimmingTrailingWhitespace(actualLine)
77+
XCTAssertEqual(trimmedExpectedLine, trimmedActualLine, message(), file: file, line: line)
7378
}
7479
}
7580

@@ -89,10 +94,10 @@ final class BenchmarkReporterTests: XCTestCase {
8994
counters: [:]),
9095
]
9196
let expected = #"""
92-
name time std iterations
93-
---------------------------------------------
94-
MySuite.fast 1500 ns ± 47.14 % 2
95-
MySuite.slow 1500000 ns ± 47.14 % 2
97+
name time std iterations
98+
-------------------------------------------------
99+
MySuite.fast 1500.000 ns ± 47.14 % 2
100+
MySuite.slow 1500000.000 ns ± 47.14 % 2
96101
"""#
97102
assertConsoleReported(results, expected)
98103
}
@@ -113,10 +118,10 @@ final class BenchmarkReporterTests: XCTestCase {
113118
counters: [:]),
114119
]
115120
let expected = #"""
116-
name time std iterations foo
117-
-------------------------------------------------
118-
MySuite.fast 1500 ns ± 47.14 % 2 7
119-
MySuite.slow 1500000 ns ± 47.14 % 2 0
121+
name time std iterations foo
122+
-----------------------------------------------------
123+
MySuite.fast 1500.000 ns ± 47.14 % 2 7
124+
MySuite.slow 1500000.000 ns ± 47.14 % 2 0
120125
"""#
121126
assertConsoleReported(results, expected)
122127
}
@@ -137,10 +142,10 @@ final class BenchmarkReporterTests: XCTestCase {
137142
counters: [:]),
138143
]
139144
let expected = #"""
140-
name time std iterations warmup
141-
----------------------------------------------------
142-
MySuite.fast 1500 ns ± 47.14 % 2 60 ns
143-
MySuite.slow 1500000 ns ± 47.14 % 2 0 ns
145+
name time std iterations warmup
146+
-----------------------------------------------------------
147+
MySuite.fast 1500.000 ns ± 47.14 % 2 60.000 ns
148+
MySuite.slow 1500000.000 ns ± 47.14 % 2 0.000 ns
144149
"""#
145150
assertConsoleReported(results, expected)
146151
}
@@ -173,12 +178,12 @@ final class BenchmarkReporterTests: XCTestCase {
173178
counters: [:]),
174179
]
175180
let expected = #"""
176-
name time std iterations
177-
----------------------------------------------
178-
MySuite.ns 123456789 ns ± 0.00 % 1
179-
MySuite.us 123456.789 us ± 0.00 % 1
180-
MySuite.ms 123.457 ms ± 0.00 % 1
181-
MySuite.s 0.123 s ± 0.00 % 1
181+
name time std iterations
182+
-------------------------------------------------
183+
MySuite.ns 123456789.000 ns ± 0.00 % 1
184+
MySuite.us 123456.789 us ± 0.00 % 1
185+
MySuite.ms 123.457 ms ± 0.00 % 1
186+
MySuite.s 0.123 s ± 0.00 % 1
182187
"""#
183188
assertConsoleReported(results, expected)
184189
}
@@ -199,10 +204,10 @@ final class BenchmarkReporterTests: XCTestCase {
199204
counters: [:]),
200205
]
201206
let expected = #"""
202-
name min max
203-
-------------------------------
204-
MySuite.fast 1000 ns
205-
MySuite.slow 2000000 ns
207+
name min max
208+
---------------------------------------
209+
MySuite.fast 1000.000 ns
210+
MySuite.slow 2000000.000 ns
206211
"""#
207212
assertConsoleReported(results, expected)
208213
}

0 commit comments

Comments
 (0)