直方图是 Gil Tene 的 High Dynamic Range (HDR) Histogram 到原生 Swift 的端口。它提供了对大型可配置值范围内采样数据值计数的记录和分析,并在该范围内具有可配置的精度。生成的 “HDR” 直方图可以对具有非正态分布(如延迟)的数据的极端范围进行快速而准确的分析。
直方图支持对可配置整数值范围内采样数据值计数的记录和分析,并在该范围内具有可配置的值精度。值精度表示为值记录中的有效位数,并提供对值范围内的值量化行为以及任何给定级别上的后续值分辨率的控制。
例如,一个直方图可以配置为跟踪 0 到 3,600,000,000 之间观察到的整数值的计数,同时在该范围内保持 3 位有效值精度。因此,范围内的值量化将不大于任何值的 1/1,000(或 0.1%)。
此示例直方图可用于跟踪和分析幅度在 1 微秒到 1 小时之间的观测响应时间的计数,同时保持高达 1 毫秒的 1 微秒值分辨率、高达 1 秒的 1 毫秒(或更好)分辨率以及高达 1,000 秒的 1 秒(或更好)分辨率。在其最大跟踪值(1 小时)时,它仍将保持 3.6 秒(或更好)的分辨率。
直方图专为记录延迟和性能敏感型应用中的值测量直方图而设计。
测量显示在 Apple Silicon CPU (M1) 上,值记录时间低至 3-4 纳秒。
直方图在空间和时间上都保持固定的成本。直方图的内存占用是恒定的,记录数据值或迭代数据值都不涉及分配操作。
内存占用是固定的,与记录的数据值样本的数量无关,并且仅取决于选择的动态范围和精度。记录样本所涉及的工作量是恒定的,并且直接计算存储索引位置,以便在记录数据值时永远不会涉及迭代或搜索。
此端口包含 Java 实现支持的功能子集。
当前支持的功能有
鼓励用户阅读原始 Java 实现 的文档,因为大多数概念直接转换为 Swift 端口。 另外感谢 Rust 端口的维护者,感谢他们对我们大量借鉴的软件包进行了很好的介绍。
添加到你的项目
dependencies: [
.package(url: "https://github.com/HdrHistogram/hdrhistogram-swift", .upToNextMajor(from: "0.1.0"))
]
然后将依赖项添加到你的目标,例如
.executableTarget(
name: "MyExecutableTarget",
dependencies: [
.product(name: "Histogram", package: "hdrhistogram-swift")
]),
直方图 API 遵循原始 HdrHistogram Java 实现的 API,并进行了一些修改,使其在 Swift 中的使用更加符合语言习惯。
类和 API 的文档 由 SwiftPackageIndex 托管
(请参阅 Sources/HistogramExample 中的实现)
import Histogram
let maxValue: UInt64 = 3_600_000_000 // e.g. for 1 hr in usec units
var histogram = Histogram<UInt64>(highestTrackableValue: maxValue, numberOfSignificantValueDigits: .three)
// record some random values
for _ in 1...100 {
histogram.record(UInt64.random(in: 10...1000))
}
// record value n times
histogram.record(UInt64.random(in: 50...200), count: 10)
// record value with correction for co-ordinated omission
histogram.recordCorrectedValue(1_000, expectedInterval: 100)
// iterate using percentile iterator
for pv in histogram.percentiles(ticksPerHalfDistance: 1) {
print("Percentile: \(pv.percentile), Value: \(pv.value)")
}
print(String(repeating: "-", count: 80))
// print values for interesting percentiles
let percentiles = [ 0.0, 50.0, 80.0, 95.0, 99.0, 99.9, 99.99, 99.999, 100.0 ]
for p in percentiles {
print("Percentile: \(p), Value: \(histogram.valueAtPercentile(p))")
}
print(String(repeating: "-", count: 80))
// general stats
print("min: \(histogram.min)")
print("max: \(histogram.max)")
print("mean: \(histogram.mean)")
print("stddev: \(histogram.stdDeviation)")
print("\(histogram)")