观测工具
计数器
内核维护了各种统计数据,称为计数器,用于对事件计数。通常计数器实现为无符号的整型数,发生事件时递增。例如,有网络包接收的计数器,有磁盘I/O发生的计数器,也有系统调用执行的计数器。
计数器的使用可以认为是“零开销”的,因为它们默认就是开启的,而且始终由内核维护。唯一的使用开销是从用户空间读取它们的时候(可以忽略不计)。
系统级别
下面这些工具利用内核的计数器在系统软硬件的环境中检查系统级别的活动。
vmstat:虚拟内存和物理内存的统计,系统级别。
mpstat:每个CPU的使用情况。
iostat:网络接口的统计,TCP/IP栈的统计,以及每个连接的一些统计信息。
sar:各种各样的统计,能归档历史数据。
这些工具通常是系统全体用户可见的(非root用户)。统计出的数据也常常被监控软件用来绘图。
这些工具有一个使用惯例,即可选时间间隔和次数,例如,vmstat用一秒作为时间间隔,输出三次:
输出的第一行是自系统启动以来的信息统计,显示的是系统启动后整个时间的均值。随后的一行是一秒时间间隔的总结,显示的是当前的活动。至少,意图是这样:这个Linux版本在第一行对自启动以来的信息统计和当前值不做严格区别。
进程级别
下面这些工具是以进程为导向的,使用的是内核为每个进程维护的计数器。
ps:进程状态,显示进程的各种统计信息,包括内存和CPU的使用。
top:按一个统计 数据(如CPU)排序,显示排名高的进程。基于Solaris的系统对应的工具是prstat(1M)。
pmap:将进程的内存段和使用统计一起列出。
一般来说,上述这些工具是从/proc文件系统里读取统计信息的。
跟踪
跟踪收集每一个事件的数据以供分析。跟踪框架一般默认是不启用的,因为跟踪捕获数据会有CPU开销,另外还需要不小的存储空间来存放数据。这些开销会拖慢所跟踪的对象,在解释测量时间的时候需要加以考虑。
日志,包括系统日志,可以认为是一种默认开启的低频率跟踪。日志包括每一个事件的数据,虽然通常只针对偶发事件,如错误和警告。
以下是系统级别和进程级别的跟踪工具的例子。
系统级别
利用内核的跟踪设施,下面这些跟踪工具在系统软硬件的环境中检查系统级别的活动。
tcpdump:网络包跟踪(用libpcap库)。
snoop:为基于Solaris的系统打造的网络包跟踪工具。
blktrace:块I/O跟踪(Linux)
iosnoop:块I/O跟踪(基于DTrace)
execsnoop:跟踪新进程(基于DTrace)
dtruss:系统级别的系统调用缓冲跟踪(基于DTrace)
DTrace:跟踪内核的内部活动和所有资源的使用情况(不仅仅是网络和块I/O),支持静态和动态的跟踪。
SystemTap:跟踪内核的内部活动和所有资源的使用情况,支持静态和动态的跟踪。
perf:Linux性能事件,跟踪静态和动态的探针。
DTrace和SystemTap都是可编程环境,在它们之上可以构建系统级别的跟踪工具,在前面的列表中已经包括了一些。
进程级别
下面这些跟踪工具是以进程为导向的,基于的是操作系统提供的框架。
strace:基于Linux系统的系统调用跟踪。
truss:基于Solaris系统的系统调用跟踪。
gdb:源代码级别的调试器,广泛应用于Linux系统。
mdb:Solaris系统的一个具有可扩展性的调试器。
调试器能够检查每一个事件的数据,不过做这件事情时需要停止目标程序的执行,然后再启动。
诸如DTrace,SystemTap和perf这样的工具,虽然更合适归纳到系统级别一类中,但是它们都支持对单个进程做检查。
剖析(profiling)
剖析通过对目标收集采样或快照来归纳目标特征。
一个常见的例子就是CPU的使用率,对程序计数器采样,或跟踪栈来找到消耗CPU周期的代码路径。
剖析也能基于非计时的硬件事件,如CPU硬件缓存未命中或者总线活动。这可以显示出哪条代码路径负责任。
系统级别和进程级别
下面是一些剖析器的例子,这些工具所做的剖析都是基于时间并基于硬件缓存的。
oprofile:Linux系统剖析。
perf:Linux性能工具集,包含有剖析的子命令。
DTrace:程序化剖析,基于时间的剖析用自身的profile provider,基于硬件事件的剖析用cpc provider。
SystemTap:程序化剖析,基于时间的剖析用自身的timer tapset,基于硬件事件的剖析用自身perf tapset。
cachegrind:源自valgrind工具集,能对硬件缓存的使用做剖析,也能用kcachegrind做数据可视化。
Inter VTune Amplifier XE:Linux和Windows的剖析,拥有包括源代码浏览在内的图形界面。
Oracle Solaris Studio:用自带的性能分析器对Solaris和Linux做剖析,拥有包括源代码浏览在内的图形界面。
编程语言通常有自己的专用分析器,可以检查语言上下文。
监视
最广泛用于监视单一操作系统的工具是sar,来源于AT&T的UNIX。sar是基于计数器的,在预定的时间(通过cron)执行以记录系统计数器的状态。
sar工具支持用命令行来查看这些数据,例如:
[postgres@minion1 systune]$ sar
Linux 2.6.32-504.el6.x86_64 (minion1) 02/14/2016 _x86_64_ (4 CPU)
08:45:25 AM LINUX RESTART
08:50:02 AM CPU %user %nice %system %iowait %steal %idle
09:00:01 AM all 0.04 0.00 0.01 0.06 0.00 99.89
09:10:01 AM all 0.02 0.00 0.01 0.07 0.00 99.90
09:20:01 AM all 0.02 0.00 0.01 0.05 0.00 99.91
09:30:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
09:40:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
09:50:01 AM all 0.03 0.04 0.11 1.04 0.00 98.78
10:00:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
10:10:01 AM all 0.02 0.00 0.01 0.07 0.00 99.90
10:20:01 AM all 0.03 0.00 0.01 0.06 0.00 99.89
10:30:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
10:40:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
10:50:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
11:00:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
11:10:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
11:20:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
11:30:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
11:40:01 AM all 0.03 0.00 0.01 0.06 0.00 99.90
11:50:01 AM all 0.02 0.00 0.01 0.06 0.00 99.91
12:00:01 PM all 0.02 0.00 0.01 0.06 0.00 99.91
12:10:01 PM all 0.01 0.00 0.01 0.07 0.00 99.92
12:20:01 PM all 0.01 0.00 0.01 0.06 0.00 99.92
12:30:01 PM all 0.00 0.00 0.01 0.06 0.00 99.93
12:40:01 PM all 0.00 0.00 0.01 0.06 0.00 99.93
12:50:01 PM all 0.01 0.00 0.01 0.06 0.00 99.92
01:00:01 PM all 0.00 0.00 0.01 0.06 0.00 99.93
01:10:01 PM all 0.00 0.00 0.01 0.06 0.00 99.92
01:10:01 PM CPU %user %nice %system %iowait %steal %idle
01:20:01 PM all 0.01 0.00 0.01 0.06 0.00 99.92
01:30:01 PM all 0.00 0.00 0.01 0.07 0.00 99.92
01:40:01 PM all 0.00 0.00 0.01 0.07 0.00 99.92
01:50:01 PM all 0.01 0.00 0.01 0.07 0.00 99.91
02:00:01 PM all 0.00 0.00 0.01 0.07 0.00 99.92
02:10:02 PM all 0.03 0.00 0.01 0.07 0.00 99.89
02:20:01 PM all 0.04 0.00 0.01 0.06 0.00 99.89
02:30:01 PM all 0.03 0.00 0.01 0.08 0.00 99.87
02:40:01 PM all 0.04 0.00 0.01 0.06 0.00 99.89
02:50:01 PM all 0.04 0.00 0.02 0.11 0.00 99.83
03:00:01 PM all 0.04 0.00 0.01 0.06 0.00 99.89
03:10:01 PM all 0.03 0.00 0.01 0.07 0.00 99.89
03:20:01 PM all 0.04 0.00 0.01 0.06 0.00 99.89
03:30:01 PM all 0.03 0.00 0.01 0.05 0.00 99.91
03:40:01 PM all 0.04 0.00 0.01 0.04 0.00 99.91
03:50:01 PM all 0.03 0.00 0.01 0.06 0.00 99.90
04:00:01 PM all 0.04 0.00 0.01 0.06 0.00 99.89
04:10:01 PM all 0.04 0.00 0.01 0.06 0.00 99.89
04:20:01 PM all 0.03 0.00 0.01 0.06 0.00 99.90
Average: all 0.02 0.00 0.01 0.08 0.00 99.88
默认状态下,sar读取自己统计信息的归档数据(若开启)来打印历史统计信息。你可以指定时间间隔和次数,按照所指定的频率检查当前的活动。
sar可以报告很多的统计数据,但可能它并不覆盖所有你真正想要的东西。替代sar的选择,System Data Recorder和Collectl。
观测来源
系统性能统计的主要来源是:/proc、/sys和kstat。
Type Linux
进程级计数器 /proc
系统级计数器 /proc,/sys
设备驱动和调试信息 /sys
进程级跟踪 ptrace,uprobes
性能计数器 perf_event
网络跟踪 /libpcap
进程级延时指标 延时核算
系统级跟踪 tracepoints,kprobes,ftrace
/proc是一个提供内核统计信息的文件系统接口。/proc包含很多的目录,其中以进程ID命名的目录代表的就是那个进程。这些目录下的众多问题包含了进程的信息和统计数据,有内核数据结构映射而来。在Linux中,/proc还有其它的文件,提供系统级别的统计数据。
/proc有内核动态创建,不需要任何存储设备 (在内存中运行)。多数文件是只读的,为观测工具提供统计数据。一部分文件是可写的,用于控制进程和内核的行为。
该文件系统是很便利的:这是一个直观的框架,将内核统计数据用目录树的形式暴露给用户空间,编程接口就是众说周知的POSIX的文件系统调用,即open()、read()、close()。
Linux在/proc下有各种进程统计的文件。
[postgres@minion1 proc]$ ls -F
1/ 1887/ 21/ 2443/ 2597/ 2733/ 2811/ 38/ 50/ 6/ 83/ filesystems modules timer_list
10/ 19/ 2130/ 2447/ 2599/ 2740/ 2821/ 39/ 51/ 60/ 84/ fs/ mounts@ timer_stats
11/ 1910/ 2142/ 2448/ 26/ 2741/ 29/ 4/ 5163/ 61/ 85/ interrupts mtd tty/
117/ 1911/ 2143/ 2449/ 2601/ 2743/ 3/ 40/ 5166/ 62/ 9/ iomem mtrr uptime
118/ 1912/ 2153/ 2450/ 2602/ 2747/ 30/ 409/ 517/ 63/ acpi/ ioports net@ version
12/ 1913/ 2196/ 2451/ 2604/ 2751/ 301/ 41/ 5186/ 64/ asound/ irq/ pagetypeinfo vmallocinfo
13/ 1935/ 22/ 25/ 2672/ 2753/ 302/ 411/ 5188/ 65/ buddyinfo kallsyms partitions vmstat
14/ 2/ 2203/ 2509/ 2674/ 2758/ 303/ 42/ 52/ 66/ bus/ kcore sched_debug zoneinfo
146/ 20/ 2260/ 2515/ 2681/ 2771/ 304/ 428/ 5269/ 67/ cgroups keys schedstat
15/ 2038/ 2269/ 2522/ 2685/ 2780/ 305/ 429/ 53/ 68/ cmdline key-users scsi/
1574/ 2039/ 2279/ 2533/ 27/ 2782/ 306/ 43/ 5333/ 69/ cpuinfo kmsg self@
1575/ 2041/ 23/ 2548/ 2704/ 2783/ 31/ 44/ 54/ 7/ crypto kpagecount slabinfo
16/ 2042/ 2374/ 2571/ 2708/ 2791/ 32/ 45/ 55/ 70/ devices kpageflags softirqs
1618/ 2043/ 2399/ 2572/ 2714/ 2795/ 33/ 46/ 56/ 78/ diskstats loadavg stat
17/ 2060/ 24/ 2589/ 2720/ 28/ 34/ 47/ 57/ 79/ dma locks swaps
1794/ 2071/ 2400/ 2591/ 2726/ 2801/ 35/ 48/ 585/ 8/ driver/ mdstat sys/
18/ 2077/ 2413/ 2593/ 2729/ 2807/ 36/ 49/ 588/ 80/ execdomains meminfo sysrq-trigger
1857/ 2091/ 2442/ 2595/ 2731/ 2809/ 37/ 5/ 59/ 81/ fb misc sysvipc/
[root@minion1 ~]# ls -F /proc/2091
attr/ cmdline environ limits mounts oom_adj root@ stack task/
autogroup comm exe@ loginuid mountstats oom_score sched stat wchan
auxv coredump_filter fd/ maps net/ oom_score_adj schedstat statm
cgroup cpuset fdinfo/ mem ns/ pagemap sessionid status
clear_refs cwd@ io mountinfo numa_maps personality smaps syscall
具体可用的文件列表取决于内核的版本和内核的CONFIG选项。
与进程性能观测相关的问题如下:
limits:实际的资源限制。
maps:映射的内存区域。
sched:CPU调度器的各种统计。
schedstat:CPU运行时间、延时和时间分片。
smaps:映射内存区域的使用统计。
stat:进程状态和统计,包括总的CPU和内存的使用情况。
statm:以页为单位 的内存使用总结。
status:stat和statm的信息,用户可读。
task:每个任务的统计目录。
Linux将/proc延伸到了系统级别的统计,包括下面这些额外的文件和目录:
[root@minion1 ~]# cd /proc/;ls -Fd [a-z]*
acpi/ cpuinfo execdomains ioports kmsg meminfo net@ self@ sysrq-trigger version
asound/ crypto fb irq/ kpagecount misc pagetypeinfo slabinfo sysvipc/ vmallocinfo
buddyinfo devices filesystems kallsyms kpageflags modules partitions softirqs timer_list vmstat
bus/ diskstats fs/ kcore loadavg mounts@ sched_debug stat timer_stats zoneinfo
cgroups dma interrupts keys locks mtd schedstat swaps tty/
cmdline driver/ iomem key-users mdstat mtrr scsi/ sys/ uptime
与性能观测相关的系统级别的文件如下:
cpuinfo:物理处理器信息,包含所有虚拟CPU、型号、时钟频率和缓存大小。
diskstats:对于所有磁盘设备的磁盘I/O统计。
interrupts:每个CPU的中断计数器。
loadavg:负载平均值。
meminfo:系统内存使用明细。
net/dev:网络接口统计。
net/tcp:活跃的TCP套接字信息。
schedstat:系统级别的CPU调度器统计。
self:关联当前进程ID路径的符号链接,为了使用方便。
slabinfo:内核slab分配器缓存统计。
stat:内核和系统资源的统计,CPU、磁盘、分页、交换区、进程。
zoneinfo:内存区信息。
/proc文件一般是文本格式,通过shell脚本工具可以容易地用命令行读取。例如:
cat /proc/meminfo
[root@localhost ~]# cat /proc/meminfo
MemTotal: 11676096 kB
MemFree: 3055008 kB
Buffers: 10436 kB
Cached: 38700 kB
SwapCached: 0 kB
Active: 24744 kB
Inactive: 36160 kB
Active(anon): 11784 kB
Inactive(anon): 256 kB
Active(file): 12960 kB
Inactive(file): 35904 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 2097144 kB
SwapFree: 2097144 kB
Dirty: 88 kB
Writeback: 0 kB
AnonPages: 11776 kB
Mapped: 6424 kB
Shmem: 268 kB
Slab: 65284 kB
SReclaimable: 9748 kB
SUnreclaim: 55536 kB
KernelStack: 984 kB
PageTables: 1556 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 3740888 kB
Committed_AS: 62676 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 314624 kB
VmallocChunk: 34359419872 kB
HardwareCorrupted: 0 kB
AnonHugePages: 0 kB
HugePages_Total: 4096
HugePages_Free: 4096
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 8128 kB
DirectMap2M: 2611200 kB
DirectMap1G: 9437184 kB
/sys
Linux还提供了一个sysfs文件系统,挂载在/sys,这是在2.6内核引入的,为内核统计提供一个基于目录的结构。与/proc不同的是,/sys经过一段时间的发展,把各种系统信息放在了顶层目录。sysfs最初是设计用于提供设备驱动的统计数据,不过现在已经扩展到了提供所有的统计类型。
下面是CPU0的/sys文件列表:
find /sys/devices/system/cpu/cpu0 –type f
[root@localhost ~]# find /sys/devices/system/cpu/cpu0/ -type f
/sys/devices/system/cpu/cpu0/crash_notes
/sys/devices/system/cpu/cpu0/cache/index0/type
/sys/devices/system/cpu/cpu0/cache/index0/level
/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
/sys/devices/system/cpu/cpu0/cache/index0/physical_line_partition
/sys/devices/system/cpu/cpu0/cache/index0/ways_of_associativity
/sys/devices/system/cpu/cpu0/cache/index0/number_of_sets
/sys/devices/system/cpu/cpu0/cache/index0/size
/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_map
/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list
/sys/devices/system/cpu/cpu0/cache/index1/type
/sys/devices/system/cpu/cpu0/cache/index1/level
/sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size
/sys/devices/system/cpu/cpu0/cache/index1/physical_line_partition
/sys/devices/system/cpu/cpu0/cache/index1/ways_of_associativity
/sys/devices/system/cpu/cpu0/cache/index1/number_of_sets
/sys/devices/system/cpu/cpu0/cache/index1/size
/sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_map
/sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_list
/sys/devices/system/cpu/cpu0/cache/index2/type
/sys/devices/system/cpu/cpu0/cache/index2/level
/sys/devices/system/cpu/cpu0/cache/index2/coherency_line_size
/sys/devices/system/cpu/cpu0/cache/index2/physical_line_partition
/sys/devices/system/cpu/cpu0/cache/index2/ways_of_associativity
/sys/devices/system/cpu/cpu0/cache/index2/number_of_sets
/sys/devices/system/cpu/cpu0/cache/index2/size
/sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_map
/sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_list
/sys/devices/system/cpu/cpu0/topology/physical_package_id
/sys/devices/system/cpu/cpu0/topology/core_id
/sys/devices/system/cpu/cpu0/topology/thread_siblings
/sys/devices/system/cpu/cpu0/topology/thread_siblings_list
/sys/devices/system/cpu/cpu0/topology/core_siblings
/sys/devices/system/cpu/cpu0/topology/core_siblings_list
上面列出的文件都是关于CPU硬件缓存的。下面的输出显示的是它们的内容(用了grep,,所以连同文件名也包括在输出中):
grep ./sys/devices/system/cpu/cpu0/cache/index*/level
[root@localhost ~]# grep . /sys/devices/system/cpu/cpu0/cache/index*/level
/sys/devices/system/cpu/cpu0/cache/index0/level:1
/sys/devices/system/cpu/cpu0/cache/index1/level:1
/sys/devices/system/cpu/cpu0/cache/index2/level:2
grep ./sys/devices/system/cpu/cpu0/cache/index*/size
[root@localhost ~]# grep . /sys/devices/system/cpu/cpu0/cache/index*/size
/sys/devices/system/cpu/cpu0/cache/index0/size:64K
/sys/devices/system/cpu/cpu0/cache/index1/size:64K
/sys/devices/system/cpu/cpu0/cache/index2/size:512K
CPU0有两个L1缓存,每个都是64KB,还有一个512KB的L2缓存。
DTrace
DTrace是一个囊括了编程语言和工具的观测框架,,在Solaris和Linux系统中,DTrace都可以用来作为性能观测工具的扩展。
通过称为探针的指令点,DTrace可以观察所有用户级和内核级的代码。当探针命中时,就能执行D语言编写的任意action。action可以包括计数事件、记录时间戳、执行计划。打印数据和数据汇总。当跟踪开启时,这些action的执行都可以是实时的。
DTrace的设计是生产环境安全的,拥有最小的性能开销。
DTrace同时支持静态跟踪和动态跟踪 ,两者功能互补。静态探针有文档完备且稳定的接口,动态探针提供所需的近乎无限的可观测性。
DTrace能动态跟踪函数的入口和返回,以及在用户空间的指令。
探针
DTrace探针是以四元组命名的:
provider:module:function:name
provider是一些相关探针的集合,与软件库的概念相似。module和function是动态产生的,标记探针指示的代码位置。name是探针的名字。
当指定这些的时候,还可以使用通配符(“*”)。留空的字段(“::”)相当于通配(“:*:”)。当探针指定好时,留空的字段也可以省略(例如,“:::BEGIN”==”BEGIN”)。
例如:
io:::start
这是io provider的start探针。module和function字段都留空,因此这匹配的是所有位置上的start探针。
provider
可用的DTrace provider取决于你的DTrace和操作系统的版本。可能如下:
syscall:系统调用自陷表。
vminfo:虚拟内存统计。
sysinfo:系统统计。
profile:任意频率的采样。
sched:内核调度事件。
proc:进程级别事件,创建,执行,退出。
io:块设备接口跟踪(磁盘I/O)
pid:用户级别动态跟踪。
tcp:TCP协议事件,连接,发送和接收。
ip:IP协议事件,发送和接收。
fbt:内核级别动态跟踪。
参数
探针通过一组称为参数的变量来提供数据。参数的使用取决于provider。
系统调用的provider给每一个系统调用都做了入口和返回的探针。
入口:arg0……argN,系统调用的参数
返回:arg0或arg1,返回值,error也会设置。
CPU
对每个CPU,检查一下内容:
使用率:CPU繁忙的时间(未在空闲线程中)。
饱和度:可运行线程排队等待CPU的程度。
错误:CPU错误,包括可改正错误。
性能监控
性能监控可以发现一段时间内活跃的问题和行为模式。关键的CPU指标如下
使用率:繁忙百分比。
饱和度:从系统负载推算出来的运行队列长度,或者是线程调度器延时的数值。
静态性能调优
静态性能调优关注配置环境的问题。关于CPU性能,检查下列方面的静态配置:
有多少CPU可以?是核吗?还是硬件线程?
CPU的架构师单处理器还是多处理器?
CPU缓存的大小是多少?是共享的吗?
CPU时钟频率是多少?是动态的吗?这些动态特性在BIOS启动了吗?
BIOS里启动或者禁用了其它什么CPU相关的特性?
这款型号的处理器有什么性能问题(bug)?出现在处理器勘误表上了吗?
这个BIOS固件版本有什么性能问题(bug)吗?
有软件的CPU使用限制(资源控制)吗?是什么?
这些问题的答案可能暴露之前忽视的配置选择。
CPU绑定
一个CPU性能调优的方法是把进程和线程绑定在单个CPU或者一组CPU上。这可以增加进程的CPU缓存温度,提高他的内存I/O性能。对NUMA系统这可以提高内存本地性,同样也提高性能。
这个方法有一下两个实现方式。
进程绑定:配置一个进程只跑在单个CPU上,或者预定义CPU组中的一个。
独占CPU组:分成一组CPU,让这些CPU只能运行指定的进程。这可以更大地提升CPU缓存效率,因为当进程空闲时,其它进程不能使用CPU,保证了缓存的温度。
在Linux的系统上,独占CPU组可以通过cpuset实现。
分析
基于Linux系统的CPU性能分析工具
uptime 平均负载
vmstat 包括系统范围的CPU瓶颈负载
mpstat 单个CPU统计信息
sar 历史统计信息
ps 进程状态
top 监控每个进程/线程CPU用量
pidstat 每个进程/线程CPU用量分解
time 给一个命令计时,带CPU用量分解
DTrace,perf CPU剖析和跟踪
perf CPU性能计数器分析
uptime是几个打印系统平均负载的工具之一:
[root@minion1 scripts]# numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 16334 MB
node 0 free: 14329 MB
node distances:
node 0
0: 10
[root@minion1 scripts]# uptime
11:53:11 up 3:09, 2 users, load average: 0.00, 0.00, 0.00
[root@minion1 scripts]# uptime
11:54:22 up 3:10, 2 users, load average: 1.38, 0.31, 0.10
[root@minion1 scripts]# uptime
11:54:52 up 3:10, 2 users, load average: 4.07, 1.08, 0.37
[root@minion1 scripts]# uptime
11:55:48 up 3:11, 3 users, load average: 6.05, 2.15, 0.77
最后三个数字是1、5、15分钟内的平均负载。通过比较这三个数字,可以判断负载在15分钟内是在上升,下降,还是平稳。
平均负载(平均负载是对CPU需求的度量 )
平均负载是一段时间内可运行进程数的平均值。例如,一小时内的平均负载为10,意味着(对单CPU系统)在那个小时内的任意时间预期有1个进程在运行,另外还有9个就绪运行(例如,并未阻塞等待I/O),等待CPU。
举一个现代的例子,一个有64颗CPU的系统的平均负载为128。这意味着每个CPU上有一个线程在运行,还有一个线程在等待。而同样的系统,如果平均负载为10,则代表还有很大的余量,在所有CPU跑满前还可以运行54个消耗型线程。
平均负载表示了对CPU资源的需求,通过汇总正在运行的线程数(使用率)和正在排队等待运行的线程数(饱和度)计算得出。计算平均负载的一个新方法是把使用率加上线程调度器延时得出,而不是去取样队列长度,从而提高精度。
这个值的意义为,平均负载大于CPU数量表示CPU不足以服务线程,有些线程在等待。如果平均负载小于CPU数量,这(很可能)代表还有一些余量,线程可以在它们想要的时候在CPU上运行。
这三个平均负载值是指数衰减移动平均数,反映了1、5、15分钟以上(时间实际上是指数移动总和里使用的常数)的负载。
Linux平均负载
Linux目前把在不可中断状态执行磁盘I/O的任务也计入了平均负载。这意味着平均负载再也不能单用来表示CPU余量或者饱和度,因为不能单从这个值推断出CPU或者磁盘负载。由于负载可能会在CPU和磁盘之间不断变化,比较这三个平均负载数值也变得困难了。
另外一种包含其它资源负载的方法是为每一种类型的资源分别使用不同的平均负载。在Linux上最好通过一些其它的指标了解CPU负载,例如vmstat和mpstat提供的一些数据。
vmstat
虚拟内存统计信息命令,vmstat,在最后几列打印了系统全局范围的CPU平均负载,另外在第一列还有可运行线程数。下面是Linux版本的一个示例输出:
[root@minion1 scripts]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 2 0 14337416 165388 1351916 0 0 14 23 16 41 0 0 98 2 0
1 1 0 14335804 165396 1353508 0 0 1104 892 638 2368 1 1 74 24 0
0 1 0 14333944 165396 1355220 0 0 976 712 624 2166 1 1 70 28 0
0 3 0 14332208 165396 1356700 0 0 944 800 576 2157 1 1 73 25 0
0 2 0 14330844 165396 1358292 0 0 864 704 577 2082 1 0 75 24 0
0 1 0 14329232 165396 1359432 0 0 984 680 522 1987 1 1 74 24 0
0 3 0 14327744 165404 1360904 0 0 752 772 594 2155 1 1 71 28 0
输出的第一行是系统启动以来的总结信息,Linux上的r列除外—这个是显示当前值的。输出列如下:
r:运行队列长度—可运行线程的总数。
us:用户态时间。
sy:系统态时间(内核)。
id:空闲。
wa:等待I/O,即线程被阻塞等待磁盘I/O时的CPU空闲时间。
st:偷取,CPU在虚拟化的环境下在其它租户上的开销。
这些值都是所有CPU的系统平均数,r除外,这是总数。
在Linux上,r列代表所有等待的加上正在运行的线程数。
mpstat
多处理器统计信息工具mpstat,能够报告每个CPU的统计信息。下面是Linux版本的一些示例输出:
[root@minion1 scripts]# mpstat -P ALL 1
Linux 2.6.32-504.el6.x86_64 (minion1) 02/17/2016 _x86_64_ (4 CPU)
02:31:33 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
02:31:34 PM all 0.75 0.00 0.50 24.56 0.00 0.00 0.00 0.00 74.19
02:31:34 PM 0 1.01 0.00 1.01 65.66 0.00 1.01 0.00 0.00 31.31
02:31:34 PM 1 0.00 0.00 1.00 16.00 0.00 0.00 0.00 0.00 83.00
02:31:34 PM 2 2.00 0.00 0.00 10.00 0.00 0.00 0.00 0.00 88.00
02:31:34 PM 3 0.00 0.00 0.00 6.00 0.00 0.00 0.00 0.00 94.00
02:31:34 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
02:31:35 PM all 0.50 0.00 0.25 26.82 0.00 0.00 0.00 0.00 72.43
02:31:35 PM 0 2.02 0.00 0.00 71.72 0.00 0.00 0.00 0.00 26.26
02:31:35 PM 1 0.00 0.00 0.00 15.31 0.00 0.00 0.00 0.00 84.69
02:31:35 PM 2 0.00 0.00 0.99 15.84 0.00 0.00 0.00 0.00 83.17
02:31:35 PM 3 0.00 0.00 0.00 4.04 0.00 0.00 0.00 0.00 95.96
02:31:35 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
02:31:36 PM all 0.50 0.00 0.50 25.81 0.00 0.00 0.00 0.00 73.18
02:31:36 PM 0 1.01 0.00 1.01 79.80 0.00 0.00 0.00 0.00 18.18
02:31:36 PM 1 0.99 0.00 0.99 16.83 0.00 0.00 0.00 0.00 81.19
02:31:36 PM 2 0.00 0.00 0.00 7.00 0.00 0.00 0.00 0.00 93.00
02:31:36 PM 3 0.00 0.00 0.00 1.98 0.00 0.00 0.00 0.00 98.02
选项 –P ALL用来打印每个CPU的报告。mpstat默认只打印系统级别的总结信息(所有)。输出列如下:
CPU:逻辑CPU ID,或者all表示总结信息。
%usr:用户态时间。
%nice:以nice优先级运行的进程用户态时间。
%sys:系统态时间(内核)。
%iowait:I/O等待。
%irq:硬件中断CPU用量。
%soft:软件中断CPU用量。
%steal:耗费在服务其它租户的时间。
%guest:花在访客虚拟机的时间。
%idle:空闲。
重要列有%usr,%sys和%idle。这些显示了每个CPU的用量以及用户态和内核态的时间比例。这同样也能表明“热”CPU—那些跑到100%使用率(%usr + %sys)的CPU,而其它CPU并未跑满—可能由单线程应用程序的负载或者设备中断映射造成。
sar
系统活动报告器,sar,可以用来观察当前的活动,以及配置用以归档和报告历史统计信息。
Linux版本有一下选项:
-P ALL:与mpstat的 –P ALL 选项相同。
[root@minion1 scripts]# sar -P ALL
Linux 2.6.32-504.el6.x86_64 (minion1) 02/17/2016 _x86_64_ (4 CPU)
08:44:07 AM LINUX RESTART
08:50:02 AM CPU %user %nice %system %iowait %steal %idle
09:00:01 AM all 0.02 0.00 0.01 0.09 0.00 99.88
09:00:01 AM 0 0.07 0.00 0.01 0.36 0.00 99.55
09:00:01 AM 1 0.01 0.00 0.02 0.00 0.00 99.97
09:00:01 AM 2 0.00 0.00 0.01 0.00 0.00 99.99
09:00:01 AM 3 0.00 0.00 0.00 0.00 0.00 100.00
09:00:01 AM CPU %user %nice %system %iowait %steal %idle
09:10:01 AM all 0.02 0.00 0.01 0.08 0.00 99.88
09:10:01 AM 0 0.04 0.00 0.01 0.33 0.00 99.61
09:10:01 AM 1 0.00 0.00 0.02 0.00 0.00 99.98
09:10:01 AM 2 0.00 0.00 0.01 0.00 0.00 99.98
09:10:01 AM 3 0.03 0.00 0.00 0.00 0.00 99.97
09:10:01 AM CPU %user %nice %system %iowait %steal %idle
09:20:01 AM all 0.02 0.00 0.01 0.10 0.00 99.87
09:20:01 AM 0 0.07 0.00 0.01 0.39 0.00 99.52
09:20:01 AM 1 0.02 0.00 0.02 0.00 0.00 99.96
09:20:01 AM 2 0.00 0.00 0.01 0.00 0.00 99.99
09:20:01 AM 3 0.00 0.00 0.00 0.00 0.00 100.00
-u:与mpstat的默认输出相同,仅包括系统范围的平均值。
-q:包括运行队列长度列runq-sz(等待数加上运行数,与vmstat的r列相同)和平均负载。
[root@minion1 scripts]# sar -q
Linux 2.6.32-504.el6.x86_64 (minion1) 02/17/2016 _x86_64_ (4 CPU)
08:44:07 AM LINUX RESTART
08:50:02 AM runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15
09:00:01 AM 0 255 0.00 0.00 0.00
09:10:01 AM 0 255 0.00 0.00 0.00
09:20:01 AM 0 255 0.00 0.00 0.00
09:30:01 AM 0 255 0.00 0.00 0.00
09:40:01 AM 0 255 0.00 0.00 0.00
09:50:01 AM 0 256 0.14 0.05 0.02
10:00:01 AM 0 258 0.00 0.00 0.00
10:10:01 AM 0 268 0.07 0.03 0.01
10:20:01 AM 0 275 0.00 0.00 0.00
10:30:01 AM 0 269 0.00 0.00 0.00
10:40:01 AM 0 271 0.00 0.04 0.00
10:50:01 AM 0 263 0.00 0.01 0.00
11:00:01 AM 0 263 0.00 0.00 0.00
11:10:01 AM 0 263 0.00 0.00 0.00
11:20:01 AM 0 263 0.00 0.00 0.00
11:30:01 AM 0 263 0.00 0.00 0.00
11:40:01 AM 0 263 0.00 0.00 0.00
11:50:01 AM 0 263 0.00 0.00 0.00
12:00:01 PM 0 291 7.15 4.88 2.22
12:10:01 PM 0 271 0.07 1.76 2.16
12:20:01 PM 0 271 0.00 0.23 1.12
12:30:01 PM 0 271 0.02 0.03 0.57
12:40:01 PM 0 271 0.00 0.00 0.28
12:50:01 PM 0 271 0.00 0.00 0.13
01:00:01 PM 0 271 0.00 0.00 0.05
01:10:01 PM 0 271 0.00 0.00 0.01
ps
进程状态命令,ps列出了所有进程的细节信息,包括CPU用量统计信息。例如:
[root@minion1 scripts]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 19364 1540 ? Ss 08:43 0:00 /sbin/init
root 2 0.0 0.0 0 0 ? S 08:43 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 08:43 0:00 [migration/0]
root 4 0.0 0.0 0 0 ? S 08:43 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S 08:43 0:00 [stopper/0]
root 6 0.0 0.0 0 0 ? S 08:43 0:00 [watchdog/0]
root 7 0.0 0.0 0 0 ? S 08:43 0:00 [migration/1]
root 8 0.0 0.0 0 0 ? S 08:43 0:00 [stopper/1]
root 9 0.0 0.0 0 0 ? S 08:43 0:00 [ksoftirqd/1]
root 10 0.0 0.0 0 0 ? S 08:43 0:00 [watchdog/1]
postgres 4719 0.0 0.0 262712 12964 pts/0 S 11:52 0:00 /usr/local/pg8k/bin/postgres -D ../data
postgres 4721 0.0 0.8 262828 131828 ? Ss 11:52 0:02 postgres: checkpointer process
postgres 4722 0.0 0.0 262712 15640 ? Ss 11:52 0:00 postgres: writer process
postgres 4723 0.0 0.0 262712 5172 ? Ss 11:52 0:01 postgres: wal writer process
postgres 4724 0.0 0.0 263132 1776 ? Ss 11:52 0:00 postgres: autovacuum launcher process
postgres 4725 0.0 0.0 117996 988 ? Ss 11:52 0:01 postgres: stats collector process
root 4764 0.0 0.0 98376 4340 ? Ss 11:55 0:00 sshd: root@pts/1
root 4767 0.0 0.0 108472 1848 pts/1 Ss 11:55 0:00 -bash
root 4787 0.1 0.0 15040 1300 pts/1 S+ 11:55 0:19 top
postfix 4980 0.0 0.0 81408 3824 ? S 13:43 0:00 pickup -l -t fifo -u
postgres 5160 1.2 0.0 42044 1732 pts/0 S+ 15:07 0:01 ./pgbench -h localhost -p 5432 -d postgres -c 4 -T 600
postgres 5162 0.9 0.2 263720 39612 ? Ss 15:07 0:01 postgres: postgres postgres ::1(50073) COMMIT
postgres 5163 0.9 0.2 263720 39604 ? Ds 15:07 0:01 postgres: postgres postgres ::1(50074) COMMIT
postgres 5164 0.9 0.2 263720 39380 ? Ss 15:07 0:01 postgres: postgres postgres ::1(50075) COMMIT
postgres 5165 0.9 0.2 263720 39692 ? Ss 15:07 0:01 postgres: postgres postgres ::1(50076) COMMIT
root 5174 0.0 0.0 110240 1128 pts/2 R+ 15:10 0:00 ps aux
aux选项列出了所有的用户(a),还有面向用户的扩展信息(u),以及没有终端的进程(x)。终端在电传打字机(TTY)一列。
[root@minion1 scripts]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:43 ? 00:00:00 /sbin/init
root 2 0 0 08:43 ? 00:00:00 [kthreadd]
root 3 2 0 08:43 ? 00:00:00 [migration/0]
root 4 2 0 08:43 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 08:43 ? 00:00:00 [stopper/0]
root 6 2 0 08:43 ? 00:00:00 [watchdog/0]
root 7 2 0 08:43 ? 00:00:00 [migration/1]
root 8 2 0 08:43 ? 00:00:00 [stopper/1]
postgres 4719 1 0 11:52 pts/0 00:00:00 /usr/local/pg8k/bin/postgres -D ../data
postgres 4721 4719 0 11:52 ? 00:00:02 postgres: checkpointer process
postgres 4722 4719 0 11:52 ? 00:00:00 postgres: writer process
postgres 4723 4719 0 11:52 ? 00:00:01 postgres: wal writer process
postgres 4724 4719 0 11:52 ? 00:00:00 postgres: autovacuum launcher process
postgres 4725 4719 0 11:52 ? 00:00:02 postgres: stats collector process
root 4764 2260 0 11:55 ? 00:00:00 sshd: root@pts/1
root 4767 4764 0 11:55 pts/1 00:00:00 -bash
root 4787 4767 0 11:55 pts/1 00:00:19 top
postfix 4980 2374 0 13:43 ? 00:00:00 pickup -l -t fifo -u
postgres 5160 3460 1 15:07 pts/0 00:00:04 ./pgbench -h localhost -p 5432 -d postgres -c 4 -T 600
postgres 5162 4719 0 15:07 ? 00:00:03 postgres: postgres postgres ::1(50073) COMMIT
postgres 5163 4719 0 15:07 ? 00:00:03 postgres: postgres postgres ::1(50074) UPDATE
postgres 5164 4719 0 15:07 ? 00:00:03 postgres: postgres postgres ::1(50075) COMMIT
postgres 5165 4719 0 15:07 ? 00:00:03 postgres: postgres postgres ::1(50076) COMMIT
root 5181 3902 0 15:14 pts/2 00:00:00 ps –ef
这个命令可以列出所有进程(-e)的完整信息(-f)。
CPU用量的主要列是TIME和%CPU
TIME列列显示了进程自从创建开始消耗的CPU总时间(用户态+系统态),格式为“小时:分钟:秒”。
Linux上,%CPU列显示了在前一秒内所有CPU上的CPU用量之和。一个单线程的CPU型进程会报告100%。而一个双线程的CPU型进程则会报告200%。
top
top显示了最消耗CPU的任务,并带有CPU消耗百分比,以及一个ASCII字符的条形直方图(不是整列的数据)。
top命令监控了运行得最多的进程,以一定间隔刷新屏幕。例如,在Linux上:
top - 15:54:26 up 7:10, 3 users, load average: 1.48, 0.40, 0.24
Tasks: 194 total, 2 running, 192 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.9%us, 0.6%sy, 0.0%ni, 78.1%id, 20.2%wa, 0.0%hi, 0.2%si, 0.0%st
Mem: 16281948k total, 2677488k used, 13604460k free, 169132k buffers
Swap: 8388604k total, 0k used, 8388604k free, 2065604k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5245 postgres 20 0 42044 1732 1384 S 1.7 0.0 0:00.99 pgbench
5247 postgres 20 0 257m 28m 26m D 1.7 0.2 0:00.75 postgres
5248 postgres 20 0 257m 27m 26m S 1.7 0.2 0:00.75 postgres
5249 postgres 20 0 257m 28m 26m D 1.7 0.2 0:00.76 postgres
5250 postgres 20 0 257m 27m 26m S 1.7 0.2 0:00.75 postgres
3395 root 20 0 98764 4660 3336 S 1.0 0.0 0:13.97 sshd
20 root 20 0 0 0 0 S 0.3 0.0 0:01.51 events/1
顶部是系统范围的统计信息,而下面则是进程/任务的列表,默认按照CPU用量排序。系统范围的总结信息包括平均负载和CPU状态:%us,%sy,%ni,%id,%wa,%hi,%si,%st。这些状态和mpstat打印的相同,而与前面描述的一样,是所有CPU的平均值。
CPU用量通过TIME和%CPU列显示。
TIME+列的精度达到了百分之一秒。例如:“1:36.53”代表在CPU上的时间总计为1分36.53秒。top自身的CPU用量有可能会变得很大,原因在于可用的系统调用open(),read(),close()以及当遍历/proc里许多进程项目时它们的开销。Linux上 有 一个top的变种 名为atop,使用进程核算 技术 以捕捉短寿命进程的存在,然后把这些进程加入显示。
pidstat
Linux上的pidstat工具按进程或线程打印CPU用量,包括用户态和系统态时间的分解。默认情况下,仅循环输出活动的信息。例如:
[root@minion1 ~]# pidstat 1
Linux 2.6.32-504.el6.x86_64 (minion1) 02/17/2016 _x86_64_ (4 CPU)
04:19:56 PM PID %usr %system %guest %CPU CPU Command
04:19:57 PM 1912 0.00 0.99 0.00 0.99 2 kondemand/2
04:19:57 PM 3395 0.99 0.00 0.00 0.99 2 sshd
04:19:57 PM 5313 0.00 1.98 0.00 1.98 1 pgbench
04:19:57 PM 5315 0.99 0.99 0.00 1.98 0 postgres
04:19:57 PM 5316 0.99 0.00 0.00 0.99 0 postgres
04:19:57 PM 5317 0.00 0.99 0.00 0.99 0 postgres
04:19:57 PM 5318 0.99 0.00 0.00 0.99 0 postgres
04:19:57 PM PID %usr %system %guest %CPU CPU Command
04:19:58 PM 3395 0.00 1.00 0.00 1.00 3 sshd
04:19:58 PM 5313 2.00 1.00 0.00 3.00 1 pgbench
04:19:58 PM 5315 1.00 0.00 0.00 1.00 0 postgres
04:19:58 PM 5316 1.00 1.00 0.00 2.00 0 postgres
04:19:58 PM 5317 1.00 0.00 0.00 1.00 0 postgres
04:19:58 PM 5318 2.00 1.00 0.00 3.00 0 postgres
04:19:58 PM 5319 0.00 1.00 0.00 1.00 3 pidstat
04:19:58 PM PID %usr %system %guest %CPU CPU Command
04:19:59 PM 34 0.00 1.00 0.00 1.00 0 kblockd/0
04:19:59 PM 3395 0.00 1.00 0.00 1.00 3 sshd
04:19:59 PM 5313 0.00 1.00 0.00 1.00 1 pgbench
04:19:59 PM 5315 2.00 1.00 0.00 3.00 0 postgres
04:19:59 PM 5316 1.00 0.00 0.00 1.00 0 postgres
04:19:59 PM 5317 1.00 1.00 0.00 2.00 0 postgres
04:19:59 PM 5318 1.00 0.00 0.00 1.00 0 postgres
04:19:59 PM 5319 1.00 1.00 0.00 2.00 3 pidstat
-P ALL可以用来打印所有进程,包括空闲进程。选项-t打印每个线程的统计信息。
[root@minion1 ~]# pidstat -p ALL
Linux 2.6.32-504.el6.x86_64 (minion1) 02/17/2016 _x86_64_ (4 CPU)
04:25:33 PM PID %usr %system %guest %CPU CPU Command
04:25:33 PM 1 0.00 0.00 0.00 0.00 2 init
04:25:33 PM 2 0.00 0.00 0.00 0.00 3 kthreadd
04:25:33 PM 3 0.00 0.00 0.00 0.00 0 migration/0
04:25:33 PM 4 0.00 0.00 0.00 0.00 0 ksoftirqd/0
04:25:33 PM 5 0.00 0.00 0.00 0.00 0 stopper/0
04:25:33 PM 6 0.00 0.00 0.00 0.00 0 watchdog/0
04:25:33 PM 7 0.00 0.00 0.00 0.00 1 migration/1
04:25:33 PM 8 0.00 0.00 0.00 0.00 1 stopper/1
04:25:33 PM 9 0.00 0.00 0.00 0.00 1 ksoftirqd/1
04:25:33 PM 10 0.00 0.00 0.00 0.00 1 watchdog/1
04:25:33 PM 11 0.00 0.00 0.00 0.00 2 migration/2
04:25:33 PM 12 0.00 0.00 0.00 0.00 2 stopper/2
04:25:33 PM 13 0.00 0.00 0.00 0.00 2 ksoftirqd/2
04:25:33 PM 14 0.00 0.00 0.00 0.00 2 watchdog/2
04:25:33 PM 15 0.00 0.00 0.00 0.00 3 migration/3
04:25:33 PM 16 0.00 0.00 0.00 0.00 3 stopper/3
04:25:33 PM 17 0.00 0.00 0.00 0.00 3 ksoftirqd/3
04:25:33 PM 18 0.00 0.00 0.00 0.00 3 watchdog/3
04:25:33 PM 19 0.00 0.01 0.00 0.01 0 events/0
04:25:33 PM 20 0.00 0.01 0.00 0.01 1 events/1
04:25:33 PM 21 0.00 0.01 0.00 0.01 2 events/2
04:25:33 PM 22 0.00 0.00 0.00 0.00 3 events/3
04:25:33 PM 23 0.00 0.00 0.00 0.00 2 cgroup
04:25:33 PM 24 0.00 0.00 0.00 0.00 1 khelper
04:25:33 PM 25 0.00 0.00 0.00 0.00 2 netns
04:25:33 PM 26 0.00 0.00 0.00 0.00 1 async/mgr
04:25:33 PM 27 0.00 0.00 0.00 0.00 2 pm
04:25:33 PM 28 0.00 0.00 0.00 0.00 0 sync_supers
04:25:33 PM 29 0.00 0.00 0.00 0.00 0 bdi-default
04:25:33 PM 30 0.00 0.00 0.00 0.00 0 kintegrityd/0
04:25:33 PM 31 0.00 0.00 0.00 0.00 1 kintegrityd/1
04:25:33 PM 32 0.00 0.00 0.00 0.00 2 kintegrityd/2
04:25:33 PM 33 0.00 0.00 0.00 0.00 3 kintegrityd/3
04:25:33 PM 34 0.00 0.01 0.00 0.01 0 kblockd/0
04:25:33 PM 35 0.00 0.00 0.00 0.00 1 kblockd/1
04:25:33 PM 36 0.00 0.00 0.00 0.00 2 kblockd/2
04:25:33 PM 37 0.00 0.00 0.00 0.00 3 kblockd/3
04:25:33 PM 38 0.00 0.00 0.00 0.00 0 kacpid
04:25:33 PM 39 0.00 0.00 0.00 0.00 0 kacpi_notify
04:25:33 PM 40 0.00 0.00 0.00 0.00 0 kacpi_hotplug
04:25:33 PM 41 0.00 0.00 0.00 0.00 2 ata_aux
04:25:33 PM 42 0.00 0.00 0.00 0.00 0 ata_sff/0
04:25:33 PM 43 0.00 0.00 0.00 0.00 1 ata_sff/1
04:25:33 PM 44 0.00 0.00 0.00 0.00 2 ata_sff/2
04:25:33 PM 45 0.00 0.00 0.00 0.00 3 ata_sff/3
04:25:33 PM 46 0.00 0.00 0.00 0.00 2 ksuspend_usbd
04:25:33 PM 47 0.00 0.00 0.00 0.00 2 khubd
04:25:33 PM 48 0.00 0.00 0.00 0.00 1 kseriod
04:25:33 PM 49 0.00 0.00 0.00 0.00 0 md/0
04:25:33 PM 50 0.00 0.00 0.00 0.00 1 md/1
04:25:33 PM 51 0.00 0.00 0.00 0.00 2 md/2
04:25:33 PM 52 0.00 0.00 0.00 0.00 3 md/3
04:25:33 PM 53 0.00 0.00 0.00 0.00 0 md_misc/0
04:25:33 PM 54 0.00 0.00 0.00 0.00 1 md_misc/1
04:25:33 PM 55 0.00 0.00 0.00 0.00 2 md_misc/2
04:25:33 PM 56 0.00 0.00 0.00 0.00 3 md_misc/3
04:25:33 PM 57 0.00 0.00 0.00 0.00 2 linkwatch
04:25:33 PM 59 0.00 0.00 0.00 0.00 0 khungtaskd
04:25:33 PM 60 0.00 0.00 0.00 0.00 2 kswapd0
04:25:33 PM 61 0.00 0.00 0.00 0.00 2 ksmd
04:25:33 PM 62 0.00 0.00 0.00 0.00 1 khugepaged
04:25:33 PM 63 0.00 0.00 0.00 0.00 0 aio/0
04:25:33 PM 64 0.00 0.00 0.00 0.00 1 aio/1
04:25:33 PM 65 0.00 0.00 0.00 0.00 2 aio/2
04:25:33 PM 66 0.00 0.00 0.00 0.00 3 aio/3
04:25:33 PM 67 0.00 0.00 0.00 0.00 0 crypto/0
04:25:33 PM 68 0.00 0.00 0.00 0.00 1 crypto/1
04:25:33 PM 69 0.00 0.00 0.00 0.00 2 crypto/2
04:25:33 PM 70 0.00 0.00 0.00 0.00 3 crypto/3
04:25:33 PM 78 0.00 0.00 0.00 0.00 0 kthrotld/0
04:25:33 PM 79 0.00 0.00 0.00 0.00 1 kthrotld/1
04:25:33 PM 80 0.00 0.00 0.00 0.00 2 kthrotld/2
04:25:33 PM 81 0.00 0.00 0.00 0.00 3 kthrotld/3
04:25:33 PM 83 0.00 0.00 0.00 0.00 3 kpsmoused
04:25:33 PM 84 0.00 0.00 0.00 0.00 2 usbhid_resumer
04:25:33 PM 85 0.00 0.00 0.00 0.00 3 deferwq
04:25:33 PM 117 0.00 0.00 0.00 0.00 2 kdmremove
04:25:33 PM 118 0.00 0.00 0.00 0.00 2 kstriped
04:25:33 PM 146 0.00 0.00 0.00 0.00 1 ttm_swap
04:25:33 PM 292 0.00 0.00 0.00 0.00 0 scsi_eh_0
04:25:33 PM 293 0.00 0.00 0.00 0.00 1 scsi_eh_1
04:25:33 PM 294 0.00 0.00 0.00 0.00 0 scsi_eh_2
04:25:33 PM 295 0.00 0.00 0.00 0.00 3 scsi_eh_3
04:25:33 PM 296 0.00 0.00 0.00 0.00 1 scsi_eh_4
04:25:33 PM 297 0.00 0.00 0.00 0.00 1 scsi_eh_5
04:25:33 PM 409 0.00 0.00 0.00 0.00 1 kdmflush
04:25:33 PM 411 0.00 0.00 0.00 0.00 2 kdmflush
04:25:33 PM 428 0.00 0.00 0.00 0.00 0 jbd2/dm-1-8
04:25:33 PM 429 0.00 0.00 0.00 0.00 0 ext4-dio-unwrit
04:25:33 PM 517 0.00 0.00 0.00 0.00 1 udevd
04:25:33 PM 585 0.00 0.00 0.00 0.00 0 hd-audio0
04:25:33 PM 588 0.00 0.00 0.00 0.00 0 hd-audio1
04:25:33 PM 1574 0.00 0.00 0.00 0.00 0 jbd2/sda1-8
04:25:33 PM 1575 0.00 0.00 0.00 0.00 0 ext4-dio-unwrit
04:25:33 PM 1618 0.00 0.00 0.00 0.00 3 kauditd
04:25:33 PM 1794 0.00 0.01 0.00 0.01 1 flush-253:1
04:25:33 PM 1857 0.00 0.00 0.00 0.00 3 auditd
04:25:33 PM 1887 0.00 0.00 0.00 0.00 0 rsyslogd
04:25:33 PM 1910 0.00 0.01 0.00 0.01 0 kondemand/0
04:25:33 PM 1911 0.00 0.01 0.00 0.01 1 kondemand/1
04:25:33 PM 1912 0.00 0.01 0.00 0.01 2 kondemand/2
04:25:33 PM 1913 0.00 0.00 0.00 0.00 3 kondemand/3
04:25:33 PM 1935 0.00 0.00 0.00 0.00 1 irqbalance
04:25:33 PM 2038 0.00 0.00 0.00 0.00 0 iprt-VBoxWQueue
04:25:33 PM 2039 0.00 0.00 0.00 0.00 1 iprt-VBoxWQueue
04:25:33 PM 2040 0.00 0.00 0.00 0.00 2 iprt-VBoxWQueue
04:25:33 PM 2041 0.00 0.00 0.00 0.00 3 iprt-VBoxWQueue
04:25:33 PM 2043 0.00 0.00 0.00 0.00 0 iprt-VBoxTscThr
04:25:33 PM 2060 0.00 0.00 0.00 0.00 0 dbus-daemon
04:25:33 PM 2071 0.00 0.00 0.00 0.00 1 NetworkManager
04:25:33 PM 2077 0.00 0.00 0.00 0.00 3 modem-manager
04:25:33 PM 2092 0.00 0.00 0.00 0.00 0 cupsd
04:25:33 PM 2130 0.00 0.00 0.00 0.00 1 acpid
04:25:33 PM 2142 0.00 0.00 0.00 0.00 1 hald
04:25:33 PM 2143 0.00 0.00 0.00 0.00 0 hald-runner
04:25:33 PM 2147 0.00 0.00 0.00 0.00 2 wpa_supplicant
04:25:33 PM 2224 0.00 0.00 0.00 0.00 1 hald-addon-inpu
04:25:33 PM 2227 0.00 0.00 0.00 0.00 0 hald-addon-acpi
04:25:33 PM 2260 0.00 0.00 0.00 0.00 1 sshd
04:25:33 PM 2269 0.00 0.00 0.00 0.00 0 ntpd
04:25:33 PM 2279 0.00 0.00 0.00 0.00 2 ntpd
04:25:33 PM 2374 0.00 0.00 0.00 0.00 0 master
04:25:33 PM 2384 0.00 0.00 0.00 0.00 1 qmgr
04:25:33 PM 2402 0.00 0.00 0.00 0.00 0 abrtd
04:25:33 PM 2413 0.00 0.00 0.00 0.00 0 crond
04:25:33 PM 2557 0.00 0.00 0.00 0.00 3 Xvnc
04:25:33 PM 2563 0.00 0.00 0.00 0.00 0 ck-xinit-sessio
04:25:33 PM 2570 0.00 0.00 0.00 0.00 3 vncconfig
04:25:33 PM 2581 0.00 0.00 0.00 0.00 0 atd
04:25:33 PM 2596 0.00 0.00 0.00 0.00 0 rhsmcertd
04:25:33 PM 2619 0.00 0.00 0.00 0.00 1 dbus-launch
04:25:33 PM 2620 0.00 0.00 0.00 0.00 1 dbus-daemon
04:25:33 PM 2637 0.00 0.00 0.00 0.00 3 mingetty
04:25:33 PM 2639 0.00 0.00 0.00 0.00 0 mingetty
04:25:33 PM 2641 0.00 0.00 0.00 0.00 1 mingetty
04:25:33 PM 2643 0.00 0.00 0.00 0.00 0 mingetty
04:25:33 PM 2645 0.00 0.00 0.00 0.00 1 mingetty
04:25:33 PM 2647 0.00 0.00 0.00 0.00 2 mingetty
04:25:33 PM 2648 0.00 0.00 0.00 0.00 1 udevd
04:25:33 PM 2649 0.00 0.00 0.00 0.00 0 udevd
04:25:33 PM 2651 0.00 0.00 0.00 0.00 1 console-kit-dae
04:25:33 PM 2719 0.00 0.00 0.00 0.00 2 gnome-session
04:25:33 PM 2721 0.00 0.00 0.00 0.00 0 ssh-agent
04:25:33 PM 2728 0.00 0.00 0.00 0.00 3 devkit-power-da
04:25:33 PM 2732 0.00 0.00 0.00 0.00 1 gconfd-2
04:25:33 PM 2751 0.00 0.00 0.00 0.00 1 gnome-keyring-d
04:25:33 PM 2755 0.00 0.00 0.00 0.00 1 gnome-settings-
04:25:33 PM 2761 0.00 0.00 0.00 0.00 0 gvfsd
04:25:33 PM 2767 0.00 0.00 0.00 0.00 1 gvfs-fuse-daemo
04:25:33 PM 2773 0.00 0.00 0.00 0.00 2 metacity
04:25:33 PM 2776 0.00 0.00 0.00 0.00 1 gnome-panel
04:25:33 PM 2778 0.07 0.00 0.00 0.07 1 nautilus
04:25:33 PM 2780 0.00 0.00 0.00 0.00 3 bonobo-activati
04:25:33 PM 2787 0.00 0.00 0.00 0.00 0 wnck-applet
04:25:33 PM 2788 0.00 0.00 0.00 0.00 3 trashapplet
04:25:33 PM 2790 0.00 0.00 0.00 0.00 1 gvfs-gdu-volume
04:25:33 PM 2795 0.01 0.00 0.00 0.01 1 udisks-daemon
04:25:33 PM 2801 0.00 0.00 0.00 0.00 3 gvfsd-trash
04:25:33 PM 2802 0.00 0.00 0.00 0.00 2 udisks-daemon
04:25:33 PM 2807 0.00 0.00 0.00 0.00 2 gnome-volume-co
04:25:33 PM 2819 0.00 0.00 0.00 0.00 3 gpk-update-icon
04:25:33 PM 2828 0.00 0.00 0.00 0.00 1 gnome-power-man
04:25:33 PM 2831 0.00 0.00 0.00 0.00 0 nm-applet
04:25:33 PM 2832 0.00 0.00 0.00 0.00 3 polkit-gnome-au
04:25:33 PM 2837 0.00 0.00 0.00 0.00 0 polkitd
04:25:33 PM 2844 0.00 0.00 0.00 0.00 0 gnome-screensav
04:25:33 PM 2849 0.00 0.00 0.00 0.00 2 pulseaudio
04:25:33 PM 2856 0.00 0.00 0.00 0.00 1 gdm-user-switch
04:25:33 PM 2858 0.00 0.00 0.00 0.00 0 clock-applet
04:25:33 PM 2860 0.00 0.00 0.00 0.00 3 notification-ar
04:25:33 PM 2878 0.00 0.00 0.00 0.00 1 gconf-helper
04:25:33 PM 3395 0.02 0.05 0.00 0.07 3 sshd
04:25:33 PM 3398 0.00 0.00 0.00 0.00 1 bash
04:25:33 PM 3458 0.00 0.00 0.00 0.00 0 su
04:25:33 PM 3460 0.00 0.00 0.00 0.00 3 bash
04:25:33 PM 3872 0.00 0.00 0.00 0.00 2 dbus-launch
04:25:33 PM 3873 0.00 0.00 0.00 0.00 0 dbus-daemon
04:25:33 PM 3899 0.00 0.00 0.00 0.00 0 sshd
04:25:33 PM 3902 0.00 0.00 0.00 0.00 0 bash
04:25:33 PM 4719 0.00 0.00 0.00 0.00 0 postgres
04:25:33 PM 4721 0.00 0.01 0.00 0.01 1 postgres
04:25:33 PM 4722 0.00 0.00 0.00 0.00 2 postgres
04:25:33 PM 4723 0.00 0.01 0.00 0.01 0 postgres
04:25:33 PM 4724 0.00 0.00 0.00 0.00 2 postgres
04:25:33 PM 4725 0.00 0.01 0.00 0.01 0 postgres
04:25:33 PM 4764 0.00 0.00 0.00 0.00 0 sshd
04:25:33 PM 4767 0.00 0.00 0.00 0.00 1 bash
04:25:33 PM 5197 0.00 0.00 0.00 0.00 1 pickup
04:25:33 PM 5313 0.01 0.01 0.00 0.02 1 pgbench
04:25:33 PM 5315 0.01 0.00 0.00 0.01 0 postgres
04:25:33 PM 5316 0.01 0.00 0.00 0.01 0 postgres
04:25:33 PM 5317 0.01 0.00 0.00 0.01 0 postgres
04:25:33 PM 5318 0.01 0.00 0.00 0.01 0 postgres
04:25:33 PM 5334 0.00 0.00 0.00 0.00 3 pidstat
perf
perf命令原名为Linux性能 计数器(Performance Counters for Linux,PCL),已经演化成为一整套剖析和跟踪的工具,现名为Linux性能事件(Linux Performance Evens,LPE)。每个工具分别作为一个子命令,例如,perf stat执行stat命令,提供基于CPC的统计信息。这些命令的列表可以在USAGE消息中找到。
下面是一部分命令的说明:
annotate:读取perf.data(有perf record创建)并显示注释过的代码
diff:读取两个perf.data文件并显示两份剖析信息之间的差异
evlist:列出一个perf.data文件里的事件名称
inject:过滤以加强事件流,在其中加入额外的信息
kmem:跟踪/测量内核内存(slab)属性的工具
kvm:跟踪/测量kvm客户机操作系统的工具
list: 列出所有的符号事件类型
lock:分析锁事件
probe:定义新的动态跟踪点
record:运行一个命令,并把剖析信息记录在perf.data中
report:读取perf.data(perf record创建)并显示剖析信息
sched:跟踪/测量调度器属性(延时)的工具
script:读取perf.data(由perf record创建)并显示跟踪输出
stat:运行一个命令并收集性能计数器统计信息
timechart:可视化某一个负载期间系统总体性能的工具
top: 系统剖析工具
下面演示了如何使用一些关键命令:
系统剖析
perf可以用来剖析CPU调用路径,对CPU时间如何消耗在内核和用户空间进行概括总结。这项工作有record命令完成,该命令以一定间隔进行取样,并导出到一个perf.data文件,然后使用report命令查看文件。
下面的例子里,所有的CPU(-a)以997Hz的频率(-F 997)对调用栈(-g)取样10s(sleep 10)。选项—studio用来打印所有的输出,而非采用默认的交互模式操作。
[root@minion1 ~]# perf record -a -g -F 997 sleep 10
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.283 MB perf.data (~12351 samples) ]
可以看到在当前目录生成了perf.data文件
[root@minion1 ~]# ll perf.data
-rw------- 1 root root 298972 Feb 17 17:17 perf.data
将perf.data的内容读取到test_perf文件中,以便分析
[root@minion1 ~]# perf report > test_perf
[root@minion1 ~]# ll test_perf
-rw-r--r-- 1 root root 21950 Feb 17 17:23 test_perf
将perf.data的内容直接输出到屏幕
[root@minion1 ~]# perf report --stdio
# ========
# captured on: Wed Feb 17 17:17:49 2016
# hostname : minion1
# os release : 2.6.32-504.el6.x86_64
# perf version : 2.6.32-504.el6.x86_64.debug
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i5-3450 CPU @ 3.10GHz
# cpuid : GenuineIntel,6,58,9
# total memory : 16281948 kB
# cmdline : /usr/bin/perf record -a -g -F 997 sleep 10
# event : name = cycles, type = 0, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0
# HEADER_CPU_TOPOLOGY info available, use -I to display
# HEADER_NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: cpu = 4, tracepoint = 2, software = 1
# ========
# Samples: 61 of event 'cycles'
# Event count (approx.): 73110159
#
# Overhead Command Shared Object Symbol
# ........ ............... .................. .....................................
#
26.06% sleep [kernel.kallsyms] [k] flush_tlb_others_ipi
|
--- flush_tlb_others_ipi
native_flush_tlb_others
flush_tlb_mm
exit_mmap
mmput
flush_old_exec
load_elf_binary
search_binary_handler
do_execve
sys_execve
stub_execve
__execve
25.17% init [kernel.kallsyms] [k] intel_idle
|
--- intel_idle
cpuidle_idle_call
cpu_idle
start_secondary
21.88% init [kernel.kallsyms] [k] run_timer_softirq
|
--- run_timer_softirq
__do_softirq
call_softirq
do_softirq
irq_exit
smp_apic_timer_interrupt
apic_timer_interrupt
cpuidle_idle_call
cpu_idle
start_secondary
4.89% irqbalance [kernel.kallsyms] [k] wake_up_bit
|
--- wake_up_bit
unlock_new_inode
proc_get_inode
proc_lookup_de
proc_lookup
proc_root_lookup
do_lookup
__link_path_walk
path_walk
filename_lookup
do_filp_open
do_sys_open
sys_open
system_call_fastpath
__GI___libc_open
__fopen_internal
进程剖析
除了剖析系统里的所有CPU,也可以对单个进程进行剖析。下面的命令执行了command并创建文件perf.data:
perf record –g command
perf需要调试信息文件,这样在查看报告是可以进行符号转译。
调度器延时
sched命令记录并报告调度器统计信息。例如:
perf sched record sleep 10
[root@minion1 ~]# perf sched record sleep 10
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.408 MB perf.data (~17818 samples) ]
将perf.data信息输出到文件,以便于读取
统计信息包括了周期和指令计数,以及IPC(CPI的倒数)。和前面描述的一样,这是一个对判断周期类型以及其中有多少停滞周期非常有用的概要指标。
下面列出了其它可以检查的计数器:
上面显示了跟踪时期平均和最大的调度器延时。
调度器事件较为频繁,因此此类跟踪会导致CPU和存储的开销。perf.data文件即为跟踪10s的产物。
stat
stat命令基于CPC为CPU周期行为提供了一个概要总结。下面的例子里它启动了gzip命令
这些事件可以使用选项-e指定。
L1-dcache-load-misses:一级数据缓存负载未命中。可以看出应用程序施加的内存负载,其中有一部分负载从一级缓存返回。可以与其它L1事件计数器进行对比以确定缓存命中率。
LLC-load-misses:末级缓存负载未命中。在末级缓存之后,就会直接存取主存,因此这实际测量了主存负载。从它与L1-dcache-load-misses之间的区别,可以大概看出,除一级CPU缓存之外其它缓存的有效性。
dTLB-load-misses:数据转译后备缓冲器中。它展示了MMU为负载缓存页面映射的有效性,可以用来测量内存负载的大小(工作集)。
软件跟踪
perf record –e 可以与各种软件性能测量点配合,用来跟踪内核调度器的活动。这些测量点包括了软件时间和跟踪点事件(静态探测器)。由perf list列出。
[root@minion1 tmp]# perf record -g -a -e context-switches sleep 30
[root@minion1 tmp]# ll perf.data
-rw------- 1 root root 625804 Feb 18 09:54 perf.data
[root@minion1 tmp]# perf report --stdio
# Samples: 2K of event 'context-switches'
# Event count (approx.): 34465
#
# Overhead Command Shared Object Symbol
# ........ ............... ................. .............................
#
28.98% postgres [kernel.kallsyms] [k] perf_event_task_sched_out
|
--- perf_event_task_sched_out
schedule
|
|--50.38%-- schedule_timeout
| |
| |--96.10%-- sk_wait_data
| | tcp_recvmsg
| | sock_common_recvmsg
| | sock_recvmsg
| | sys_recvfrom
| | system_call_fastpath
| | __libc_recv
| |
| --3.90%-- wait_for_common
| wait_for_completion
| __blkdev_issue_flush
| blkdev_issue_flush
| ext4_sync_file
其它工具
oprofile:最初的CPU剖析工具 。
htop:包括了CPU用量的ASCII柱状图,比最初的top有更强大的交互模式。
atop:包括了更多的系统级统计信息。
/proc/cpuinfo:可以获取处理器详细信息。
valgrind:一个内存调试和剖析工具组。它包括了callgrind,一个跟踪函数调用并生成调用图的工具,并可以通过kcachegrind可视化;另外cachegrind可用来分析一个给定程序的硬件缓存用来。
生成调用图的工具,并可以通过kcachegrind可视化;另外cachegrind可用来分析一个给定程序的硬件缓存用来。
可视化
负载工具xload
火焰图通过perf或者SystemTap的数据制作。通过perf剖析Linux内核。
进程绑定
一个进程可以绑定在一个或者多个CPU上,这样可以通过提供缓存温度和内存本地性来提高性能。
在Linux上,是通过taskset命令实现的,这个方法可以使用CPU掩码或者范围设置CPU关联性。例如
[root@minion1 tmp]# taskset
taskset (util-linux-ng 2.17.2)
usage: taskset [options] [mask | cpu-list] [pid | cmd [args...]]
set or get the affinity of a process
-p, --pid operate on existing given pid
-c, --cpu-list display and specify cpus in list format
-h, --help display this help
-V, --version output version information
The default behavior is to run a new command:
taskset 03 sshd -b 1024
You can retrieve the mask of an existing task:
taskset -p 700
Or set it:
taskset -p 03 700
List format uses a comma-separated list instead of a mask:
taskset -pc 0,3,7-11 700
Ranges in list format can take a stride argument:
e.g. 0-31:2 is equivalent to mask 0x55555555
taskset –pc 7-10 10790
上面的设置限定了PID为10790的进程只能跑在CPU7到CPU10之间。
独占CPU组
Linux提供了CPU组,允许编组CPU并为其分配进程。这个进程绑定类似,可以提供性能,但还可以通过使得CPU组独占—不允许其它进程使用—而进一步提高性能。这种权衡另一方面减少了系统其它部分的可用CPU数量。
下面带注释的示例创建了一个独占组:
mkdir /dev/cpuset
mount –t cpuset cpuset /dev/cpuset
cd /dev/cpuset
mkdir prodset #create a cpuset called “prodset”
cd prodset
echo 7-10 > cpus #assign CPUs 7-10
echo 1 > cpu_exclusive #make prodset exclusive
echo 1159 > tasks #assign PID 1159 to prodset
资源控制
除了把进程和整个CPU关联外,现代操作系统还对CPU用量分配提供了细粒度资源控制。
Linux上的控制组(cgroups),通过进程或者进程组控制了资源用量。CPU用量可以使用份额进行控制,而CFS调度器允许对每段时间内分配的CPU微秒数周期,设置上限(CPU带宽)