15 个版本 (4 个稳定版)
2.1.1 | 2023 年 12 月 21 日 |
---|---|
2.0.0 | 2023 年 12 月 21 日 |
1.0.0 | 2021 年 3 月 4 日 |
0.1.7 | 2021 年 3 月 4 日 |
0.1.6 | 2018 年 12 月 12 日 |
在 性能分析 中排名第 316
每月下载 45 次
35KB
433 行代码(不含注释)
histlog
提供将 HdrHistogram 时间间隔日志离线程序列化到文件的功能。
对于与 hdrhistogram
crate 一起使用,这是一个 Rust 版本的 Gil Tene 的 HdrHistogram,它提供了一个干净且合理的默认设置,用于离线程序列化 HdrHistogram 时间间隔日志到文件。
用途
HdrHistogram 常用于测量延迟。通常,如果您想测量延迟,则不太可能希望在同一线程上写入文件。
一个选项是将序列化到内存缓冲区中(例如 Vec<u8>
)。但是,这仍然需要在缓冲区中分配内存,并且对于长时间运行的进程最终需要大量的内存。
histlog::HistLog
允许热线程定期将其 hdrhistogram::Histogram
传递给指定的写入线程,该线程可以处理 IO 操作。时间间隔日志是增量写入的,并且在程序仍在运行时可以进行审查和分析。
HistLog
完全依赖于 hdrhistogram
crate,无论是内存中记录值还是序列化。它提供的功能是离线程写入,具有干净的用户界面和合理的默认设置,使得使用相对容易。
示例
一个 HistLog
有一个 "series" 名称和一个 "tag"。HdrHistogram 区间日志格式为每个条目提供一个 tag。系列名称用于命名写入的区间日志文件。
use std::time::*;
let log_dir = "/tmp/path/to/logs";
let series = "server-latency"; // used to name the log file
let tag = "xeon-e7-8891-v2"; // recorded with each entry
let freq = Duration::from_secs(1); // how often results sent to writer thread
// `HistLog::new` could fail creating file, `hdrhistogram::Histogram`
let mut server1 = histlog::HistLog::new(log_dir, series, tag, freq).unwrap();
// use `HistLog::clone_with_tag` to serialize a separate tag to same file.
let mut server2 = server1.clone_with_tag("xeon-e5-2670");
for i in 0..1000u64 { // dummy data
server1.record(i).unwrap(); // call to `hdrhistogram::Histogram::record` could fail
server2.record(i * 2).unwrap();
}
assert_eq!(server1.path(), server2.path()); // both being saved to same file, via same writer thread
HistLog
的 API 设计是针对事件循环的。循环的每次迭代都会记录新的值,并检查当前时间以确定当前 Histogram
是否应该传递给写线程。
use std::time::*;
let mut spintime = histlog::HistLog::new("/tmp/var/hist", "spintime", "main", Duration::from_secs(60)).unwrap();
let mut loop_time = Instant::now();
let mut prev: Instant;
loop {
prev = loop_time;
loop_time = Instant::now();
spintime.record(histlog::nanos(loop_time - prev)).unwrap(); // nanos: Duration -> u64
spintime.check_send(loop_time); // sends to writer thread if elapsed > freq,
// or...
spintime.check_try_send(loop_time).unwrap(); // non-blocking equivalent (can fail)
// do important stuff ...
}
日志
日志保存在 <log dir>/<series name>.<datetime>.hdrhistogram-interval-log.v2.gz
。
日志的格式如下
#[StartTime: 1544631293.283 (seconds since epoch)]
#[BaseTime: 0.000 (seconds since epoch)]
Tag=xeon-e7-8891-v2,1544631293.283,0.003,999.000,HISTFAAAAC94Ae3GMRUAMAgD0bRI6FovNVcHmGREAgNR [...]
Tag=xeon-e5-2670,1544631293.283,0.003,999.000,HISTFAAAABx4AZNpmSzMwMDAxAABzFCaEUoz2X+AsQA/awK [...]
[...]
只有直方图数据被压缩(deflate),因此 .gz
扩展名可能有些误导。
日志文件可以在此处查看/分析 这里(javascript,本地运行)或使用基于 Java 的 HistogramLogAnalyzer。
日志序列化的完整文档 可在 hdrhistogram
包中找到。
功能
minstant
:用minstant::Instant
替换std::time::Instant
,它通常更快,并且是一个具有相同 API 的直接替换。smol_str
:将smol_str::SmolStr
用于系列名称(SeriesName
类型别名)和 tag(Tag
类型别名)的类型。SmolStr
允许动态字符串,且无需堆分配,大小可达一定限制,因此该功能使系列名称和 tag 值都可以是动态的。
限制
HistLog::check_send
和HistLog::check_try_send
在每个区间创建一个新的hdrhistogram::Histogram
,并将当前/上一个发送到写线程。内部,一个hdrhistogram::Histogram
使用一个Vec
来存储其计数,因此涉及到分配。- 只能记录
u64
值(请参阅C
类型别名)。
依赖项
~4MB
~74K SLoC