附录 A
USE 方法:Linux
本附录包含源自 USE 方法 [Gregg 13d] 的 Linux 速查表。这是一种用于检查系统健康状况、识别常见资源瓶颈和错误的方法,最初在第 2 章 方法论 第 2.5.9 节“USE 方法”中介绍。后续章节(5、6、7、9、10)在特定语境下对其进行了描述,并介绍了支持其使用的工具。性能工具经常被增强,并且新的工具也在不断开发中,因此您应该将其视为一个需要更新的起点。也可以开发新的可观测性框架和工具,专门让遵循 USE 方法变得更加容易。
关键提示
对于任何施加了资源控制的环境(例如云计算),请检查每个资源控制的 USE 指标。这些控制可能会在硬件资源被完全利用之前遇到——并限制使用。
物理资源
| 组件 | 类型 | 指标 |
|---|---|---|
| CPU | 利用率 | 每个 CPU: mpstat -P ALL 1,消耗 CPU 的列(%usr, %nice, %sys, %irq, %soft, %guest, %gnice)之和,或空闲列(%iowait, %steal, %idle)的逆;sar -P ALL,消耗 CPU 的列(%user, %nice, %system)之和,或空闲列(%iowait, %steal, %idle)的逆系统范围: vmstat 1,us + sy;sar -u,%user + %nice + %system每个进程: top,%CPU;htop,CPU%;ps -o pcpu;pidstat 1,%CPU每个内核线程: top/htop(按 K 切换),其中 VIRT == 0(启发式方法) |
| CPU | 饱和度 | 系统范围: vmstat 1,r > CPU 数量¹;sar -q,runq-sz > CPU 数量;runqlat;runqlen每个进程: /proc/PID/schedstat 第二个字段 (sched_info.run_delay);getdelays.c,CPU²;perf sched latency(显示每次调度的平均和最大延迟)³ |
| CPU | 错误 | 在 dmesg 或 rasdaemon 和 ras-mc-ctl --summary 中看到的机器检查异常;如果处理器特定的错误事件 可用,则使用 perf(1);例如,AMD64 的“04Ah Single-bit ECC Errors Recorded by Scrubber”⁴(也可归类为内存设备错误);ipmtool sel list;ipmitool sdr list |
| 内存容量 | 利用率 | 系统范围: free -m,Mem:(主存),Swap:(虚拟内存);vmstat 1,free(主存),swap(虚拟内存);sar -r,%memused;slabtop -s c 用于 kmem slab 使用量每个进程: top/htop,RES(常驻主存),VIRT(虚拟内存),Mem 用于系统范围摘要 |
| 内存容量 | 饱和度 | 系统范围: vmstat 1,si/so(交换);sar -B,pgscank + pgscand(扫描);sar -W每个进程: getdelays.c,SWAP²;/proc/PID/stat 的第 10 个字段 (min_flt) 用于轻微缺页率,或动态插桩⁵;dmesg | grep killed(OOM killer) |
| 内存容量 | 错误 | dmesg 用于物理故障或 rasdaemon 和 ras-mc-ctl --summary 或 edac-util;dmidecode 也可能显示物理故障;ipmtool sel list;ipmitool sdr list;动态插桩,例如用于失败 malloc() 的 uretprobes (bpftrace) |
| 网络接口 | 利用率 | ip -s link,RX/TX 吞吐量 / 最大带宽;sar -n DEV,rx/tx kB/s / 最大带宽;/proc/net/dev,bytes RX/TX 吞吐量/max |
| 网络接口 | 饱和度 | nstat,TcpRetransSegs;sar -n EDEV,*drop/s, *fifo/s⁶;/proc/net/dev,RX/TX drop;其他 TCP/IP 栈排队的动态插桩 (bpftrace) |
| 网络接口 | 错误 | ip -s link,errors;sar -n EDEV all;/proc/net/dev,errs, drop⁶;额外的计数器可能在 /sys/class/net/*/statistics/*error* 下;驱动程序函数返回值的动态插桩 |
| 存储设备 I/O | 利用率 | 系统范围: iostat -xz 1,%util;sar -d,%util每个进程: iotop,biotop;/proc/PID/sched se.statistics.iowait_sum |
| 存储设备 I/O | 饱和度 | iostat -xnz 1,avgqu-sz > 1,或高 await;sar -d 同上;perf(1) block 跟踪点用于队列长度/延迟;biolatency |
| 存储设备 I/O | 错误 | /sys/devices/ . . . /ioerr_cnt;smartctl;bioerr;I/O 子系统响应代码的动态/静态插桩⁷ |
| 存储容量 | 利用率 | Swap:swapon -s;free;/proc/meminfo SwapFree/SwapTotal;文件系统:df -h |
| 存储容量 | 饱和度 | 不确定这个是否有意义——一旦满了,就会返回 ENOSPC(尽管当接近满时,性能可能会下降,具体取决于文件系统空闲块算法) |
| 存储容量 | 错误 (文件系统) | strace 用于 ENOSPC;ENOSPC 的动态插桩;/var/log/messages 错误,取决于文件系统 (FS);应用程序日志错误 |
| 存储控制器 | 利用率 | iostat -sxz 1,对设备求和并与每张卡已知的 IOPS/吞吐量限制进行比较 |
| 存储控制器 | 饱和度 | 参见存储设备饱和度,… |
| 存储控制器 | 错误 | 参见存储设备错误,… |
| 网络控制器 | 利用率 | 从 ip –s link(或 sar,或 /proc/net/dev)及其接口已知的控制器最大吞吐量推断 |
| 网络控制器 | 饱和度 | 参见网络接口,饱和度,… |
| 网络控制器 | 错误 | 参见网络接口,错误,… |
| CPU 互联 | 利用率 | 带有 CPU 互联端口 PMC 的 perf stat,吞吐量/max |
| CPU 互联 | 饱和度 | 带有停顿周期 PMC 的 perf stat |
| CPU 互联 | 错误 | 带有任何可用 PMC 的 perf stat |
| 内存互联 | 利用率 | 带有内存总线 PMC 的 perf stat,吞吐量/max;例如 Intel uncore_imc/data_reads/,uncore_imc/data_writes/;或 IPC 小于(比如)0.2;PMC 可能还有本地与远程计数器 |
| 内存互联 | 饱和度 | 带有停顿周期 PMC 的 perf stat |
| 内存互联 | 错误 | 带有任何可用 PMC 的 perf stat;dmidecode 可能会有一些信息 |
| I/O 互联 | 利用率 | 如果可用,带有吞吐量/max PMC 的 perf stat;通过 iostat/ip/… 已知吞吐量推断 |
| I/O 互联 | 饱和度 | 带有停顿周期 PMC 的 perf stat |
| I/O 互联 | 错误 | 带有任何可用 PMC 的 perf stat |
脚注:
r列报告了正在等待的线程以及正在 CPU 上运行的线程。参见第 6 章 CPU 中对vmstat(1)的描述。- 使用延迟记账;参见第 4 章 可观测性工具。
perf(1)也有sched:sched_process_wait跟踪点;在跟踪时要注意开销,因为调度器事件非常频繁。- 在最近的 Intel 和 AMD 处理器手册中,与错误相关的事件并不多。
- 这可以用来显示是什么消耗了内存并导致饱和,通过查看是什么引起了轻微缺页。这应该在
htop(1)中作为 MINFLT 可用。 - 丢弃的数据包同时被包含为饱和度和错误指标,因为它们可能由于这两种类型的事件而发生。
- 这包括跟踪 I/O 子系统不同层的函数:块设备、SCSI、SATA、IDE… 一些静态探针可用(
perf(1)scsi 和 block 跟踪点事件);否则,使用动态跟踪。
一般说明
uptime“负载均值”(或/proc/loadavg):未包含在 CPU 指标中,因为 Linux 的负载均值包含了处于不可中断 I/O 状态的任务。perf(1):是一个强大的可观测性工具包,可读取 PMC,也可使用动态和静态插桩。其接口是perf(1)命令。参见第 13 章 perf。- PMC:性能监控计数器。参见第 6 章 CPU,及其与
perf(1)的使用。- I/O 互联:这包括 CPU 到 I/O 控制器总线、I/O 控制器以及设备总线(例如 PCIe)。
- 动态插桩:允许开发自定义指标。参见第 4 章 可观测性工具,以及后续章节中的示例。Linux 的动态跟踪工具包括
perf(1)(第 13 章)、Ftrace(第 14 章)、BCC 和 bpftrace(第 15 章)。
软件资源
| 组件 | 类型 | 指标 |
|---|---|---|
| 内核互斥锁 | 利用率 | 在 CONFIG_LOCK_STATS=y 的情况下,/proc/lock_stat holdtime-total / acquisitions(另见 holdtime-min, holdtime-max)⁸;锁函数或指令的动态插桩(可能) |
| 内核互斥锁 | 饱和度 | 在 CONFIG_LOCK_STATS=y 的情况下,/proc/lock_stat waittime-total / contentions(另见 waittime-min, waittime-max);锁函数的动态插桩,例如 mlock.bt [Gregg 19];自旋显示在性能分析中 perf record -a -g -F 99 ... |
| 内核互斥锁 | 错误 | 动态插桩(例如,递归互斥锁进入);其他错误可能导致内核锁定/宕机,使用 kdump/crash 进行调试 |
脚注:
- 内核锁分析过去是通过
lockmeter进行的,它有一个名为lockstat的接口。
17.1 附录
| 组件 | 类型 | 指标 |
|---|---|---|
| 用户互斥锁 (User mutex) | 利用率 (Utilization) | valgrind --tool=drd --exclusive-threshold= ...(持有时间);对加锁到解锁函数时间的动态插桩9 |
| 用户互斥锁 (User mutex) | 饱和度 (Saturation) | valgrind --tool=drd 从持有时间推断争用情况;同步函数的动态插桩以获取等待时间,例如 pmlock.bt;性能剖析 (perf(1)) 用户态栈以查找自旋 |
| 用户互斥锁 (User mutex) | 错误 (Errors) | valgrind --tool=drd 各种错误;pthread_mutex_lock() 的动态插桩以捕获 EAGAIN, EINVAL, EPERM, EDEADLK, ENOMEM, EOWNERDEAD 等错误 |
| 任务容量 (Task capacity) | 利用率 (Utilization) | top/htop,Tasks(当前);sysctl kernel.threads-max,/proc/sys/kernel/threads-max(最大值) |
| 任务容量 (Task capacity) | 饱和度 (Saturation) | 线程在内存分配上阻塞;此时页面扫描器应该正在运行(sar -B, pgscan*),否则使用动态追踪进行检查 |
| 任务容量 (Task capacity) | 错误 (Errors) | “can’t fork()” 错误;用户级线程:pthread_create() 失败并返回 EAGAIN, EINVAL 等;内核:kernel_thread() ENOMEM 的动态追踪 |
| 文件描述符 (File descriptors) | 利用率 (Utilization) | 系统级:sar -v,file-nr 对比 /proc/sys/fs/file-max;或直接查看 /proc/sys/fs/file-nr单进程:`echo /proc/PID/fd/* |
| 文件描述符 (File descriptors) | 饱和度 (Saturation) | 此项可能无意义 |
| 文件描述符 (File descriptors) | 错误 (Errors) | strace 在返回文件描述符的系统调用(如 open(2), accept(2) 等)上 errno == EMFILE;opensnoop -x |
A.1 参考文献
- [Gregg 13d] Gregg, B., “USE Method: Linux Performance Checklist,” http://www.brendangregg.com/USEmethod/use-linux.html, 首次发布于 2013 年。
脚注 9
由于这些函数可能非常频繁,请注意追踪每次调用带来的性能开销:应用程序可能会变慢 2 倍或更多。
附录 B sar 总结
这是系统活动报告器 sar(1) 的选项和指标总结。你可以用它来唤醒记忆,了解哪些指标在哪些选项下。完整列表请参阅 man 手册页。
sar(1) 在第 4 章“可观测性工具”第 4.4 节中介绍,部分选项在后续章节(6、7、8、9、10)中进行了总结。
| 选项 | 指标 | 描述 |
|---|---|---|
-u -P ALL | %user %nice %system %iowait %steal %idle | 每 CPU 利用率(-u 可选) |
-u | %user %nice %system %iowait %steal %idle | CPU 利用率 |
-u ALL | ... %irq %soft %guest %gnice | CPU 利用率(扩展) |
-m CPU -P ALL | MHz | 每 CPU 频率 |
-q | runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked | CPU 运行队列长度 |
-w | proc/s cswch/s | CPU 调度器事件 |
-B | pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff | 分页统计 |
-H | kbhugfree kbhugused %hugused | 大页 |
-r | kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty | 内存利用率 |
-S | kbswpfree kbswpused %swpused kbswpcad %swpcad | 交换区利用率 |
-W | pswpin/s pswpout/s | 交换统计 |
-v | dentunusd file-nr inode-nr pty-nr | 内核表 |
-d | tps rkB/s wkB/s areq-sz aqu-sz await svctm %util | 磁盘统计 |
-n DEV | rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil | 网络接口统计 |
-n EDEV | rxerr/s txerr/s coll/s rxdrop/s txdrop/s txcarr/s rxfram/s rxfifo/s txfifo/s | 网络接口错误 |
-n IP | irec/s fwddgm/s idel/s orq/s asmrq/s asmok/s fragok/s fragcrt/s | IP 统计 |
-n EIP | ihdrerr/s iadrerr/s iukwnpr/s idisc/s odisc/s onort/s asmf/s fragf/s | IP 错误 |
-n TCP | active/s passive/s iseg/s oseg/s | TCP 统计 |
-n ETCP | atmptf/s estres/s retrans/s isegerr/s orsts/s | TCP 错误 |
-n SOCK | totsck tcpsck udpsck rawsck ip-frag tcp-tw | Socket 统计 |
TIP
我加粗显示了我重点关注的指标。
WARNING
某些
sar(1)选项可能需要启用内核功能(例如大页),并且某些指标是在sar(1)的后续版本中添加的(此处显示的是 12.0.6 版本)。
附录 C bpftrace 单行命令
本附录包含一些实用的 bpftrace 单行命令。除了本身非常实用之外,它们还可以帮助你一行一行地学习 bpftrace。其中大部分已包含在之前的章节中。许多命令可能无法立即运行:它们可能依赖于某些 tracepoint 或函数的存在,或者依赖于特定的内核版本或配置。
关于 bpftrace 的介绍,请参见第 15 章第 15.2 节。
CPUs
追踪新进程及其参数:
bpftrace -e 'tracepoint:syscalls:sys_enter_execve { join(args->argv); }'按进程统计系统调用:
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[pid, comm] = count(); }'按系统调用探针名统计系统调用:
bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[probe] = count(); }'以 99 赫兹对正在运行的进程名进行采样:
bpftrace -e 'profile:hz:99 { @[comm] = count(); }'以 49 赫兹对全系统的用户态和内核栈进行采样,包含进程名:
bpftrace -e 'profile:hz:49 { @[kstack, ustack, comm] = count(); }'以 49 赫兹对 PID 189 的用户态栈进行采样:
bpftrace -e 'profile:hz:49 /pid == 189/ { @[ustack] = count(); }'以 49 赫兹对 PID 189 深度为 5 帧的用户态栈进行采样:
bpftrace -e 'profile:hz:49 /pid == 189/ { @[ustack(5)] = count(); }'以 49 赫兹对名为 “mysqld” 的进程的用户态栈进行采样:
bpftrace -e 'profile:hz:49 /comm == "mysqld"/ { @[ustack] = count(); }'统计内核 CPU 调度器 tracepoint:
bpftrace -e 'tracepoint:sched:* { @[probe] = count(); }'统计上下文切换事件的脱离 CPU (off-CPU) 内核栈:
bpftrace -e 'tracepoint:sched:sched_switch { @[kstack] = count(); }'统计以 “vfs_” 开头的内核函数调用:
bpftrace -e 'kprobe:vfs_* { @[func] = count(); }'通过 pthread_create() 追踪新线程:
bpftrace -e 'u:/lib/x86_64-linux-gnu/libpthread-2.27.so:pthread_create {
printf("%s by %s (%d)\n", probe, comm, pid); }'Memory
按用户栈和进程汇总 libc malloc() 请求字节数(高开销):
bpftrace -e 'u:/lib/x86_64-linux-gnu/libc.so.6:malloc {
@[ustack, comm] = sum(arg0); }'按用户栈为 PID 181 汇总 libc malloc() 请求字节数(高开销):
bpftrace -e 'u:/lib/x86_64-linux-gnu/libc.so.6:malloc /pid == 181/ {
@[ustack] = sum(arg0); }'以 2 的幂次直方图显示 PID 181 的 libc malloc() 请求字节数(高开销):
bpftrace -e 'u:/lib/x86_64-linux-gnu/libc.so.6:malloc /pid == 181/ {
@[ustack] = hist(arg0); }'按内核栈追踪汇总内核 kmem 缓存分配字节数:
bpftrace -e 't:kmem:kmem_cache_alloc { @bytes[kstack] = sum(args->bytes_alloc); }'按代码路径统计进程堆扩展 (brk(2)):
bpftrace -e 'tracepoint:syscalls:sys_enter_brk { @[ustack, comm] = count(); }'按进程统计缺页:
bpftrace -e 'software:page-fault:1 { @[comm, pid] = count(); }'按用户级栈追踪统计用户态缺页:
bpftrace -e 't:exceptions:page_fault_user { @[ustack, comm] = count(); }'按 tracepoint 统计 vmscan 操作:
bpftrace -e 'tracepoint:vmscan:* { @[probe]++; }'按进程统计换入:
bpftrace -e 'kprobe:swap_readpage { @[comm, pid] = count(); }'统计页面迁移:
bpftrace -e 'tracepoint:migrate:mm_migrate_pages { @ = count(); }'追踪内存规整 事件:
bpftrace -e 't:compaction:mm_compaction_begin { time(); }'列出 libc 中的 USDT 探针:
bpftrace -l 'usdt:/lib/x86_64-linux-gnu/libc.so.6:*'列出内核 kmem tracepoint:
bpftrace -l 't:kmem:*'列出所有内存子系统 的 tracepoint:
bpftrace -l 't:*:mm_*'File Systems
追踪通过 openat(2) 打开的文件及进程名:
bpftrace -e 't:syscalls:sys_enter_openat { printf("%s %s\n", comm,
str(args->filename)); }'按系统调用类型统计读系统调用:
bpftrace -e 'tracepoint:syscalls:sys_enter_*read* { @[probe] = count(); }'按系统调用类型统计写系统调用:
bpftrace -e 'tracepoint:syscalls:sys_enter_*write* { @[probe] = count(); }'显示 read() 系统调用请求大小的分布:
bpftrace -e 'tracepoint:syscalls:sys_enter_read { @ = hist(args->count); }'显示 read() 系统调用读取字节(和错误)的分布:
bpftrace -e 'tracepoint:syscalls:sys_exit_read { @ = hist(args->ret); }'按错误码统计 read() 系统调用错误:
bpftrace -e 't:syscalls:sys_exit_read /args->ret < 0/ { @[- args->ret] = count(); }'统计 VFS 调用:
bpftrace -e 'kprobe:vfs_* { @[probe] = count(); }'统计 PID 181 的 VFS 调用:
bpftrace -e 'kprobe:vfs_* /pid == 181/ { @[probe] = count(); }'统计 ext4 tracepoint:
bpftrace -e 'tracepoint:ext4:* { @[probe] = count(); }'统计 xfs tracepoint:
bpftrace -e 'tracepoint:xfs:* { @[probe] = count(); }'按进程名和用户级栈统计 ext4 文件读取:
bpftrace -e 'kprobe:ext4_file_read_iter { @[ustack, comm] = count(); }'追踪 ZFS spa_sync() 时间:
bpftrace -e 'kprobe:spa_sync { time("%H:%M:%S ZFS spa_sync()\n"); }'按进程名和 PID 统计 dcache 引用:
bpftrace -e 'kprobe:lookup_fast { @[comm, pid] = count(); }'Disks
统计块 I/O tracepoint 事件:
bpftrace -e 'tracepoint:block:* { @[probe] = count(); }'以直方图汇总块 I/O 大小:
bpftrace -e 't:block:block_rq_issue { @bytes = hist(args->bytes); }'统计块 I/O 请求的用户栈追踪:
bpftrace -e 't:block:block_rq_issue { @[ustack] = count(); }'统计块 I/O 类型标志:
bpftrace -e 't:block:block_rq_issue { @[args->rwbs] = count(); }'# 17.1 附录
> [!INFO] 连续性提示]
>
> 本部分为文档的第 3/6 部分,承接自上一部分的 `bpftrace` 块 I/O 单行命令内容。
---
跟踪带有设备和 I/O 类型的块 I/O 错误:
```bash
bpftrace -e 't:block:block_rq_complete /args->error/ {
printf("dev %d type %s error %d\n", args->dev, args->rwbs, args->error); }'统计 SCSI 操作码:
bpftrace -e 't:scsi:scsi_dispatch_cmd_start { @opcode[args->opcode] =
count(); }'统计 SCSI 结果码:
bpftrace -e 't:scsi:scsi_dispatch_cmd_done { @result[args->result] = count(); }'统计 SCSI 驱动函数调用:
bpftrace -e 'kprobe:scsi* { @[func] = count(); }'网络
按 PID 和进程名统计套接字 accept(2) 调用:
bpftrace -e 't:syscalls:sys_enter_accept* { @[pid, comm] = count(); }'按 PID 和进程名统计套接字 connect(2) 调用:
bpftrace -e 't:syscalls:sys_enter_connect { @[pid, comm] = count(); }'按用户栈调用轨迹统计套接字 connect(2) 调用:
bpftrace -e 't:syscalls:sys_enter_connect { @[ustack, comm] = count(); }'按方向、运行 CPU 的 PID 和进程名统计套接字发送/接收:
bpftrace -e 'k:sock_sendmsg,k:sock_recvmsg { @[func, pid, comm] = count(); }'按运行 CPU 的 PID 和进程名统计套接字发送/接收字节数:
bpftrace -e 'kr:sock_sendmsg,kr:sock_recvmsg /(int32)retval > 0/ { @[pid, comm] =
sum((int32)retval); }'按运行 CPU 的 PID 和进程名统计 TCP 连接:
bpftrace -e 'k:tcp_v*_connect { @[pid, comm] = count(); }'按运行 CPU 的 PID 和进程名统计 TCP 接受:
bpftrace -e 'k:inet_csk_accept { @[pid, comm] = count(); }'按运行 CPU 的 PID 和进程名统计 TCP 发送/接收:
bpftrace -e 'k:tcp_sendmsg,k:tcp_recvmsg { @[func, pid, comm] = count(); }'以直方图显示 TCP 发送字节数:
bpftrace -e 'k:tcp_sendmsg { @send_bytes = hist(arg2); }'以直方图显示 TCP 接收字节数:
bpftrace -e 'kr:tcp_recvmsg /retval >= 0/ { @recv_bytes = hist(retval); }'按类型和远程主机统计 TCP 重传(假设为 IPv4):
bpftrace -e 't:tcp:tcp_retransmit_* { @[probe, ntop(2, args->saddr)] = count(); }'统计所有 TCP 函数(会给 TCP 增加高开销):
bpftrace -e 'k:tcp_* { @[func] = count(); }'按运行 CPU 的 PID 和进程名统计 UDP 发送/接收:
bpftrace -e 'k:udp*_sendmsg,k:udp*_recvmsg { @[func, pid, comm] = count(); }'以直方图显示 UDP 发送字节数:
bpftrace -e 'k:udp_sendmsg { @send_bytes = hist(arg2); }'以直方图显示 UDP 接收字节数:
bpftrace -e 'kr:udp_recvmsg /retval >= 0/ { @recv_bytes = hist(retval); }'统计发送内核栈调用轨迹:
bpftrace -e 't:net:net_dev_xmit { @[kstack] = count(); }'显示每个设备的接收 CPU 直方图:
bpftrace -e 't:net:netif_receive_skb { @[str(args->name)] = lhist(cpu, 0, 128, 1); }'统计 ieee80211 层函数(会给数据包增加高开销):
bpftrace -e 'k:ieee80211_* { @[func] = count()'WARNING
原文中此条命令缺少闭合括号
},执行时需补全为bpftrace -e 'k:ieee80211_* { @[func] = count(); }'。
统计所有 ixgbevf 设备驱动函数(会给 ixgbevf 增加高开销):
bpftrace -e 'k:ixgbevf_* { @[func] = count(); }'统计所有 iwl 设备驱动跟踪点(会给 iwl 增加高开销):
bpftrace -e 't:iwlwifi:*,t:iwlwifi_io:* { @[probe] = count(); }'附录 D 部分练习题解答
以下是针对部分练习题的建议解答。^1^
第 2 章——方法论
问:什么是延迟? 答: 一种时间度量,通常指等待某事完成所花费的时间。在 IT 行业中,该术语的用法可能因上下文而异。
第 3 章——操作系统
问:列出线程离开 CPU 的原因。 答: 因 I/O 阻塞、因锁阻塞、调用 yield、时间片到期、被其他线程抢占、设备中断、退出。
第 6 章——CPU
问:计算平均负载…… 答: 34
第 7 章——内存
问:使用 Linux 术语,分页 和交换 有什么区别? 答: 分页是指内存页的移动;交换是指内存页与交换设备/文件之间的移入和移出。
问:描述内存使用率和饱和度。 答: 对于内存容量,使用率是指已使用且不可用的内存量,以占总可用内存的比例来衡量。这可以表示为百分比,类似于文件系统容量。饱和度是指对超出内存大小的可用内存的需求度量,这通常会调用内核例程来释放内存以满足此需求。
第 8 章——文件系统
问:逻辑 I/O 和物理 I/O 有什么区别? 答: 逻辑 I/O 是面向文件系统接口的;物理 I/O 是面向存储设备(磁盘)的。
问:解释文件系统写时复制 如何提高性能。 答: 由于随机写入可以写入到新位置,它们可以被组合(通过增加 I/O 大小)并顺序写出。这两个因素通常都能提高性能,具体取决于存储设备类型。
第 9 章——磁盘
问:描述当磁盘工作过载时会发生什么,包括对应用程序性能的影响。 答: 磁盘以持续的高利用率(高达 100%)运行,并伴随高度饱和(排队)。由于排队的可能性(可以被建模),它们的 I/O 延迟会增加。如果应用程序正在执行文件系统或磁盘 I/O,增加的延迟可能会损害应用程序性能,前提是这是一种同步 I/O 类型:读取或同步写入。这种情况也必须发生在应用程序的关键代码路径上,例如在处理请求时,而不是异步后台任务期间(这可能只会间接导致糟糕的应用程序性能)。通常,来自 I/O 延迟增加的反压 会控制 I/O 请求的速率,防止延迟无限制地增加。
第 11 章——云计算
问:描述从 OS 虚拟化的客户机观察物理系统的情况。 答: 取决于宿主机内核的实现,客户机可以看到所有物理资源(包括 CPU 和磁盘)的高级指标,并注意到它们何时被其他租户使用。泄露用户数据的指标应该被内核阻止。例如,某个 CPU 的利用率可能是可观察的(比如 50%),但导致该利用率的其他租户的进程 ID 和进程名称则是不可见的。
附录 E 系统性能名人录
了解我们所使用技术的创建者是非常有益的。以下是基于本书涉及技术的系统性能领域名人录。此名单灵感来源于 [Libes 89] 中的 Unix 名人录。对未能列入或归属不当的人士深表歉意。如果您希望深入了解这些人物和历史,请参阅章节参考文献以及 Linux 源码中列出的人员,包括 Linux 仓库历史记录和 Linux 源代码中的 MAINTAINERS 文件。我的 BPF 著作 [Gregg 19] 的致谢部分也列出了各种技术,特别是扩展 BPF、BCC、bpftrace、kprobes 和 uprobes,以及它们背后的人员。
- John Allspaw:容量规划 [Allspaw 08]。
- Gene M. Amdahl:计算机可扩展性的早期研究 [Amdahl 67]。
- Jens Axboe:CFQ I/O 调度器、fio、blktrace、io_uring。
- Brenden Blanco:BCC。
- Jeff Bonwick:发明了内核 slab 分配器,共同发明了用户级 slab 分配器,共同发明了 ZFS、kstat,最初开发了 mpstat。
- Daniel Borkmann:扩展 BPF 的共同创建者和维护者。
- Roch Bourbonnais:Sun Microsystems 系统性能专家。
- Tim Bray:编写了 Bonnie 磁盘 I/O 微基准测试,以 XML 闻名。
- Bryan Cantrill:共同创建了 DTrace;Oracle ZFS Storage Appliance Analytics。
- Rémy Card:ext2 和 ext3 文件系统的主要开发者。
- Nadia Yvette Chambers:Linux hugetlbfs。
- Guillaume Chazarain:Linux 的 iotop(1)。
- Adrian Cockcroft:性能著作 [Cockcroft 95][Cockcroft 98],Virtual Adrian (SE Toolkit)。
- Tim Cook:Linux 的 nicstat(1) 及其增强功能。
- Alan Cox:Linux 网络栈性能。
- Mathieu Desnoyers:Linux 跟踪工具包 (LTTng)、内核跟踪点,用户空间 RCU 的主要作者。
- Frank Ch. Eigler:SystemTap 的首席开发者。
- Richard Elling:静态性能调优方法。
- Julia Evans:性能和调试文档及工具。
- Kevin Robert Elz:DNLC。
- Roger Faulkner:为 UNIX System V 编写了 /proc,为 Solaris 编写了线程实现,以及 truss(1) 系统调用跟踪器。
- Thomas Gleixner:各种 Linux 内核性能工作,包括 hrtimers。
- Sebastian Godard:Linux 的 sysstat 软件包,包含众多性能工具,包括 iostat(1)、mpstat(1)、pidstat(1)、nfsiostat(1)、cifsiostat(1),以及增强版的 sar(1)、sadc(8)、sadf(1)(参见附录 B 中的指标)。
- Sasha Goldshtein:BPF 工具(argdist(8)、trace(8) 等),BCC 贡献。
- Brendan Gregg:nicstat(1)、DTraceToolkit、ZFS L2ARC、BPF 工具(execsnoop、biosnoop、ext4slower、tcptop 等)、BCC/bpftrace 贡献、USE 方法、热力图(延迟、利用率、亚秒偏移)、火焰图、火焰作用域、本书及前作 [Gregg 11a][Gregg 19],其他性能工作。
- Dr. Neil Gunther:通用可扩展性定律,CPU 利用率三元图,性能著作 [Gunther 97]。
- Jeffrey Hollingsworth:动态插桩 [Hollingsworth 94]。
- Van Jacobson:traceroute(8)、pathchar、TCP/IP 性能。
- Raj Jain:系统性能理论 [Jain 91]。
- Jerry Jelinek:Solaris Zones。
- Bill Joy:vmstat(1)、BSD 虚拟内存工作、TCP/IP 性能、FFS。
- Andi Kleen:Intel 性能,对 Linux 的众多贡献。
- Christoph Lameter:SLUB 分配器。
- William LeFebvre:编写了 top(1) 的第一个版本,启发了许多其他工具。
- David Levinthal:Intel 处理器性能专家。
- John Levon:OProfile。
- Mike Loukides:第一本关于 Unix 系统性能的书 [Loukides 90],该书开启或鼓励了基于资源(CPU、内存、磁盘、网络)分析的传统。
- Robert Love:Linux 内核性能工作,包括抢占。
- Mary Marchini:libstapsdt:各种语言的动态 USDT。
- Jim Mauro:《Solaris Performance and Tools》[McDougall 06a] 的合著者,《DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X, and FreeBSD》[Gregg 11] 的合著者。
^1^ 如果您管理的培训课程中学生收到了本教材的副本,请联系出版商或我本人以获取完整的练习解答列表。
# 17.1 附录
## 系统性能名人录
*Richard McDougall*:Solaris 微状态记账,合著《Solaris Performance and Tools》[McDougall 06a]。
*Marshall Kirk McKusick*:FFS,从事 BSD 相关工作。
*Arnaldo Carvalho de Melo*:Linux `perf(1)` 维护者。
*Barton Miller*:动态插桩 [Hollingsworth 94]。
*David S. Miller*:Linux 网络维护者和 SPARC 维护者。众多性能改进,以及对扩展 BPF 的支持。
*Cary Millsap*:Method R。
*Ingo Molnar*:O(1) 调度器、完全公平调度器、自愿内核抢占、ftrace、perf,以及实时抢占、互斥锁、futex、调度器性能分析、工作队列方面的工作。
*Richard J. Moore*:DProbes,kprobes。
*Andrew Morton*:fadvise,预读。
*Gian-Paolo D. Musumeci*:《System Performance Tuning》第2版 [Musumeci 02]。
*Mike Muuss*:`ping(8)`。
*Shailabh Nagar*:延迟记账,taskstats。
*Rich Pettit*:SE Toolkit。
*Nick Piggin*:Linux 调度域。
*Bill Pijewski*:Solaris `vfsstat(1M)`,ZFS I/O 节流。
*Dennis Ritchie*:Unix,及其最初的性能特性:进程优先级、交换、缓冲区缓存等。
*Alastair Robertson*:创建了 bpftrace。
*Steven Rostedt*:Ftrace,KernelShark,实时 Linux,自适应自旋互斥锁,Linux 追踪支持。
*Rusty Russell*:最初的 futex,各种 Linux 内核工作。
*Michael Shapiro*:联合创建 DTrace。
*Aleksey Shipilëv*:Java 性能专家。
*Balbir Singh*:Linux 内存资源控制器、延迟记账、taskstats、cgroupstats、CPU 记账。
*Yonghong Song*:BTF,以及扩展 BPF 和 BCC 方面的工作。
*Alexei Starovoitov*:扩展 BPF 的联合创建者和维护者。
*Ken Thompson*:Unix,及其最初的性能特性:进程优先级、交换、缓冲区缓存等。
*Martin Thompson*:机械共鸣。
---
*Linus Torvalds*:Linux 内核以及系统性能所必需的众多核心组件,Linux I/O 调度器,Git。
*Arjan van de Ven*:latencytop,PowerTOP,irqbalance,从事 Linux 调度器性能分析工作。
*Nitsan Wakart*:Java 性能专家。
*Tobias Waldekranz*:ply(第一个高级 BPF 追踪器)。
*Dag Wieers*:dstat。
*Karim Yaghmour*:LTT,推动 Linux 中的追踪技术。
*Jovi Zhangwei*:ktap。
*Tom Zanussi*:Ftrace hist 触发器。
*Peter Zijlstra*:自适应自旋互斥锁实现、硬中断回调框架,其他 Linux 性能工作。
## E.1 参考文献
- [Amdahl 67] Amdahl, G., “Validity of the Single Processor Approach to Achieving Large Scale Computing Capabilities,” AFIPS, 1967.
- [Libes 89] Libes, D., and Ressler, S., *Life with UNIX: A Guide for Everyone*, Prentice Hall, 1989.
- [Loukides 90] Loukides, M., *System Performance Tuning*, O’Reilly, 1990.
- [Hollingsworth 94] Hollingsworth, J., Miller, B., and Cargille, J., “Dynamic Program Instrumentation for Scalable Performance Tools,” Scalable High-Performance Computing Conference (SHPCC), May 1994.
- [Cockcroft 95] Cockcroft, A., *Sun Performance and Tuning*, Prentice Hall, 1995.
- [Cockcroft 98] Cockcroft, A., and Pettit, R., *Sun Performance and Tuning: Java and the Internet*, Prentice Hall, 1998.
- [Musumeci 02] Musumeci, G. D., and Loukidas, M., *System Performance Tuning*, 2nd Edition, O’Reilly, 2002.
- [McDougall 06a] McDougall, R., Mauro, J., and Gregg, B., *Solaris Performance and Tools: DTrace and MDB Techniques for Solaris 10 and OpenSolaris*, Prentice Hall, 2006.
- [Gunther 07] Gunther, N., *Guerrilla Capacity Planning*, Springer, 2007.
- [Allspaw 08] Allspaw, J., *The Art of Capacity Planning*, O’Reilly, 2008.
- [Gregg 11a] Gregg, B., and Mauro, J., *DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD*, Prentice Hall, 2011.
- [Gregg 19] Gregg, B., *BPF Performance Tools: Linux System and Application Observability*, Addison-Wesley, 2019.
---
## 词汇表
**ABI**:应用二进制接口。
**ACK**:TCP 确认。
**adaptive mutex(自适应互斥锁)**:一种互斥(互斥排他)同步锁类型。参见第5章 应用程序,第5.2.5节 并发与并行。
**address(地址)**:内存位置。
**address space(地址空间)**:虚拟内存上下文。参见第7章 内存。
**AMD**:处理器供应商。
**API**:应用编程接口。
**application(应用程序)**:一个程序,通常指用户态程序。
**ARM**:处理器供应商。
**ARP**:地址解析协议。
**array(数组)**:一组值的集合。这是编程语言的一种数据类型。底层语言通常将数组存储在连续的内存范围内,值索引指的是它们的偏移量。
**ASIC**:专用集成电路。
**associative array(关联数组)**:一种编程语言的数据类型,其值由任意键或多个键引用。
**AT&T**:美国电话电报公司,包含开发 Unix 的贝尔实验室。
**back end(后端)**:指数据存储和基础设施组件。Web 服务器是后端软件。参见前端。
**balanced system(均衡系统)**:没有瓶颈的系统。
**bandwidth(带宽)**:通信信道的频率范围,以赫兹为单位测量。在计算中,带宽用于描述通信信道的最大传输速率。它也经常被误用来描述当前的吞吐量(这是错误的)。
**BCC**:BPF 编译器集合。BCC 是一个包含 BPF 编译器框架以及许多 BPF 性能工具的项目。参见第15章。
**benchmark(基准测试)**:在计算中,基准测试是一种执行工作负载实验并测量其性能的工具:即基准测试结果。这些通常用于评估不同选项的性能。
**BIOS**:基本输入/输出系统:用于初始化计算机硬件并管理引导过程的固件。
**bottleneck(瓶颈)**:限制性能的事物。
**BPF**:伯克利数据包过滤器:1992年创建的一种内核轻量级技术,旨在提高数据包过滤的性能。自2014年以来,它已被扩展成为一个通用执行环境(参见 eBPF)。
**BSD**:伯克利软件发行版,Unix 的衍生版本。
**buffer(缓冲区)**:用于临时数据的内存区域。
**byte(字节)**:数字数据的单位。本书遵循行业标准,即一个字节等于八位,其中一位是一个零或一个一。
**C**:C 编程语言。
**cache hit(缓存命中)**:对可以从缓存内容中返回的数据请求。
**cache miss(缓存未命中)**:在缓存中未找到的数据请求。
**cache warmth(缓存温度)**:参见第2章 方法论,第2.3.14节 缓存中的热、冷和温缓存。
**CDN**:内容分发网络。
**client(客户端)**:网络服务的消费者,指客户端主机或客户端应用程序。
**command(命令)**:在 shell 中执行的程序。
**concurrency(并发)**:参见第5章 应用程序,第5.2.5节 并发与并行。
**contention(争用)**:对资源的竞争。
**core(核心)**:处理器上的执行流水线。这些可能作为单个 CPU 暴露给操作系统,或者通过超线程作为多个 CPU 暴露。
**CPI**:每指令周期数。参见第6章 CPU。
**CPU**:中央处理器。此术语指执行指令的功能单元集,包括寄存器和算术逻辑单元 (ALU)。现在它通常用于指代处理器或虚拟 CPU。
**CPU cross call(CPU 交叉调用)**:CPU 在多 CPU 系统上请求其他 CPU 工作的调用。交叉调用可以用于系统范围的事件,例如 CPU 缓存一致性调用。参见第6章 CPU。Linux 将这些称为“SMP 调用”。
**CPU cycle(CPU 周期)**:基于处理器时钟率的时间单位:对于 2 GHz,每个周期为 0.5 ns。周期本身是一个电信号,即电压的上升或下降,用于触发数字逻辑。
**cross call(交叉调用)**:参见 CPU 交叉调用。
**CSV**:逗号分隔值文件类型。
**CTSS**:兼容分时系统,最早的分时系统之一。
**daemon(守护进程)**:持续运行以提供服务的系统程序。
**datagram(数据报)**:参见段。
**debuginfo file(调试信息文件)**:符号和调试信息文件,由调试器和分析器使用。
**DEC**:数字设备公司。
**disk(磁盘)**:物理存储设备。另见 HDD 和 SSD。
**disk controller(磁盘控制器)**:管理直接连接的磁盘,使它们可被系统访问(直接访问或映射为虚拟磁盘)的组件。磁盘控制器可以内置于系统主板、作为扩展卡包含或内置于存储阵列中。它们支持一种或多种存储接口类型(例如 SCSI、SATA、SAS),并且通常与接口类型一起被称为主机总线适配器 (HBA),例如 SAS HBA。
**DNS**:域名服务。
**DRAM**:动态随机存取存储器,一种常用作主存的易失性存储器。
**duplex(双工)**:同时双向通信。
**dynamic instrumentation(动态插桩)**:动态插桩或动态追踪是一种可以插桩任何软件事件(包括函数调用和返回)的技术,通过实时修改指令文本并插入临时追踪指令来实现。
**dynamic tracing(动态追踪)**:可以指实现动态插桩的软件。
**eBPF**:扩展 BPF(参见 BPF)。eBPF 缩写最初描述的是 2014 年的扩展 BPF,它更新了寄存器大小、指令集、添加了映射存储,并限制了内核调用。到 2015 年,决定将 eBPF 直接称为 BPF。
**ECC**:纠错码。一种用于检测错误并修复某些类型错误(通常是单位错误)的算法。
**ELF**:可执行与可链接格式:可执行程序的常见文件格式。
**errno**:一个包含遵循标准 (POSIX.1-2001) 的数字形式最后一个错误的变量。
**Ethernet(以太网)**:一组用于物理层和数据链路层网络连接的标准。
**expander card(扩展卡)**:连接到系统的物理设备(卡),通常用于提供额外的 I/O 控制器。
**file descriptor(文件描述符)**:程序用来引用打开文件的标识符。
**firmware(固件)**:嵌入式设备软件。
**flame graph(火焰图)**:一组栈追踪的可视化。参见第2章 方法论。
**FPGA**:现场可编程门阵列。一种可重编程集成电路,在计算中通常用于加速特定操作。
**frame(帧)**:OSI 网络模型中数据链路层的消息(参见
# 17.1 附录
> [!INFO] 词汇表(续)
>
> 以下为系统性能相关术语的继续部分,承接上一节的内容。
### F
**frame**(帧):OSI 网络模型中数据链路层的消息(参见第 10 章第 10.2.3 节,协议栈)。
**FreeBSD**:一种开源的、类 Unix 的操作系统。
**front end**(前端):指最终用户界面和展示软件。Web 应用就是一种前端软件。参见 [[back end]]。
**fsck**:文件系统检查命令,用于在系统故障(如由于断电或内核崩溃)后修复文件系统。这个过程可能需要花费数小时。
### G
**Gbps**:千兆比特每秒(Gigabits per second)。
**GPU**:图形处理单元(Graphics processing unit)。它们也可用于其他工作负载,例如机器学习。
**GUI**:图形用户界面(Graphical user interface)。
### H
**HDD**:硬盘驱动器(Hard disk drive),一种旋转式磁性存储设备。参见第 9 章,磁盘。
**Hertz (Hz)**:赫兹,每秒的周期数。
**hit ratio**(命中率):常用于描述缓存性能:缓存命中次数与命中加未命中次数之和的比率,通常以百分比表示。越高越好。
**host**(主机):连接到网络的系统。也称为网络节点。
**HTTP**:超文本传输协议(Hyper Text Transfer Protocol)。
**hyperthread**(超线程):英特尔对 [[SMT]] 的实现。这是一种用于扩展 CPU 的技术,允许操作系统为一个物理核创建多个虚拟 CPU 并在它们上调度工作,处理器会尝试并行处理这些工作。
### I
**ICMP**:互联网控制消息协议(Internet Control Message Protocol)。由 `ping(1)` 使用(ICMP 回显请求/回复)。
**I/O**:输入/输出(Input/output)。
**IO Visor**:Linux 基金会项目,它在 GitHub 上托管了 bcc 和 bpftrace 仓库,并促进不同公司的 BPF 开发人员之间的协作。
**IOPS**:每秒 I/O 操作数(I/O operations per second),衡量 I/O 速率的指标。
**Intel**:一家处理器供应商。
**instance**(实例):虚拟服务器。云计算提供服务器实例。
**IP**:互联网协议(Internet Protocol)。主要版本为 IPv4 和 IPv6。参见第 10 章,网络。
**IPC**:可指以下两者之一:每周期指令数(instructions per cycle),一种底层 CPU 性能指标;或者进程间通信(inter-process communication),进程交换数据的一种方式。套接字(Sockets)就是一种进程间通信机制。
**IRIX**:由硅图公司(Silicon Graphics, Inc.,SGI)开发的一种派生自 Unix 的操作系统。
**IRQ**:中断请求(Interrupt request),一种发给处理器请求工作的硬件信号。参见第 3 章,操作系统。
### K
**Kbytes**:千字节。国际单位制(SI)将千字节定义为 1000 字节,但在计算机领域,千字节通常指 1024 字节(SI 称之为 kibibyte,千字节二进制单位)。在本书中,报告 Kbytes 的工具通常使用 1024($2^{10}$)字节的定义。
**kernel**(内核):系统上以特权模式运行以管理资源和用户级进程的核心程序。
**kernel-land**:内核软件。
**kernel-level**:内核执行使用的处理器特权模式。
**kernel-space**:内核的地址空间。
**kprobes**:一种用于内核级动态插桩的 Linux 内核技术。
### L
**latency**(延迟):花费在等待上的时间。在计算性能中,它通常用于描述资源 I/O 时间。延迟对性能分析很重要,因为它通常是衡量性能问题最有效的指标。如果没有进一步的限定词,测量它的确切位置可能会产生歧义。例如,“磁盘延迟”可能仅指在磁盘驱动程序队列中等待的时间,或者从应用程序的角度来看,它可能指等待磁盘 I/O 完成的整个时间,包括排队时间和服务时间。延迟受下限限制,而带宽受上限限制。
**local disks**(本地磁盘):直接连接到服务器并由服务器管理的磁盘。这些包括服务器机箱内部的磁盘以及通过存储传输直接连接的磁盘。
**logical processor**(逻辑处理器):虚拟 CPU 的另一种称呼。参见第 6 章,CPU。
**LRU**:最近最少使用(Least recently used)。参见第 2 章方法论中的第 2.3.14 节,缓存。
### M
**main board**(主板):容纳处理器和系统互连的电路板;也称为系统板。
**main memory**(主存):系统的主要内存存储,通常由 DRAM 实现。
**major fault**(主缺页):由存储设备(磁盘)提供服务的内存访问缺页。参见第 3 章,操作系统。
**malloc**:内存分配(Memory allocate)。这通常指执行分配的函数。
**Mbps**:兆比特每秒(Megabits per second)。
**Mbytes**:兆字节。国际单位制(SI)将兆字节定义为 1,000,000 字节,但在计算机领域,兆字节通常指 1,048,576 字节(SI 称之为 mebibyte,兆字节二进制单位)。在本书中,报告 Mbytes 的工具通常使用 1,048,576($2^{20}$)字节的定义。
**memory**(内存):参见 [[main memory]]。
**micro-benchmark**(微基准测试):用于测量单个或简单操作的基准测试。
**minor fault**(次缺页):由主存提供服务的内存访问缺页。参见第 3 章,操作系统。
**MMU**:内存管理单元(Memory management unit)。负责向 CPU 呈现内存以及执行虚拟地址到物理地址的转换。
**mutex**:互斥锁(Mutual exclusion lock)。它们可能成为性能瓶颈的来源,并且经常在性能问题中被调查。参见第 5 章,应用程序。
**mysqld**:MySQL 数据库的守护进程。
### N
**NVMe**:非易失性内存快车(Non-Volatile Memory express):一种用于存储设备的 PCIe 总线规范。
**observability**(可观测性):计算系统被观察的能力。这包括用于分析计算系统状态的实践和工具。
**off-CPU**(脱核):此术语指当前未在 CPU 上运行的线程,因此处于“脱核”状态,原因可能是由于在 I/O、锁、自愿休眠或其他事件上被阻塞。
**on-CPU**(在核):此术语指当前正在 CPU 上运行的线程。
### O
**operation rate**(操作速率):每时间间隔的操作数(例如,每秒操作数),其中可能包括非 I/O 操作。
**OS**:操作系统(Operating System)。包括用于管理资源和用户级进程的内核在内的软件集合。
### P
**packet**(包/分组):OSI 网络模型中网络层的网络消息(参见第 10.2.3 节)。
**page**(页):由内核和处理器管理的内存块。系统使用的所有内存都被划分为页,以便进行引用和管理。典型的页大小包括 4 Kbytes 和 2 Mbytes(取决于处理器)。
**pagefault**(缺页异常):当程序引用的内存位置其虚拟内存当前未映射到物理后备页时发生的系统陷阱。这是按需分配内存模型的正常结果。
**pagein/pageout**(页换入/页换出):由操作系统(内核)执行的功能,用于将内存块(页)移入和移出外部存储设备。
**parallel**(并行):参见第 5 章应用程序中的第 5.2.5 节,并发与并行。
**PC**:程序计数器(Program counter),一个指向当前正在执行的指令的 CPU 寄存器。
**PCID**:进程上下文 ID(Process-context ID),一种处理器/MMU 功能,用于用进程 ID 标记虚拟地址条目,以避免在上下文切换时进行刷新。
**PCIe**:外围组件互连快车(Peripheral Component Interconnect Express):一种通常用于存储和网络控制器的总线标准。
**PDP**:程序化数据处理器(Programmed Data Processor),由数字设备公司(Digital Equipment Corporation,DEC)制造的小型计算机系列。
**PEBS**:精确基于事件的采样(Precise event-based sampling,又称处理器基于事件的采样),一种英特尔处理器技术,与 [[PMCs]] 配合使用,以提供事件期间 CPU 状态的更精确记录。
**Performance engineer**(性能工程师):主要致力于计算机性能的技术人员:规划、评估、分析和改进。参见第 1 章引言中的第 1.3 节,活动。
**PID**:进程标识符(Process identifier)。操作系统为进程分配的唯一数字标识符。
**PMCs**:性能监控计数器(Performance Monitoring Counters):处理器上的特殊硬件寄存器,可以编程用于插桩底层 CPU 事件:周期、停顿周期、指令、内存加载/存储等。
**POSIX**:可移植操作系统接口(Portable Operating System Interface),由 IEEE 管理的一系列相关标准,用于定义 Unix API。这包括应用程序使用的文件系统接口,该接口通过系统调用或基于系统调用构建的系统库提供。
**process**(进程):程序的运行实例。多任务操作系统可以并发执行多个进程,并且可以将同一程序的多个实例作为不同的进程运行。一个进程包含一个或多个用于在 CPU 上执行的线程。
**processor ring**(处理器环):CPU 的一种保护模式。
**production**(生产环境):技术领域中使用的一个术语,用于描述真实客户请求的工作负载以及处理这些请求的环境。许多公司也有一个“测试”环境,其中包含合成工作负载,用于在生产部署之前进行测试。
**profiling**(性能剖析/画像):一种收集数据以表征目标性能的技术。一种常见的性能剖析技术是定时采样(参见 sampling)。
**PSI**:Linux 压力失速信息(pressure stall information),用于识别由资源引起的性能问题。
### R
**RCU**:读-拷贝-更新(Read-copy-update):一种 Linux 同步机制。
**real-time workload**(实时工作负载):具有固定延迟要求(通常是低延迟)的工作负载。
**registers**(寄存器):CPU 上的小型存储位置,直接由 CPU 指令用于数据处理。
**remote disks**(远程磁盘):服务器使用但连接到远程系统的磁盘(包括虚拟磁盘)。
**RFC**:意见征询稿(Request For Comments):互联网工程任务组(IETF)发布的公共文档,用于分享网络标准和最佳实践。RFC 用于定义网络协议:RFC 793 定义了 TCP 协议。
**RSS**:常驻集大小(Resident set size):一种主存的度量。
**ROI**:投资回报率(Return on investment),一种商业指标。
**run queue**(运行队列):CPU 调度器中等待轮到在 CPU 上运行的任务队列。实际上该队列可能实现为树结构,但仍使用运行队列这一术语。
**RX**:接收(Receive,用于网络中)。
### S
**sampling**(采样):一种可观测性方法,通过获取测量的子集(即样本)来理解目标。
**script**(脚本):在计算中,指可执行程序,通常较短且使用高级语言编写。
**SCSI**:小型计算机系统接口(Small Computer System Interface)。一种用于存储设备的接口标准。
**sector**(扇区):存储设备的数据单元大小,通常为 512 字节或 4 Kbytes。参见第 9 章,磁盘。
**segment**(段):OSI 网络模型中传输层的消息(参见第 10.2.3 节,协议栈)。
**server**(服务器):在网络中,指为网络客户端(如 HTTP 或数据库服务器)提供服务的网络主机。术语服务器也可以指物理系统。
**shell**:命令行解释器和脚本语言。
**SLA**:服务等级协议(Service level agreement)。
**SMP**:对称多处理(Symmetric multiprocessing),一种多处理器架构,其中多个相似的 CPU 共享同一主存。
**SMT**:同步多线程(Simultaneous multithreading),一种在核心上运行多个线程的处理器功能。参见 [[hyperthread]]。
**SNMP**:简单网络管理协议(Simple Network Management Protocol)。
**socket**(套接字):表示用于通信的网络端点的软件抽象。
**Solaris**:最初由 Sun Microsystems 开发的一种派生自 Unix 的操作系统,以可扩展性和可靠性著称,在企业环境中很流行。自从 Sun 被 Oracle 公司收购后,它已被更名为 Oracle Solaris。
**SONET**:同步光网络(Synchronous optical networking),一种用于光纤的物理层协议。
**SPARC**:一种处理器架构(源自可扩展处理器架构,scalable processor architecture)。
**SRE**:站点可靠性工程师(Site reliability engineer):专注于基础设施和可靠性的技术人员。SRE 作为事件响应的一部分,在较短的时间限制内处理性能问题。
**SSD**:固态驱动器(Solid-state drive),一种通常基于闪存的存储设备。参见第 9 章,磁盘。
**SSH**:安全外壳(Secure Shell)。一种加密的远程外壳协议。
**stack**(栈):在可观测性工具的上下文中,stack 通常是“栈追踪”(stack trace)的简称。
**stack frame**(栈帧):一种包含函数状态信息的数据结构,包括返回地址和函数参数。
**stack trace**(栈追踪):由跨越代码路径祖先的多个栈帧组成的调用栈。这些通常作为性能分析的一部分进行检查,特别是在 CPU 性能剖析中。
**static instrumentation/tracing**(静态插桩/追踪):带有预编译探针点的软件插桩。参见
# 17.1 附录
> [!INFO] 词汇表(续)
>
> 以下为系统性能相关词汇表的后续部分,涵盖从存储阵列到 ZFS 的相关技术术语。
---
**storage array(存储阵列)** 装在机箱中的磁盘集合,随后可附加到系统上。存储阵列通常提供各种功能以提高磁盘的可靠性和性能。
**struct(结构体)** 结构化对象,通常源自 C 编程语言。
**SunOS** Sun Microsystems 操作系统。后来被重新品牌化为 Solaris。
**SUT** 被测系统(System Under Test)。
**SVG** 可缩放矢量图形文件格式。
**SYN** TCP 同步。
**syscall** 参见 [[system call|系统调用]]。
**system call(系统调用)** 进程向内核请求特权操作的接口。参见第 3 章,操作系统。
**task(任务)** Linux 的可运行实体,可以是进程、多线程进程中的线程或内核线程。参见第 3 章,操作系统。
**TCP** 传输控制协议。最初在 RFC 793 中定义。参见第 10 章,网络。
**TENEX** TEN-EXtended 操作系统,基于 PDP-10 的 TOPS-10。
**thread(线程)** 程序执行实例的软件抽象,可被调度在 CPU 上运行。内核有多个线程,而一个进程包含一个或多个线程。参见第 3 章,操作系统。
**throughput(吞吐量)** 对于网络通信设备,吞吐量通常指以每秒比特数或每秒字节数表示的数据传输速率。在与统计分析结合使用时,特别是针对研究对象,吞吐量也可指每秒 I/O 完成次数(IOPS)。
**TLB** 传输后备缓冲器。虚拟内存系统上用于内存转换的缓存,由 MMU 使用(参见 [[MMU]])。
**TLS** 传输层安全:用于加密网络请求。
**TPU** 张量处理单元。一种由 Google 开发的用于机器学习的 AI 加速器 ASIC,以 TensorFlow(一个机器学习软件平台)命名。
**tracepoints(跟踪点)** 一种提供静态插桩的 Linux 内核技术。
**tracer(跟踪器)** 一种跟踪工具。参见 tracing。
**tracing(跟踪)** 基于事件的可观测性。
**tunable(可调参数)** 可调参数的简称。
**TX** 发送(Transmit,用于网络)。
**UDP** 用户数据报协议。最初在 RFC 768 中定义。参见第 10 章,网络。
**uprobes** 一种用于用户级动态插桩的 Linux 内核技术。
**us** 微秒。它应缩写为 μs;但是,您经常会看到它被写为“us”,尤其是在基于 ASCII 的性能工具输出中。(请注意,本书多次引用的 `vmstat(8)` 输出中包含一个 us 列,这是 user time 的缩写。)
**μs** 微秒。参见“us”。
**USDT** 用户级静态定义跟踪。这涉及程序员在应用程序代码中放置静态插桩,位于可提供有用探针的位置。
**user-land(用户态/用户域)** 指用户级软件和文件,包括 `/usr/bin`、`/lib` 等目录中的可执行程序。
**user-level(用户级别)** 用户态执行所使用的处理器特权模式。这是比内核更低的特权级别,拒绝直接访问资源,从而迫使用户级软件通过内核请求对这些资源的访问。
**user-space(用户空间)** 用户级进程的地址空间。
**variable(变量)** 编程语言使用的命名存储对象。
**vCPU** 虚拟 CPU。现代处理器可以在每个核心上暴露多个虚拟 CPU(例如,Intel 超线程)。
**VFS** 虚拟文件系统。内核用于支持不同文件系统类型的抽象。
**virtual memory(虚拟内存)** 主存的抽象,支持多任务处理和超售。
**VMS** 虚拟内存系统,由 DEC 开发的操作系统。
**workload(工作负载)** 描述对系统或资源的请求。
**x86** 基于 Intel 8086 的处理器架构。
**ZFS** 由 Sun Microsystems 创建的组合文件系统和卷管理器。
---
> [!NOTE] 页面留白
>
> 此处原书页面 intentionally left blank(刻意留白),已保留此说明。