Neon Pageserver 基准测试完全指南:从运行命令到 LayerMap / Ingest / Walredo 实现解读

发布时间:2026/9/13 4:07:29
Neon Pageserver 基准测试完全指南:从运行命令到 LayerMap / Ingest / Walredo 实现解读 Neon Pageserver 基准测试完全指南从运行命令到 LayerMap / Ingest / Walredo 实现解读【免费下载链接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.项目地址: https://gitcode.com/GitHub_Trending/ne/neon本指南以 pageserver/benches/README.md 为骨架系统介绍 Neon 存储引擎Pageserver自带基准测试套件的运行方法与实现原理。你会掌握cargo bench的三级过滤用法、5 个基准测试各自测量的性能维度与参数设计并通过源码级分析理解 LayerMap 查询、批量写入Ingest、WAL 重放Walredo、指标统计与上传队列等核心路径的性能特征。读完即可复现并解读 Pageserver 的关键性能指标。基准测试套件一览Neon Pageserver 的基准测试全部位于 pageserver/benches/ 目录基于 Rust 生态的事实标准Criterion框架编写criterion_group!/criterion_main!宏并在 pageserver/Cargo.toml 中显式声明[[bench]] name bench_layer_map harness false [[bench]] name bench_walredo harness false [[bench]] name bench_ingest harness false required-features [benchmarking] [[bench]] name upload_queue harness false [[bench]] name bench_metrics harness false每个基准都设置了harness false意味着完全由 Criterion 接管基准生命周期采样、统计、报告。bench_ingest额外声明了required-features [benchmarking]这是 Pageserver 为基准测试单独开放的特性门控见 pageserver/Cargo.toml 中的benchmarking []防止基准专用 API 进入生产构建。5 个基准测试与文件对应关系如下基准文件测量对象关键指标bench_layer_map.rsLayerMap 查询与可见性计算单次search/get_visibility耗时bench_ingest.rs批量写入路径吞吐量MiB/s、GiB/sbench_walredo.rsWAL 重放管理器单次 redo 耗时 vs 并发客户端数upload_queue.rs远程上传队列next_ready()调度成本bench_metrics.rs指标系统多核扩展性不同线程/标签数下的单次操作耗时如何运行基准测试原 README 给出了三层运行粒度这是使用该套件的核心操作# 1. 运行全部基准测试 cargo bench # 2. 只运行某个基准文件 cargo bench --bench bench_layer_map # 3. 只运行某个基准文件中的某个函数 cargo bench --bench bench_layer_map -- real_map_uniform_queries第三级命令中--之后的参数会被透传给 Criterion按函数名子串过滤基准所以real_map_uniform_queries会命中bench_from_real_project组中的uniform_queriesCriterion 的完整基准 ID 形如real_map/uniform_queries。结合仓库实际情况还有几个值得掌握的变体带 io 模式的 Ingest 基准需要显式开启特性否则会被跳过并报错cargo bench --bench bench_ingest --features benchmarkingMetrics 基准的火焰图 / 深采样模式仓库注释中记录了带--discard-baseline --noplot参数与RUST_BACKTRACEfull的运行方式见 bench_metrics.rsRUST_BACKTRACEfull cargo bench --bench bench_metrics -- --discard-baseline --noplotUpload 队列基准默认挂载 pprof 剖析器会同时产出 CPU 火焰图见下文可直接定位热点函数。Criterion 的常规扩展参数如--profile-time 秒、--save-baseline、--noplot在此同样适用基准进程会在仓库根目录的target/criterion/下生成 HTML 报告与 JSON 原始数据便于持续跟踪性能回归。LayerMap 查询基准贴近真实租户的读路径解剖bench_layer_map.rs 是理解 Pageserver 读路径的入口。它围绕pageserver::tenant::layer_map::LayerMap的search与get_visibility两个核心 API 展开在 layer_map.rs 中可以看到search(key, end_lsn)的实现逻辑先在内存层中查找再按end_lsn定位历史版本并同时对 delta 覆盖区间与 image 覆盖区间做区间查询最后按 image delta in-memory 的优先级select_layer。这正是 Neon 存算分离架构中读一个页面的最短路径。三层数据来源设计该基准对 LayerMap 的构造做了三类场景覆盖源码注释明确说明其动机性能测试环境元数据bench_from_captest_env来自运行过多次 pgbench、每次测试前重新初始化数据库的性能测试项目读取 odd-brook-layernames.txt约 2.6 万行层名构造 LayerMap。注释特别说明该文件暂未压缩TODO暗示其体积带来的 IO 开销是已知成本。真实线上项目元数据bench_from_real_project源自一个 layer map 查询耗时过长的真实项目同样加载 odd-brook 数据用于量化生产问题的改进空间。合成数据bench_sequential程序化构造100,000 个层、排列成 1000 条对角斜线每个 key 区间zero.add(10*i32)..zero.add(10*i321)对应一个 image 层LSN 随索引递增代码注释还坦白了两点工程现实初始化代码较慢且即使只跑其他基准也会执行不能放入bench_function闭包否则会在 warmup 阶段重复运行见 bench_layer_map.rs。查询模式均匀分布与 RelDir 热点uniform_query_pattern是查询生成的巧妙之处bench_layer_map.rs对每个image 层取其内部一个 key 该层创建前的 LSN由于 image 层尺寸与覆盖的 WAL 大致均匀这样生成的查询对 key 空间和 LSN 空间都是近似均匀覆盖的。此外还有两个专项用例captest_rel_dir_query查询RelDir 目录项对应的 key000000067F000080...即 PostgreSQL 的pg_class之类系统目录所在的分区参见pgdatadir_mapping.rsLSN 取一个高于树内所有 LSN 的值模拟追平到最新目录状态的典型请求。可见性基准bench_visibility用 100,000 层合成数据构造 100 个均匀分布读点以及用真实数据分别构造单个分支与多个分支8 个读点含重复分支的读点集合。get_visibility在源码中声明为O(N) 且应低频调用见 layer_map.rs用于 GC / 裁剪等后台任务判断哪些层在给定读点下可见。Ingest 写入基准参数爆炸式吞吐测试bench_ingest.rs 专门测量 Pageserver 的批量写入ingest路径。源码注释明确框定了测量边界bench_ingest.rs该基准不包含 WAL 解码从InMemoryLayer::put_value开始到冻结 ephemeral 层layer.freeze为止若开启 WriteDelta 则追加将 ephemeral 层落盘为 L0layer.write_to_disk。它使用真实磁盘 IO因此结果随存储介质变化在快速磁盘上CPU 是当时的瓶颈。六个参数维度ingest()函数对每条写入路径做了正交参数化枚举类型定义在 bench_ingest.rs参数取值含义io_modeBuffered / Direct / DirectRw虚拟文件 IO 模式通过pageserver::virtual_file::set_io_mode注入volume_mib128当前手工挑选集总写入数据量MiB由put_count volume_mib * 1024 * 1024 / key_size换算key_size100 字节 / 8192 字节每条 value 的 payload 大小Value::Image(vec![0u8; put_size])key_layoutSequential / Random / RandomReusekey 生成方式顺序递增、murmurhash32 伪随机、随机但仅用低 10 位 0x3ff以限制基数write_deltaYes / No是否把 ephemeral 层写盘为 L0L0FlushGlobalStatewrite_to_diskconcurrent_readsYes / No是否在写入的同时开启一个 reader 任务做get_values_reconstruct_data并发读当前仅对 Sequential 布局启用见 bench_ingest.rs 的断言写入过程以 16 条为一批调用layer.put_batch(SerializedValueBatch, ...)最后layer.freeze(lsn 1)WriteDelta 模式下还会把生成的 L0 文件立刻remove_file删除bench_ingest.rs避免污染临时目录。基准 ID 由全部维度拼接而成例如ingest/io_modeDirectRw volume_mib128 key_size_bytes100 key_layoutSequential write_deltaNo concurrent_readsNogroup.throughput会把key_size * put_count注册为字节吞吐量因此 Criterion 报告会同时给出时间与MiB/s 吞吐。参考数据解读源码注释中的历史记录源码尾部注释保留了两次实机运行结果bench_ingest.rs它们是当时环境的快照而非当前保证值但非常适合理解参数敏感性Hetzner AX102AMD Ryzen上DirectRw 顺序 key 8KiB 值 不落盘达到约1.0061 GiB/s中值吞吐是注释记录中最高的一组同样的硬件上随机 keymurmur 打散比顺序 key 明显慢100B 值 WriteDelta约 118.90 MiB/s vs 205.63 MiB/s印证了注释用随机顺序避免给尾部插入更快的数据结构虚假优势的设计意图开启落盘write_deltaYes普遍显著降低吞吐如 8KiB 顺序值在 AX102 上从 1022.8 MiB/s 降到 460.95 MiB/s这是 fsync / 写盘路径的固有成本im4gn.2xlarge 上三种 IO 模式Buffered/Direct/DirectRw在 100B 小值时表现接近但 8KiB 大值场景下Buffered 明显领先 DirectRw290 MiB/s vs 238 MiB/s 附近说明大块顺序写入对直接 IO 的对齐与同步开销更敏感。WAL 重放基准单管理器并发扩展性bench_walredo.rs 量化单个PostgresRedoManager在 N 个并发调用者下的吞吐。Neon 将 WAL 重放redo委托给独立的 walredo 进程见 pageserver/src/walredo.rs 与 pgxn/neon_walredo该基准直接调用manager.request_redo(...)RedoAttemptType::ReadPage。它的方法论值得一提实现被参数化为(redo_work, n_redos, nclients)nclients取值[1, 2, 4, 8, 16, 32, 64, 128]每个 client 是一个 tokio 任务用Barrier同步起跑任务间通过tokio::task::yield_now()让出执行器以模拟真实 Pageserver几乎不会连续两次 redo 不让出的行为bench_walredo.rs用iter_custom让 Criterion 自行决定迭代次数即采样最终报告的是从客户端视角聚合的墙钟时间——即每次 redo_work 执行耗时。三种redo_work负载对应源码注释中的 2024-09-18 im4gn.2xlarge 参考数据bench_walredo.rs负载含义单客户端耗时128 客户端耗时ping纯协议往返mgr.ping≈21.9 µs≈688 µsshort1132 字节记录重放含建表 DDL 记录≈32.1 µs≈993 µsmedium26,393 字节记录重放大量顺序 page 写≈138.6 µs≈10.6 msmedium/128相比medium/1大约有 76 倍的退化而ping/128只有约 31 倍——重放负载越重单管理器的串行瓶颈放大越明显。short与medium的请求载荷key、LSN、WAL 记录字节流、pg_version: PG14都是从真实日志中复制的注释注明 pg_record 字节来自Debug输出、空字节用\0转义确保重放内容贴近实际 DDL/DML。指标系统基准多核扩展性的实证研究bench_metrics.rs 不是常规性能基准而是一组证明指标统计本身就是多核瓶颈的微基准每个 benchmark 都附带了明确的结论注释共四组label_values__naive_usagevscache_label_values_lookup每次都调with_label_values做标签查找 vs 一次性缓存指标对象。参考数据Hetzner AX102显示naive 版从 1 timeline 的 ≈64.6 ns 涨到 8 timeline 的 ≈819 ns而缓存版几乎恒定≈1.3–1.6 ns。结论是重复的标签值查找是值得规避的多核扩展性瓶颈。single_metric_multicore_scalability仅一个UIntGauge被 1/4/8 线程并发inc()。数据从 ≈1.2 ns1 线程恶化到 ≈60 ns8 线程。注释承认单个指标本身即瓶颈且除非改用分片计数器原子sharded counter atomics否则无计可施。propagation_of_cached_label_value把已缓存的指标Clone到子RequestContext模拟 context 传播vs 每线程持有长生命周期Arc引用。naive 版 8 线程 ≈170 ns而长生命周期引用版 ≈2.8 ns。原因是指标内部是ArcClone会竞争引用计数原子。bucket_scalability直方图桶数从 1 增到 256观察耗时从 ≈6.4 ns 平滑升到 ≈54.9 ns量化了分位数直方图在大桶数下的线性成本。源码注释中记录了 5 台机器im4gn.2xlarge、i3en.3xlarge、Azure Standard L16s v3、M4 MAX MacBook Pro、Hetzner AX102的完整历史数据bench_metrics.rs是研究并发指标采集设计的第一手素材。这也解释了仓库为何在 libs/metrics 与 pageserver/src/metrics.rs 中大量采用预缓存指标句柄 长生命周期引用的模式。上传队列基准一个已知的二次方复杂度upload_queue.rs 针对 Pageserver 的远程上传队列pageserver::tenant::upload_queue::UploadQueue见 pageserver/src/tenant/upload_queue.rs测量next_ready()的调度成本。该基准的注释直白地记录了性能问题的根源next_ready()的成本与 in-progress 任务数即排在它前面的任务数线性相关因此整个上传队列是二次方复杂度的。基准构造方式upload_queue.rs先初始化索引与UploadQueue::Uninitialized - initialize_with_current_remote_index_part然后向inprogress_tasks注入 0 到1,000,000个删除任务UploadOp::Delete每轮迭代把UploadOp::UploadMetadata压入队首并调用next_ready()。因为UploadOp::UploadLayer需要完整的 tenant timeline 才能构造所以用 Delete/UploadMetadata 代替——注释指出这恰好是最昂贵的情形。该基准还演示了一个工程细节criterion_group!的config中挂载了pprof CPU 剖析器PProfProfiler::new(100, Output::Flamegraph(None))运行后即可在target/criterion/下得到火焰图把next_ready 的线性扫描直观可视化为热点。数据文件说明与结果解读注意事项两个层名文本文件是 LayerMap 基准的输入odd-brook-layernames.txt约 26,690 行真实层名同时用于 captest 环境与真实项目两组基准large-layer-map-layernames.txt约 5,651 行行格式为{key-range-start}-{key-range-end}__{lsn-start}-{lsn-end}如000000000000000000000000000000000000-000000067F00008000000032090100000000__0000006CF69CD8B0无__后第二段表示 image 层只有起始 LSN。解读任何基准结果时请注意三点环境相关Ingest 与 LayerMap 基准使用真实磁盘 IO 或大规模内存数据结构结果强烈依赖机器注释中 im4gn.2xlarge、Hetzner AX102、MacBook Pro 的数据差异巨大bench_ingest的virtual_file::init明确以SyncMode::Sync同步模式初始化避免缓冲写在 direct IO 面前获得不公平优势bench_ingest.rs。参考数据是历史快照所有实机数据均来自源码注释反映的是编写时的硬件与代码状态应作为相对趋势参考而非当前绝对性能承诺。瓶颈结论有明确指向Ingest 在快盘上瓶颈是 CPUnext_ready是已知的二次方热点metrics 基准整套都在论证指标原子操作与 Arc 引用计数是扩展性陷阱——这些结论都写在源码注释中是仓库维护者留给后来者的性能优化地图。延伸阅读与基准直接相关的核心实现LayerMap 查询、可见性计算、upload_queue、walredo基准输入数据odd-brook-layernames.txt、large-layer-map-layernames.txt仓库通用基准与 CI 脚本run_clippy.sh、scripts/benchmark_durations.py性能数据采集辅助、scripts/generate_and_push_perf_report.sh【免费下载链接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.项目地址: https://gitcode.com/GitHub_Trending/ne/neon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询