diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f9dbee3..3b6f3e3 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -19,6 +19,12 @@ jobs: linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable" + benchmarks: + name: Benchmarks + uses: apple/swift-nio/.github/workflows/benchmarks.yml@main + with: + benchmark_package_path: "Benchmarks" + cxx-interop: name: Cxx interop uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main diff --git a/Benchmarks/.gitignore b/Benchmarks/.gitignore new file mode 100644 index 0000000..d3ff854 --- /dev/null +++ b/Benchmarks/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +.build +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc +.benchmarkBaselines/ diff --git a/Benchmarks/Benchmarks/PrometheusBenchmarks/Benchmarks.swift b/Benchmarks/Benchmarks/PrometheusBenchmarks/Benchmarks.swift new file mode 100644 index 0000000..f4e2afd --- /dev/null +++ b/Benchmarks/Benchmarks/PrometheusBenchmarks/Benchmarks.swift @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftPrometheus open source project +// +// Copyright (c) 2018-2023 SwiftPrometheus project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Benchmark +import Foundation +import Prometheus + +let registry = PrometheusCollectorRegistry() + +public func makeLabels(_ idx: Int) -> [(String, String)] { + [ + ("job", "api_server_\(idx)"), + ("handler", "/api/handler_\(idx)"), + ("status_code", "200"), + ("version", "\(idx).0.0"), + ] +} + +let benchmarks = { + let ciMetrics: [BenchmarkMetric] = [ + .mallocCountTotal, + ] + let localMetrics = BenchmarkMetric.default + + Benchmark.defaultConfiguration = .init( + metrics: ProcessInfo.processInfo.environment["CI"] != nil ? ciMetrics : localMetrics, + warmupIterations: 10, + scalingFactor: .kilo, + maxDuration: .seconds(5), + ) + + Benchmark("Counter - setup and increment") { benchmark in + runCounterBench(benchmark.scaledIterations) + } + + Benchmark("Counter - increment only") { benchmark, run in + for _ in benchmark.scaledIterations { + run() + } + } setup: { + setupCounterBench() + } + + Benchmark("Gauge") { benchmark in + runGaugeBench(benchmark.scaledIterations) + } + + Benchmark("DurationHistogram") { benchmark in + runDurationHistogramBench(benchmark.scaledIterations) + } + + Benchmark("RegistryEmit - 5000 metrics", + configuration: .init(scalingFactor: .one)) + { benchmark, run in + for _ in benchmark.scaledIterations { + run() + } + } setup: { + setupRegistryExport(numberOfMetrics: 5000) + } +} diff --git a/Benchmarks/Benchmarks/PrometheusBenchmarks/Counter.swift b/Benchmarks/Benchmarks/PrometheusBenchmarks/Counter.swift new file mode 100644 index 0000000..4e5493a --- /dev/null +++ b/Benchmarks/Benchmarks/PrometheusBenchmarks/Counter.swift @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftPrometheus open source project +// +// Copyright (c) 2018-2023 SwiftPrometheus project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Benchmark +import Prometheus + +public func runCounterBench(_ iterations: Range) { + let ctr = registry.makeCounter(name: "counter_1", labels: makeLabels(1)) + for _ in iterations { + blackHole(ctr.increment()) + } +} + +public func setupCounterBench() -> () -> Void { + let ctr = registry.makeCounter(name: "counter_2", labels: makeLabels(2)) + return { + blackHole(ctr.increment()) + } +} diff --git a/Benchmarks/Benchmarks/PrometheusBenchmarks/DurationHistogram.swift b/Benchmarks/Benchmarks/PrometheusBenchmarks/DurationHistogram.swift new file mode 100644 index 0000000..c6de28a --- /dev/null +++ b/Benchmarks/Benchmarks/PrometheusBenchmarks/DurationHistogram.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftPrometheus open source project +// +// Copyright (c) 2018-2023 SwiftPrometheus project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Benchmark +import Prometheus + +public func runDurationHistogramBench(_ iterations: Range) { + let histogram = registry.makeDurationHistogram( + name: "histogram_1", + labels: makeLabels(3), + buckets: [ + .milliseconds(100), + .milliseconds(250), + .milliseconds(500), + .seconds(1), + ] + ) + for _ in iterations { + blackHole(histogram.record(Duration.milliseconds(400))) + } +} diff --git a/Benchmarks/Benchmarks/PrometheusBenchmarks/Gauge.swift b/Benchmarks/Benchmarks/PrometheusBenchmarks/Gauge.swift new file mode 100644 index 0000000..6c8be83 --- /dev/null +++ b/Benchmarks/Benchmarks/PrometheusBenchmarks/Gauge.swift @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftPrometheus open source project +// +// Copyright (c) 2018-2023 SwiftPrometheus project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Benchmark +import Prometheus + +public func runGaugeBench(_ iterations: Range) { + let gauge = registry.makeGauge(name: "gauge_1", labels: makeLabels(2)) + for _ in iterations { + blackHole(gauge.increment()) + } +} + +public func setupGaugeBench() -> () -> Void { + let gauge = registry.makeGauge(name: "gauge_1", labels: makeLabels(2)) + return { + blackHole(gauge.increment()) + } +} diff --git a/Benchmarks/Benchmarks/PrometheusBenchmarks/RegistryEmit.swift b/Benchmarks/Benchmarks/PrometheusBenchmarks/RegistryEmit.swift new file mode 100644 index 0000000..0a13345 --- /dev/null +++ b/Benchmarks/Benchmarks/PrometheusBenchmarks/RegistryEmit.swift @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftPrometheus open source project +// +// Copyright (c) 2018-2023 SwiftPrometheus project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Benchmark +import Prometheus + +public func setupRegistryExport(numberOfMetrics: Int) -> () -> Void { + let registryExport = PrometheusCollectorRegistry() + + var counterArray = [Counter]() + var gaugeArray = [Gauge]() + var buffer = [UInt8]() + + let counterExportSize = 620_000 + counterArray.reserveCapacity(numberOfMetrics) + gaugeArray.reserveCapacity(numberOfMetrics) + buffer.reserveCapacity(counterExportSize) + + for i in 0 ..< (numberOfMetrics / 2) { + let counter = registryExport.makeCounter(name: "http_requests_total", labels: makeLabels(i)) + counter.increment() + counterArray.append(counter) + + let gauge = registryExport.makeGauge(name: "export_gauge_\(i)", labels: makeLabels(i)) + gauge.increment() + gaugeArray.append(gauge) + } + return { + blackHole(registryExport.emit(into: &buffer)) + } +} diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift new file mode 100644 index 0000000..809706b --- /dev/null +++ b/Benchmarks/Package.swift @@ -0,0 +1,40 @@ +// swift-tools-version:5.9 +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftPrometheus open source project +// +// Copyright (c) 2018-2023 SwiftPrometheus project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftPrometheus project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import PackageDescription + +let package = Package( + name: "benchmarks", + platforms: [ + .macOS(.v13), + ], + dependencies: [ + .package(path: "../"), + .package(url: "https://github.com/ordo-one/package-benchmark.git", from: "1.29.0"), + ], + targets: [ + .executableTarget( + name: "PrometheusBenchmarks", + dependencies: [ + .product(name: "Benchmark", package: "package-benchmark"), + .product(name: "Prometheus", package: "swift-prometheus"), + ], + path: "Benchmarks/PrometheusBenchmarks", + plugins: [ + .plugin(name: "BenchmarkPlugin", package: "package-benchmark"), + ] + ), + ] +) diff --git a/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Counter_-_increment_only.p90.json b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Counter_-_increment_only.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Counter_-_increment_only.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.DurationHistogram.p90.json b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.DurationHistogram.p90.json new file mode 100644 index 0000000..282dc64 --- /dev/null +++ b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.DurationHistogram.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 2 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Gauge.p90.json b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Gauge.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.Gauge.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/5.10/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Counter_-_increment_only.p90.json b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Counter_-_increment_only.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Counter_-_increment_only.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.DurationHistogram.p90.json b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.DurationHistogram.p90.json new file mode 100644 index 0000000..282dc64 --- /dev/null +++ b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.DurationHistogram.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 2 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Gauge.p90.json b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Gauge.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.Gauge.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/6.0/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Counter_-_increment_only.p90.json b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Counter_-_increment_only.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Counter_-_increment_only.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.DurationHistogram.p90.json b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.DurationHistogram.p90.json new file mode 100644 index 0000000..282dc64 --- /dev/null +++ b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.DurationHistogram.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 2 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Gauge.p90.json b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Gauge.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.Gauge.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/6.1/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Counter_-_increment_only.p90.json b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Counter_-_increment_only.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Counter_-_increment_only.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.DurationHistogram.p90.json b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.DurationHistogram.p90.json new file mode 100644 index 0000000..282dc64 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.DurationHistogram.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 2 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Gauge.p90.json b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Gauge.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.Gauge.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-main/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Counter_-_increment_only.p90.json b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Counter_-_increment_only.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Counter_-_increment_only.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Counter_-_setup_and_increment.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.DurationHistogram.p90.json b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.DurationHistogram.p90.json new file mode 100644 index 0000000..282dc64 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.DurationHistogram.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 2 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Gauge.p90.json b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Gauge.p90.json new file mode 100644 index 0000000..557fc88 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.Gauge.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 1 +} \ No newline at end of file diff --git a/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json new file mode 100644 index 0000000..9f9de44 --- /dev/null +++ b/Benchmarks/Thresholds/nightly-next/PrometheusBenchmarks.RegistryEmit_-_5000_metrics.p90.json @@ -0,0 +1,3 @@ +{ + "mallocCountTotal" : 0 +} \ No newline at end of file diff --git a/README.md b/README.md index 7aab78a..195418b 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,17 @@ If you find a bug or have issues, please [create an issue](https://github.com/sw [Documentation]: https://swiftpackageindex.com/swift-server/swift-prometheus/documentation/prometheus [SSWG-Incubation]: https://www.swift.org/sswg/incubation-process.html + + +## Benchmarks + +Benchmarks for `swift-prometheus` are in a separate Swift Package in the `Benchmarks` subfolder of this repository. +They use the [`package-benchmark`](https://github.com/ordo-one/package-benchmark) plugin. +Benchmarks depends on the [`jemalloc`](https://jemalloc.net) memory allocation library, which is used by `package-benchmark` to capture memory allocation statistics. +An installation guide can be found in the [Getting Started article](https://swiftpackageindex.com/ordo-one/package-benchmark/documentation/benchmark/gettingstarted#Installing-Prerequisites-and-Platform-Support) of `package-benchmark`. +Afterwards you can run the benchmarks from CLI by going to the `Benchmarks` subfolder (e.g. `cd Benchmarks`) and invoking: +``` +swift package benchmark +``` + +For more information please refer to `swift package benchmark --help` or the [documentation of `package-benchmark`](https://swiftpackageindex.com/ordo-one/package-benchmark/documentation/benchmark).