`
san_yun
  • 浏览: 2594748 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Linux 性能测试与分析

 
阅读更多

本文参考:http://testing.etao.com/node/328 ,http://testing.etao.com/node/327 ,http://testing.etao.com/node/326

 

1         性能测试简介

  • 性能测试的过程就是找到系统瓶颈的过程。
  • 性能测试(包括分析和调优)的过程就是在操作系统的各个子系统之间取得平衡的过程。
  • 操作系统的各个子系统包括:

            CPU 

             Memory 

             IO 

             Network 

他们之间高度依赖,互相影响。比如:

1.      频繁的磁盘读写会增加对内存的使用

2.      大量的网络吞吐,一定意味着非常可观的CPU利用率

可用内存的减少可能增加大量的swapping,从而使系统负载上升甚至崩溃

2        应用程序类型

性能测试之前,你首先需要判断你的应用程序是属于那种类型的,这可以帮助你判断哪个子系统可能会成为瓶颈。 

通常可分为如下两种: 

CPU bound – 这类程序,cpu往往会处于很高的负载,当系统压力上升时,相对于磁盘和内存,往往CPU会首先到达瓶颈。Web server,mail server以及大部分服务类程序都属于这一类。 

I/O bound – 这类程序,往往会频繁的访问磁盘,从而发送大量的IO请求。IO类应用程序往往利用cpu发送IO请求之后,便进入sleep状态,从而造成很高的IOWAIT。数据库类程序,cache服务器往往属于这种类型。 

3        CPU

3.1      性能瓶颈

3.1.1        运算性能瓶颈

作为计算机的计算单元,其运算能力方面,可能出现如下瓶颈: 

1.  用户态进程CPU占用率很高 

2.  系统态(内核态)CPU占用率很高 

测试CPU的运算性能,通常是通过计算圆周率来测试CPU的浮点运算能力和稳定性。据说Pentium CPU的一个运算bug就是通过计算圆周率来发现的。圆周率的计算方法,通常是计算小数点后104万位,通过比较运算时间来评测CPU的运算能力。 

常用工具: 

  1. SUPER PI(π)
  2. Wprime  与SuperPI不同的是,可以支持多核CPU的运算速度测试
  3.  FritzChess  一款国际象棋测试软件,测试每秒钟可运算的步数 

 突破CPU的运算瓶颈,一般只能靠花钱。比如提高时钟频率,提高L1,L2 cache容量或不断追求新一代的CPU架构: 

 Core  ->  Nehalem(E55x,如r710dsc1100)  ->  Westmere  –>  Sandy Bridge

 

3.1.2        调度性能瓶颈

CPU除了负责计算之外,另一个非常重要的功能就是调度。在调度方面,CPU可能会出现如下性能瓶颈: 

  1. Load平均值超过了系统可承受的程度
  2. IOWait占比过高,导致Load上升或是引入新的磁盘瓶颈
  3. Context Switch过高,导致CPU就像个搬运工一样,频繁在寄存器(CPU Register)和运行队列(run queue)之间奔波
  4. 硬中断CPU占比接近于100%
  5. 软中断CPU占比接近于100%

  

超线程 

超线程芯片可以使得当前线程在访问内存的间隙,处理器可以使用它的机器周期去执行另外一个线程。一个超线程的物理CPU可以被kernel看做是两个独立的CPU。 

3.2      典型监控参数

3.2.1        参数含义
  • Load

Load是指CPU所有内核正在处理的任务加上处于等待队列中的进程数之和。

 

处于等待队列(run queue)中的进程包括TASK_RUNNING TASK_UNINTERRUPTIBLE两种状态的任务:

?  处于可运行状态的进程 

?  等待不可中断任务的进程 

 

在一个双核的系统中,如果两个进程正在执行,有四个进程处于run quque当中,那么load就是6

  • Nice%

用户进程空间内,通过调用nice或setpriority系统调用改变过优先级的进程的CPU占用率 

  • Iowait%

CPU等待IO操作的时间 

  • Idle%

CPU空闲时间 

  • Intr/s

每秒钟处理的中断数 

  • Hi%

服务于IRQs的时间占比 

  • Si%

服务于Soft IRQs的时间占比 

  • St%

关于st的解释,在IBM的一份文档里,有一段描述: 

IBM’s definition of steal time is actually pretty good:
Steal time is the percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor. 

3.3      工作原理

为了更好地理解CPU的性能参数,需要了解如下一些概念 

3.3.1        进程及进程调度算法
  1. 什么是线程

图3:进程和线程的数据结构 

  1. 2.      进程的状态 
  • 可运行状态(TASK_RUNNING)
  • 不可中断的等待状态(TASK_UNINTERRUPTIBLE)
  • 暂停状态(TASK_STOPPED)
  • 跟踪状态(TASK_TRACED)
  • 僵死状态(EXIT_ZOMBIE)

  

问题 Wait io%包含在idle%当中吗? 

从下面top实例可以看出,wait io%不属于idle%,等IO的过程被叫做uninterruptible sleep 

Cpu1  :  2.7%us,  3.0%sy,  0.0%ni,  3.7%id, 89.7%wa,  0.0%hi,  1.0%si,  0.0%st 

从性能测试角度来看,我倾向于这样理解线程:

1.      线程和进程的确不同,因为他们可以共享进程的资源,如地址空间等。因此在上下文切换的过程中可能会产生较小的性能损耗。

2. 站在调度器(scheduler)的角度来说,线程就是一个进程,或者说是一个轻量级的进程(Light Weight Process)Kernel实际上就是通过轻量级的进程来支持多线程应用程序的。我们经常用的线程开发库pthread就是通过将轻量级进程和线程关联起来,来实现的。这样既可以实现资源的共享,又可以让每个线程被调度器独立调度。

2.      进程的状态 

  • 可运行状态(TASK_RUNNING)
  • 不可中断的等待状态(TASK_UNINTERRUPTIBLE)
  • 暂停状态(TASK_STOPPED)
  • 跟踪状态(TASK_TRACED)
  • 僵死状态(EXIT_ZOMBIE)

  

问题 Wait io%包含在idle%当中吗? 

从下面top实例可以看出,wait io%不属于idle%,等IO的过程被叫做uninterruptible sleep 

Cpu1  :  2.7%us,  3.0%sy,  0.0%ni,  3.7%id, 89.7%wa,  0.0%hi,  1.0%si,  0.0%st 

3.3.4        硬中断

性能测试中关注的中断,主要由自于IO设备所产生,如键盘的一次按键,网卡的收报等等。 

IRQ

IO设备所发出的IRQ(Interrupt ReQuest)请求叫做中断请求(可屏蔽中断) 

每个能够发出中断的IO设备都有一个IRQ输出线(部分高级前兆网卡,和大部分万兆网卡都多条IRQ输出线)。每条IRQ输出线和可编程中断控制器(Programmable Interrupt Controller)引脚相关联。 

每个IRQ输出线的中断信号,只能被一个CPU core处理,IRQ线从0开始编号。 

如何观察IRQ的状态: 

问题3:大量的中断,是否会使CPU响应中断成为瓶颈呢? 

答案是一般不会,中断享有最高的优先级,有硬件中断发生时,CPU会立即停下手中的工作,响应中断,并调用相应中断处理程序。瓶颈一般发生在中断处理程序。 

IRQ硬件中断是否意味着不会出现瓶颈呢?瓶颈有可能出现在中断的服务例程中,看下面的流程图: 

IRQ在多处理器上的分发: 

遵循对称多处理模型,每个IO中断的处理时间片是相同的,均匀分配。Kernel通过中断向量表来将中断信号发送到特定的CPU上去。 

在必要的时候,Linux 2.6利用kirqd的内核线程来纠正IRQ在CPU上的分配。kirqd线程周期性的执行扫描每个CPU处理的中断个数,发现不均衡时重新调整CPU的负载。 

下面的案例表明,IRQ在CPU上的分配不够均衡,因为8个CPU,只有4个CPU有负载: 

性能测试中关注的中断,主要由自于IO设备所产生,如键盘的一次按键,网卡的收报等等。

 

IRQ

IO设备所发出的IRQ(Interrupt ReQuest)请求叫做中断请求(可屏蔽中断)

 

每个能够发出中断的IO设备都有一个IRQ输出线(部分高级前兆网卡,和大部分万兆网卡都多条IRQ输出线)。每条IRQ输出线和可编程中断控制器(Programmable Interrupt Controller)引脚相关联。

 

每个IRQ输出线的中断信号,只能被一个CPU core处理,IRQ线从0开始编号。

 

  

问题3:大量的中断,是否会使CPU响应中断成为瓶颈呢?

 

答案是一般不会,中断享有最高的优先级,有硬件中断发生时,CPU会立即停下手中的工作,响应中断,并调用相应中断处理程序。瓶颈一般发生在中断处理程序。

 

IRQ硬件中断是否意味着不会出现瓶颈呢?瓶颈有可能出现在中断的服务例程中,看下面的流程图:

 

IRQ在多处理器上的分发:

遵循对称多处理模型,每个IO中断的处理时间片是相同的,均匀分配。Kernel通过中断向量表来将中断信号发送到特定的CPU上去。

 

在必要的时候,Linux 2.6利用kirqd的内核线程来纠正IRQCPU上的分配。kirqd线程周期性的执行扫描每个CPU处理的中断个数,发现不均衡时重新调整CPU的负载。

 

下面的案例表明,IRQCPU上的分配不够均衡,因为8CPU,只有4CPU有负载:

   

  

3.3.5       软中断

Linux kernel通过一种软件的方法(可延迟函数)来模拟硬件的中断模式,通常叫做软中断(softirq)。

Linux 中的软中断

软中断 说明
NET_TX_SOFTIRQ 把数据包传送到网卡
NET_RX_SOFTIRQ 从网卡接收数据包

 

从网卡到IP层的数据处理,是有以上软中断来处理的。

软中断是否可能出现瓶颈呢?

Ksoftirqd

每个CPU都有自己的ksoftirqd/n(n为CPU的逻辑号码)。每个ksoftirqd/n内核线程都运行ksoftirqd()函数来处理自己的中端队列上的软中断。

当网卡和IP层数据包处理很繁忙时,中断处理程序会出现瓶颈.下图可看出ksoftirqd出现了瓶颈: 

从网卡到IP层的数据处理,是有以上软中断来处理的。

 

软中断是否可能出现瓶颈呢?

Ksoftirqd

每个CPU都有自己的ksoftirqd/nnCPU的逻辑号码)。每个ksoftirqd/n内核线程都运行ksoftirqd()函数来处理自己的中端队列上的软中断。

 

当网卡和IP层数据包处理很繁忙时,中断处理程序会出现瓶颈.下图可看出ksoftirqd出现了瓶颈:

软中断处理出现瓶颈,ksoftirqd可通过cpu的 si%的来观察到。

 

 

4       内存

4.1      虚拟内存

Linux kernel使用虚拟内存机制来利用磁盘对内存的空间进行扩展。Kernel将暂时不用的内存写入到磁盘从而释放出更多的可用内存。当这些数据再次被使用时,会被重新加载到内存当中。用作虚拟内存的磁盘空间被称作swap space。

对硬盘的读写,相对于内存来说速度要慢许多,因此使用了虚拟内存的程序,速度也会相应变慢。

对虚拟内存的使用,往往被认为是内存出现瓶颈的标志。

问题n:swap空间被使用是否意味着出现了内存瓶颈?

KswapdPage Frame Reclaim Algorithm

当系统的可用内存低于阈值时(page_low,page_high),kswpad服务比那开始扫描可以被swap out的空间,并试图一次swap out 32个内存页。该过程不断重复知道可用内存达到page_high水平线位置。被swap out的内存也被放在swap spae当中。

Kswapd回收内存的算法被称作Page Frame Reclaim Algorithm,一下类型的内存也是可以被回收的:

  • ? Swappable – anonymous memory pages
  • ? Syncable – pages backed by a disk file
  • ? Discardable – static pages, discarded pages

 

内存的回收采用LRU策略,最近不被经常使用的内存页,应该首先被回收。

现在来回答上面的问题:

swap空间被利用恰恰说明了Linux的内存使用的合理性,并不能表示内存出现了瓶颈。

对Swap空间的换入换出的速率是表征内存出现瓶颈的重要标志。

5         IO

IO 子系统架构图

5.1       页高速缓存

页高速缓存是Linux kernel使用的主要的磁盘缓存技术。磁盘高速缓存是一种软件机制,它允许系统把存放在磁盘上的一些数据保留在内存中,以便对那些数据的再次访问不再需要访问磁盘。

Kernel在读取磁盘时,如果数据页不再高速缓存当中,就会将读出的磁盘数据填充到页高速缓存当中。通过将数据页在高速缓存当中驻留,从而使进程再使用该页时不再需要访问磁盘。

Kernel在把一页数据写到磁盘之前,首先检查页是否已经在高速缓存当中,如果不在,首先会将页数据填充到高速缓存当中。更新到磁盘I/O的动作不是立即进行的,而是会有一点延时,从而使进程有机会对写入的数据进一步修改,这就是内核的延迟写操作。

脏数据的同步

进程对页高速缓冲区中的数据修改之后,数据页被标记为”脏数据”,即把PG_Dirty标志置位。Linux系统允许对脏数据写入磁盘块设备的延迟操作,被认为是显著增加了系统I/O能力的一种机制。

在下列条件下,脏数据写入磁盘:

  1. 页高速缓存空间不足
  2. 变脏以来,太久没有过更新
  3. 进程通过系统调用(sync(),fsync(),fdataasync())来强行对将对快设备的更新同步到磁盘。Msync系统调用用来将内存映射状态下的脏数据刷新到磁盘。

 

Pdflush

Pdflush内核线程负责丁奇扫描缓存中的脏数据,并在合适的时候将其更新到磁盘。定时器一般是500分之一秒,可以通过/proc/sys/vm/dirty_writeback_centisecs文件调整这个值。

Pdflush线程的个数是根据情况动态调整的:

  1. 至少有2个,最多有8个pdflush线程。(通过/proc/sys/vm/nr_pdflush_threads参数)可以修改这些变量的值。
  2. 如果最近1s内,没有空闲的pdflush线程,就创建新的。
  3. 如果pdflush的空闲时间超过了1s,就删除一个pdflush。

 

Buffer/cache

Cache - 全称page cache。当进程发起对磁盘的读写操作时,主要用来在内存中缓存磁盘中的数据,与磁盘的同步有pdflush负责。

Buffer – 全称block buffer。Block buffer中存放的是bio结构体数据。BIO 结构体是VFS和 block layer之间的借口。通俗的理解,Block buffer是page cache和磁盘驱动器之间打交道的一层缓存。

系统页高速缓存的使用情况可以通过buffer/cache的监控数据来分析。

从文件读写角度来看,buffer多用于缓存文件的管信息,如目录位置,inode信息等。Cache缓存的是文件内容。

由于CPU不能直接处理外设上的数据,buffer用来标记那些文件的位置等描述信息。Cache主要目的是增加传输性能,用于缓存文件内容。

从操作系统的工作原理来讲,buffer/cache的目的主要是为了减少MPFs,增加MnPFs。

MPF

Kernel要读取数据的时候,首先会查找CPU 的cache然后是物理内存,如果没有会发出一个major page fault(MPF)。一个MPF可以看做是kernel发送的一个请求,将磁盘数据加载到内存。

MnPF

当磁盘数据被加载到内存当中,kernel再次读取时,会发出一个minor page fault(MnPF)。

下面的例子展示了第一次访问一个程序和第二次访问同样的程序所产生的MPF和MnPF。

/usr/bin/time -v java

Major (requiring I/O) page faults: 103

Minor (reclaiming a frame) page faults: 2356

第二次访问:

/usr/bin/time -v java

Major (requiring I/O) page faults: 0

Minor (reclaiming a frame) page faults: 2581

下图展示了磁盘高速缓存过程

页高速缓存是Linux kernel使用的主要的磁盘缓存技术。磁盘高速缓存是一种软件机制,它允许系统把存放在磁盘上的一些数据保留在内存中,以便对那些数据的再次访问不再需要访问磁盘。

 

Kernel在读取磁盘时,如果数据页不再高速缓存当中,就会将读出的磁盘数据填充到页高速缓存当中。通过将数据页在高速缓存当中驻留,从而使进程再使用该页时不再需要访问磁盘。

 

Kernel在把一页数据写到磁盘之前,首先检查页是否已经在高速缓存当中,如果不在,首先会将页数据填充到高速缓存当中。更新到磁盘I/O的动作不是立即进行的,而是会有一点延时,从而使进程有机会对写入的数据进一步修改,这就是内核的延迟写操作。

 

脏数据的同步

进程对页高速缓冲区中的数据修改之后,数据页被标记为脏数据,即把PG_Dirty标志置位。Linux系统允许对脏数据写入磁盘块设备的延迟操作,被认为是显著增加了系统I/O能力的一种机制。

 

在下列条件下,脏数据写入磁盘:

1.      页高速缓存空间不足

2.      变脏以来,太久没有过更新

3.      进程通过系统调用(sync(),fsync(),fdataasync())来强行对将对快设备的更新同步到磁盘。Msync系统调用用来将内存映射状态下的脏数据刷新到磁盘。

 

Pdflush

Pdflush内核线程负责丁奇扫描缓存中的脏数据,并在合适的时候将其更新到磁盘。定时器一般是500分之一秒,可以通过/proc/sys/vm/dirty_writeback_centisecs文件调整这个值。

 

Pdflush线程的个数是根据情况动态调整的:

1.      至少有2个,最多有8pdflush线程。(通过/proc/sys/vm/nr_pdflush_threads参数)可以修改这些变量的值。

2.      如果最近1s内,没有空闲的pdflush线程,就创建新的。

3.      如果pdflush的空闲时间超过了1s,就删除一个pdflush

 

 

 

Buffer/cache

Cache - 全称page cache。当进程发起对磁盘的读写操作时,主要用来在内存中缓存磁盘中的数据,与磁盘的同步有pdflush负责。

 

Buffer – 全称block bufferBlock buffer中存放的是bio结构体数据。BIO 结构体是VFS block layer之间的借口。通俗的理解,Block bufferpage cache和磁盘驱动器之间打交道的一层缓存。

 

系统页高速缓存的使用情况可以通过buffer/cache的监控数据来分析。

从文件读写角度来看,buffer多用于缓存文件的管信息,如目录位置,inode信息等。Cache缓存的是文件内容。

由于CPU不能直接处理外设上的数据,buffer用来标记那些文件的位置等描述信息。Cache主要目的是增加传输性能,用于缓存文件内容。

从操作系统的工作原理来讲,buffer/cache的目的主要是为了减少MPFs,增加MnPFs。

MPF

Kernel要读取数据的时候,首先会查找CPU 的cache然后是物理内存,如果没有会发出一个major page fault(MPF)。一个MPF可以看做是kernel发送的一个请求,将磁盘数据加载到内存。

MnPF

当磁盘数据被加载到内存当中,kernel再次读取时,会发出一个minor page fault(MnPF)。

下面的例子展示了第一次访问一个程序和第二次访问同样的程序所产生的MPF和MnPF。

/usr/bin/time -v java

Major (requiring I/O) page faults: 103

Minor (reclaiming a frame) page faults: 2356

第二次访问:

/usr/bin/time -v java

Major (requiring I/O) page faults: 0

Minor (reclaiming a frame) page faults: 2581

下图展示了磁盘高速缓存过程

强行同步全部页高速缓存

此处介绍强行将所有内存缓存数据同步到磁盘,并演示释放后的free输出结果

Free pagecache

Echo 1 > /proc/sys/vm/drop_caches;

Free dentries and inodes

Echo 2 > /proc/sys/vm/drop_caches;

Free pagecache and dentries and inodes

Echo 3 > /proc/sys/vm/drop_caches;

Direct I/O

有一些更复杂的程序(通常称为自缓存应用程序),更愿意自己控制I/O的传输过程(),通过将O_DIRECT标志位置位,I/O数据的传送便绕过了页高速缓存。

出于以下原因,系统页高速缓存技术是有害的:

  1. 处理页高速缓存的多余指令,降低了read(),write()的效率
  2. Read(),write()系统调用不是在磁盘和用户空间直接传送,而是分成两步:在磁盘和内核空间,在内核空间到用户空间。

 

与页高速缓存相关的系统参数

  1. /proc/sys/vm/dirty_background_ratio

表示系统可用内存中,最高可用于存储 dirty 数据的百分比。The maximum of percentage of((cache+free)-mapped)。缺省10%。

  1. /proc/sys/vm/dirty_ratio

表示进程产生的脏数据到达系统整体内存的百分比,此时触发pdflush进程把数据回写到磁盘。缺省设置40.

  1. /proc/sys/vm/dirty_expire_centisecs

表示脏数据在内存中驻留超过该值,pdflush会将该数据回写到磁盘。缺省是3000。

  1. /proc/sys/vm/dirty_writeback_centisecs

表示pdflush周期性间隔多久处理脏数据回写。 

强行同步全部页高速缓存

此处介绍强行将所有内存缓存数据同步到磁盘,并演示释放后的free输出结果

 

Free pagecache

Echo 1 > /proc/sys/vm/drop_caches;

 

Free dentries and inodes

Echo 2 > /proc/sys/vm/drop_caches;

 

Free pagecache and dentries and inodes

Echo 3 > /proc/sys/vm/drop_caches;

 

 

Direct I/O

有一些更复杂的程序(通常称为自缓存应用程序),更愿意自己控制I/O的传输过程(),通过将O_DIRECT标志位置位,I/O数据的传送便绕过了页高速缓存。

 

出于以下原因,系统页高速缓存技术是有害的:

1.      处理页高速缓存的多余指令,降低了read(),write()的效率

2.      Read(),write()系统调用不是在磁盘和用户空间直接传送,而是分成两步:在磁盘和内核空间,在内核空间到用户空间。

 

与页高速缓存相关的系统参数

1.      /proc/sys/vm/dirty_background_ratio

表示系统可用内存中,最高可用于存储 dirty 数据的百分比。The maximum of percentage of((cache+free)-mapped)。缺省10%

 

2.      /proc/sys/vm/dirty_ratio

表示进程产生的脏数据到达系统整体内存的百分比,此时触发pdflush进程把数据回写到磁盘。缺省设置40.

 

3.      /proc/sys/vm/dirty_expire_centisecs

表示脏数据在内存中驻留超过该值,pdflush会将该数据回写到磁盘。缺省是3000

 

4.      /proc/sys/vm/dirty_writeback_centisecs

表示pdflush周期性间隔多久处理脏数据回写。

作者: 
邓 悟
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics