--- title: 存储内存使用量基准测试 weight: 5125 description: etcd 存储的性能指标(内存索引与页面缓存) categories: [参考] upstream_link: "https://github.com/etcd-io/website/blob/824597935df6e95992ef61c07e3222f4f796ca6c/content/en/docs/v3.7/benchmarks/etcd-storage-memory-benchmark.md" aliases: [/etcd/benchmarks/etcd-storage-memory-benchmark/] --- etcd 存储的两个组件会占用物理内存。etcd 进程分配了一个 *内存索引*,用于加速键的查找。进程的 *页缓存* 由操作系统管理,用于存储从磁盘读取的最近访问数据,以便快速重用。 内存索引将所有键以 [B 树][btree] 数据结构的形式存储,并附带指向磁盘数据(即值)的指针。B 树中的每个键可能包含多个指针,指向其值的不同版本。因此,内存索引的理论内存消耗可近似表示为以下公式: `N * (c1 + avg_key_size) + N * (avg_versions_of_key) * (c2 + size_of_pointer)` 其中 `c1` 为键元数据开销,`c2` 为版本元数据开销。 图表展示了内存中索引 B 树的详细结构。 ``` In mem index +------------+ | key || ... | +--------------+ | || | | | +------------+ | | | v1 || ... | | disk <----------------| || | Tree Node | | +------------+ | | | v2 || ... | | <----------------+ || | | | +------------+ +--------------+ +-----+ | | | | | | | | | +------------+ | | ^ ------+ | ... | | | +-----+ | ... | Tree Node | | +-----+ | ... | | | ------+ ``` [页面缓存内存][pagecache] 由操作系统管理,本文档不对其进行详细说明。 ## 测试环境 {#testing-environment} etcd 版本 - git 提交哈希 https://github.com/etcd-io/etcd/commit/776e9fb7be7eee5e6b58ab977c8887b4fe4d48db GCE n1-standard-2 机器类型 - 7.5 GB 内存 - 2 个 CPU ## 内存中索引内存使用量 {#in-memory-index-memory-usage} 本测试仅针对内存索引的内存使用情况进行基准测试。目标是查找上述 `c1` 和 `c2`,并了解存储系统的内存消耗上限。 我们通过 Go 运行时的 ReadMemStats 计算内存使用量。通过对比创建索引前后的已分配字节数差异来估算内存使用情况。该方法无法完全反映内存中索引本身的内存使用量,但可展示大致的消耗趋势。 | N | 版本数 | 键大小 | 内存占用 | |------|--------|--------|----------| | 100K | 1 | 64 字节 | 22 MB | | 100K | 5 | 64 字节 | 39 MB | | 1M | 1 | 64 字节 | 218 MB | | 1M | 5 | 64 字节 | 432 MB | | 100K | 1 | 256 字节 | 41 MB | | 100K | 5 | 256 字节 | 65 MB | | 1M | 1 | 256 字节 | 409 MB | | 1M | 5 | 256 字节 | 506 MB | 根据结果,我们可以计算 `c1=120bytes`、`c2=30bytes`。仅需两组数据即可计算 `c1` 和 `c2`,因为它们是公式中唯一的未知变量。`c1=120bytes` 和 `c2=30bytes` 是我们计算出的 4 组 `c1` 和 `c2` 的平均值。对于小键值对,键元数据开销仍相对显著(50%)。然而,这相较于旧存储系统已实现显著改进,后者至少存在 1000% 的开销。 ## 整体内存使用情况 {#overall-memory-usage} 整体内存使用量反映了 etcd 在存储系统上的 RSS 内存占用情况。值的大小对 etcd 的整体内存使用量影响极小,因为值数据存储在磁盘上,仅将热值保留在内存中,由操作系统的页面缓存进行管理。 | N | versions | 键大小 | 值大小 | 内存占用 | |------|----------|--------|--------|----------| | 100K | 1 | 64 字节 | 256 字节 | 40 MB | | 100K | 5 | 64 字节 | 256 字节 | 89 MB | | 1M | 1 | 64 字节 | 256 字节 | 470 MB | | 1M | 5 | 64 字节 | 256 字节 | 880 MB | | 100K | 1 | 64 字节 | 1 KB | 102 MB | | 100K | 5 | 64 字节 | 1 KB | 164 MB | | 1M | 1 | 64 字节 | 1 KB | 587 MB | | 1M | 5 | 64 字节 | 1 KB | 836 MB | 根据结果可知,值的大小对内存消耗的影响并不显著。由于操作系统页缓存中存储了更多数据,存在轻微的内存增长。 [btree]: https://en.wikipedia.org/wiki/B-tree [pagecache]: https://en.wikipedia.org/wiki/Page_cache