关于为什么要计算内存使用情况?
因为内存是昂贵的,云供应商根据CPU/磁盘/网络和内存来区分服务。计算应用程序占用多少内存是一个非常有用的技能。
Example
这篇博文正是来剖析Rust应用程序的堆使用情况。
例子如下:应用程序正在读取一个可能存在的大csv到内存中,然后存储标题和字段,以便以后通过索引访问。下面我们使用一个实例项目来演示:
cargo new --bin heaptrace_csv
其中我们需要的 struct
如下:
use std::io::{self, BufRead};
// src/main.rs
#[allow(dead_code)]
struct DataRecord {
fields: Vec<String>,
}
#[allow(dead_code)]
struct DataSheet {
headers: Vec<String>,
rows: Vec<DataRecord>,
}
以及计算和存储逻辑:
// src/main.rs
fn split_str(s: String) -> Vec<String> {
s.split(',').map(str::to_string).collect()
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = std::fs::File::open("./example.csv")?;
let reader = io::BufReader::new(file);
let mut lines = reader.lines();
let sheet = DataSheet {
headers: split_str(lines.next().ok_or("empty header")??),
rows: lines
.map(|l| DataRecord {
fields: split_str(l.unwrap()),
})
.collect(),
};
Ok(())
}
该程序从 example.csv 创建 BufReader
:
❯ du -h example.csv
976K example.csv
❯ wc -l example.csv
12427 example.csv
计算内存使用
为了计算一个进程在Linux上的内存使用情况,我们可以使用 pmap,但要做到这一点,我们必须添加一些东西,使我们的程序等待计算。让我们在main方法的最后添加简单的sleep:
// end of main method
std::thread::sleep(std::time::Duration::from_secs(10))
因此,为了简化理解内存地址的过程,我们可能想禁用 地址空间布局随机化。这是操作系统使用的一种技术,在进程的地址空间中引入一些随机性:
# read <https://askubuntu.com/questions/318315/how-can-i-temporarily-disable-aslr-address-space-layout-randomization>
# for more information
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
# to enable it back on after having fun:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
然后我们可以用 pmap 分析一下:
❯ cargo run -q --release &
❯ pmap -x $(pgrep heaptrace_csv)
81044: /home/flakm/programming/flakm/rustberry/target/release/heaptrace_csv
Adres KB RSS Brudne Tryb Odwzorowanie
0000555555554000 28 28 0 r---- heaptrace_csv
000055555555b000 228 228 0 r-x-- heaptrace_csv
0000555555594000 56 56 0 r---- heaptrace_csv
00005555555a2000 16 16 16 r---- heaptrace_csv
00005555555a6000 4 4 4 rw--- heaptrace_csv
00005555555a7000 5080 5052 5052 rw--- [ anon ]
00007ffff7d19000 388 292 292 rw--- [ anon ]
00007ffff7dab000 4 0 0 ----- [ anon ]
00007ffff7dac000 16 8 8 rw--- [ anon ]
00007ffff7db0000 152 148 0 r---- libc-2.33.so
00007ffff7dd6000 1352 796 0 r-x-- libc-2.33.so
00007ffff7f28000 312 156 0 r---- libc-2.33.so
00007ffff7f76000 12 12 12 r---- libc-2.33.so
00007ffff7f79000 12 12 12 rw--- libc-2.33.so
00007ffff7f7c000 36 12 12 rw--- [ anon ]
00007ffff7f85000 4 4 0 r---- libdl-2.33.so
00007ffff7f86000 4 4 0 r-x-- libdl-2.33.so
00007ffff7f87000 4 0 0 r---- libdl-2.33.so
00007ffff7f88000 4 4 4 r---- libdl-2.33.so
00007ffff7f89000 4 4 4 rw--- libdl-2.33.so
00007ffff7f8a000 28 28 0 r---- libpthread-2.33.so
00007ffff7f91000 56 56 0 r-x-- libpthread-2.33.so
00007ffff7f9f000 20 0 0 r---- libpthread-2.33.so
00007ffff7fa4000 4 4 4 r---- libpthread-2.33.so
00007ffff7fa5000 4 4 4 rw--- libpthread-2.33.so
00007ffff7fa6000 16 4 4 rw--- [ anon ]
00007ffff7faa000 12 12 0 r---- libgcc_s.so.1
00007ffff7fad000 68 64 0 r-x-- libgcc_s.so.1
00007ffff7fbe000 12 12 0 r---- libgcc_s.so.1
00007ffff7fc1000 4 0 0 ----- libgcc_s.so.1
00007ffff7fc2000 4 4 4 r---- libgcc_s.so.1
00007ffff7fc3000 4 4 4 rw--- libgcc_s.so.1
00007ffff7fc4000 8 8 8 rw--- [ anon ]
00007ffff7fc6000 16 0 0 r---- [ anon ]
00007ffff7fca000 8 4 0 r-x-- [ anon ]
00007ffff7fcc000 4 4 0 r---- ld-2.33.so
00007ffff7fcd000 144 144 0 r-x-- ld-2.33.so
00007ffff7ff1000 40 40 0 r---- ld-2.33.so
00007ffff7ffb000 8 8 8 r---- ld-2.33.so
00007ffff7ffd000 8 8 8 rw--- ld-2.33.so
00007ffffffd1000 184 64 64 rw--- [ stos ]
ffffffffff600000 4 0 0 --x-- [ anon ]
---------------- ------- ------- -------
razem kB 8372 7308 5524
TODO!!!
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情