35 个版本 (23 个稳定版)

7.5.4 2023 年 11 月 18 日
7.5.2 2022 年 9 月 18 日
7.5.0 2022 年 2 月 12 日
7.4.0 2021 年 10 月 24 日
0.1.8 2015 年 7 月 17 日

#238 in 性能分析

Download history 291582/week @ 2024-04-23 263478/week @ 2024-04-30 278877/week @ 2024-05-07 294209/week @ 2024-05-14 307514/week @ 2024-05-21 330037/week @ 2024-05-28 337480/week @ 2024-06-04 343313/week @ 2024-06-11 311386/week @ 2024-06-18 334288/week @ 2024-06-25 281332/week @ 2024-07-02 306569/week @ 2024-07-09 299253/week @ 2024-07-16 299823/week @ 2024-07-23 290954/week @ 2024-07-30 232853/week @ 2024-08-06

1,177,240 每月下载量
189 个 crate 中使用 (72 个直接使用)

MIT/Apache

320KB
4.5K SLoC

HdrHistogram_rust

Crates.io Documentation Codecov Dependency status

HdrSample 是 Gil Tene 的 HdrHistogram 的原生 Rust 版本。它提供了在大范围内以可配置的精度记录和分析样本数据值计数的功能。生成的“HDR”直方图允许快速准确地分析数据极端范围,如延迟。

HdrHistogram

以下是从 HdrHistogram 网站上的描述。建议用户阅读原始 Java 实现 的文档,因为大部分概念都直接适用于 Rust 版本。

HdrHistogram 支持在可配置的整数值范围和该范围内可配置的值精度内记录和分析样本数据值计数。值精度用记录的值的有效数字数量表示,并控制值量化行为和任何给定级别上的后续值分辨率。

例如,直方图可以配置为跟踪 0 到 3,600,000,000 之间观察到的整数值的计数,同时在该范围内保持 3 位有效数字的值精度。因此,范围内的值量化不会大于任何值的 1/1,000 (或 0.1%)。此示例直方图可以用于跟踪和分析介于 1 微秒和 1 小时之间的响应时间计数,同时保持从 1 微秒到 1 毫秒的 1 微秒分辨率,从 1 毫秒到 1 秒的 1 毫秒分辨率,以及从 1 秒到 1,000 秒的 1 秒分辨率。在其最大跟踪值(1 小时)时,它仍然保持 3.6 秒(或更好)的分辨率。

HDR直方图旨在记录延迟和性能敏感应用中的值测量直方图。测量显示,在2014年左右的现代英特尔CPU上,值记录时间低至3-6纳秒。HDR直方图在空间和时间上保持固定成本。直方图的内存占用是固定的,记录数据值或遍历它们时没有分配操作。内存占用固定,不受记录的数据值样本数量的影响,仅取决于选择的动态范围和精度。记录样本所需的工作量是恒定的,并且直接计算存储索引位置,因此在记录数据值时不需要迭代或搜索。

如果您正在寻找HdrHistogram_c的FFI绑定,请使用hdrhistogram_c存储库。

与库交互

HdrSample的API遵循原始HdrHistogram Java实现的API,并进行了一些修改,使其在Rust中使用更符合习惯。本节中的描述已根据Python移植中给出的说明进行修改,因为它比Java文档提供了更好的首次使用HdrHistogram的介绍。

HdrSample通常以两种模式之一使用:记录样本或查询分析。在分布式部署中,记录可能是在远程(可能在多个位置)执行的,然后在中央位置进行聚合分析。

记录样本

使用Histogram结构体上的::new方法创建直方图实例。这些方法有三种变体:newnew_with_maxnew_with_bounds。这些变体中的第一个仅设置样本数据的所需精度,但将值范围保持开放,以便记录任何值。以这种方式创建的Histogram(或其中已显式启用自动调整大小)将自动调整大小,如果遇到无法适应当前数据集的值,则会自动调整大小。使用new_with_max设置要记录的值的上限,并禁用自动调整大小,从而在记录过程中防止任何重新分配。如果应用程序尝试记录大于此最大界限的值,则record调用将返回错误。最后,new_with_bounds限制数据集可以表示的最小值,从而减少需要覆盖的范围(从而减少整体分配大小)。

例如,下面的示例显示了如何创建一个可以计数[1..3600000]范围内的值的Histogram,以1%的精度,这可以用于跟踪[1 毫秒..1 小时]范围内的延迟。

use hdrhistogram::Histogram;
let mut hist = Histogram::<u64>::new_with_bounds(1, 60 * 60 * 1000, 2).unwrap();

// samples can be recorded using .record, which will error if the value is too small or large
hist.record(54321).expect("value 54321 should be in range");

// for ergonomics, samples can also be recorded with +=
// this call will panic if the value is out of range!
hist += 54321;

