in Sources/_TracingBenchmarkTools/DriverUtils.swift [567:636]
func run(_ test: BenchmarkInfo) -> BenchResults? {
// Before we do anything, check that we actually have a function to
// run. If we don't it is because the benchmark is not supported on
// the platform and we should skip it.
guard let testFn = test.runFunction else {
logVerbose("Skipping unsupported benchmark \(test.name)!")
return nil
}
logVerbose("Running \(test.name)")
var samples: [Int] = []
func addSample(_ time: Int) {
logVerbose(" Sample \(samples.count),\(time)")
samples.append(time)
}
resetMeasurements()
if let setUp = test.setUpFunction {
setUp()
stopMeasurement()
logVerbose(" SetUp \(lastSampleTime.microseconds)")
resetMeasurements()
}
// Determine number of iterations for testFn to run for desired time.
func iterationsPerSampleTime() -> (numIters: Int, oneIter: Int) {
let oneIter = measure(test.name, fn: testFn, numIters: 1)
if oneIter > 0 {
let timePerSample = Int(c.sampleTime * 1_000_000.0) // microseconds (μs)
return (max(timePerSample / oneIter, 1), oneIter)
} else {
return (1, oneIter)
}
}
// Determine the scale of measurements. Re-use the calibration result if
// it is just one measurement.
func calibrateMeasurements() -> Int {
let (numIters, oneIter) = iterationsPerSampleTime()
if numIters == 1 { addSample(oneIter) }
else { resetMeasurements() } // for accurate yielding reports
return numIters
}
let numIters = min( // Cap to prevent overflow on 32-bit systems when scaled
Int.max / 10000, // by the inner loop multiplier inside the `testFn`.
c.numIters ?? calibrateMeasurements()
)
let numSamples = c.numSamples ?? min(
200, // Cap the number of samples
c.numIters == nil ? 1 : calibrateMeasurements()
)
samples.reserveCapacity(numSamples)
logVerbose(" Collecting \(numSamples) samples.")
logVerbose(" Measuring with scale \(numIters).")
for _ in samples.count ..< numSamples {
addSample(measure(test.name, fn: testFn, numIters: numIters))
}
test.tearDownFunction?()
if let lf = test.legacyFactor {
logVerbose(" Applying legacy factor: \(lf)")
samples = samples.map { $0 * lf }
}
return BenchResults(samples, maxRSS: measureMemoryUsage())
}