// if the code that generates the values is subject to Coordinated Omission,
// the self-correcting record method should be used instead.
// for example, if the expected sampling interval is 10 msec:
hist.record_correct(54321, 10).expect("value 54321 should be in range");

注意u64类型。此类型可以更改以减少所有直方图分箱的存储开销,但会以增加大量样本最终落在同一分箱中的饱和风险为代价。

查询样本

在任何时候,都可以查询直方图以返回有趣的统计测量,例如记录的样本总数或给定分位数处的值。

use hdrhistogram::Histogram;
let hist = Histogram::<u64>::new(2).unwrap();
// ...
println!("# of samples: {}", hist.len());
println!("99.9'th percentile: {}", hist.value_at_quantile(0.999));

还提供了一些实用的迭代器,可以快速获取数据集概览。最简单的一个是 iter_recorded(),它为每个非空样本桶返回一个条目。所有 HdrHistogram 迭代器都在 HdrSample 中得到支持,所以请查看 Java 文档 中的 *Iterator 类。

use hdrhistogram::Histogram;
let hist = Histogram::<u64>::new(2).unwrap();
// ...
for v in hist.iter_recorded() {
    println!("{}'th percentile of data is {} with {} samples",
        v.percentile(), v.value_iterated_to(), v.count_at_value());
}

恐慌和错误处理

只要您使用的是安全、不会引发恐慌的函数(见下文),则该库永远不会引发恐慌。您遇到的任何恐慌都是错误;请在问题跟踪器中报告。

一些函数的功能通过 AddAssignSubAssign 实现。这些替代形式与简单地调用正常函数上的 unwrap() 相当,因此适用于 unwrap() 的正常规则:在生产代码中使用时,请怀疑其用途等。

返回 Result 在错误时引发恐慌 功能
h.record(v) h+=v 为值 v 增加计数
h.add(h2) h+=h2 h2 的计数添加到 h
h.subtract(h2) h-=h2 h 中减去 h2 的计数

除了上述函数的恐慌形式外,其他所有操作如果可能失败,将返回 ResultOption

usize 限制

根据配置的有效数字数量和最大值,直方图的内部存储可能包含数十万个单元格。具有 16 位 usize 的系统无法表示如此大的指针偏移,因此相关操作(创建、反序列化等)将因适当的错误而失败(例如,CreationError::UsizeTypeTooSmall)。如果您使用的是此类系统并且遇到这些错误,则减少有效数字的数量将大大减少内存消耗(因此减少对大 usize 值的需求)。只要禁用调整大小,降低最大值也可能有所帮助。

32 位及以上的系统将不会出现此类问题,因为所有可能的直方图都适合 32 位索引。

浮点数精度

一些计算固有地涉及浮点值,例如 value_at_quantile,因此受 IEEE754 浮点计算的精度限制。用户可见的后果是,在特定情况下,您可能会得到一个比使用任意精度算术进行计算时更高的桶(因此是值)。但是,双精度 IEEE754(即 f64)非常擅长其工作,所以这些情况应该很少见。此外,我们尚未看到偏差超过一个桶的情况。

为了最小化假阳性(FP)的精度损失,我们更倾向于使用分位数而不是百分位数。分位数表示集合中的一个部分,用 [0, 1] 中的数字来表示。百分位数与分位数概念相同,但它使用的是范围 [0, 100]。仅使用分位数意味着我们可以在几个地方跳过一个FP操作,从而避免精度损失的机会。

限制和注意事项

与其他所有HdrHistogram端口一样,此端口可能无法提供上游HdrHistogram实现中的最新功能和错误修复。也有一些功能尚未(尚未)实现

  • 并发支持(《AtomicHistogram》,《ConcurrentHistogram》,……)。
  • DoubleHistogram.
  • HdrHistogram的《Recorder》功能。
  • 值移位(“归一化”)。
  • 文本输出方法。这些似乎几乎与HdrSample正交,尽管如果我们实现了相关特性(CSV、JSON以及可能简单的《fmt::Display》)可能会方便一些。

这些功能中的大多数应该相当简单易懂,因为代码与原始Java/C#代码相当吻合。如果您决定实现其中之一并发送PR,请确保您还移植了测试用例,并尽可能实现适当的特性,以使功能的用法尽可能方便。

用法

将此添加到您的《Cargo.toml》中

[dependencies]
hdrhistogram = "7"

并将此添加到您的crate根目录

extern crate hdrhistogram;

许可

双许可,与Rust项目兼容。

根据您的要求,在Apache License,版本2.0 http://apache.ac.cn/licenses/LICENSE2.0 或MIT许可证 http://opensource.org/licenses/MIT 下许可。此文件不得复制、修改或分发,除非根据这些条款。

依赖关系

~175–700KB
~12K SLoC