图片 1

Java性能优化权威指南-读书笔记(一)-操作系统性能监控工具

Linux-CPU性能优化,

前言

何为性能优化?个人认为,性能优化是为了提高应用程序或系统能力为目的。那么如何才能实现对应用程序的性能调优呢?这里很设计到很多的内容,包括Linux内核、CPU架构以及Linux内核对资源的分配以及管理,了解进程的创建过程等。这方面由于篇幅较多,所以我的文章就不过多介绍。接下来的几篇文章中,都是讲解如何发现应用程序故障根源为目标讲解,这也是每一个系统工程师应该具备的能力。废话不多说,我直接进入主题。

常用术语

  延时:延时是描述操作之后用来等待返回结果的时间。在某些情况下,它可以指的是整个操作时间,等同于响应时间。

  IOPS:每秒发生的输入/输出操作的次数,是数据传输的一个度量方法。对于磁盘的读写,IOPS指的是每秒读写的次数。

  响应时间:一般操作完成的时间。包括用于等待和服务的时间,也包括用来返回结果的时间。

  使用率:对于服务所请求的资源,使用率描述在所给定时间区间内资源的繁忙程度。对于春初资源来说,使用率指的就是所消耗的存储容量。

  饱和度:指的就是某一资源无法满足服务的排队工作量。

  吞吐量:评价工作秩序的速率,尤其是在数据传输方面,这个属于用于数据传输速度(字节/秒和比特/秒)。在某些情况下,吞吐量指的是操作的速度。

Linux内核功能

  CPU调度级别:各种先进的CPU调度算法,非一直存储访问架构(NUMA);

  I/O调度界别:I/O调度算法,包括deadline/anticipatory和完全公平队列(CFQ);

  TCP网络阻塞:TCP拥堵算法,允许按需选择;

常见问题

进程、线程和任务之间的区别是什么?

  进程通常定义为程序的执行。用以执行用户级别程序的环境。它包括内存地址空间、文件描述符、线程栈和寄存器。
  线程是某一进程中单独运行的程序。也就是说线程在进程之中。
  任务是程序完成的某一活动,可以使一个进程,也可以是一个线程。

参考连接:

什么是上下文切换?

  执行一段程序代码,实现一个功能的过程介绍,当得到CPU的时候,相关的资源必须也已经就位,就是显卡、内存、GPS等,然后CPU开始执行。这里除了CPU以外所有的就构成了这个程序的执行环境,也就是我们所定义的程序上下文。当这个程序执行完或者分配给他的CPU执行时间用完了,那它就要被切换出去,等待下一次CPU的临幸。在被切换出去的最后一步工作就是保存程序上下文,因为这个是下次他被CPU临幸的运行环境,必须保存。

I/O密集型和CPU密集型工作负载之间的区别?

  I/O密集型指的是系统的CPU耗能相对硬盘/内存的耗能能要好很多,此时,系统运作,大部分的状况是
CPU 在等
I/O(硬盘/内存)的读/写,此时CPU负载不高。CPU密集型指的是系统的硬盘/内存耗能相对CPU的耗能要好很多,此时,系统运作,大部分的状况是
CPU负载 100%,CPU 要读/写 I/O
(硬盘/内存),I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU负载很高。一般而言CPU占用率相当高,大部份时间用来做计算、逻辑判断等CPU动作的程序。

应用程序性能技术

1.选择I/O尺寸
  执行I/O的开销包括初始化缓冲区、系统调用、上下文切换、分配内核元数据、检查进程权限和限制、映射地址到设备、执行内核和驱动代码来执行I/O,以及在最后释放元数据和缓冲区。增加I/O尺寸是应用程序提高吞吐量的常用策略。
2.缓存
  操作系统用缓存提高文件系统的读性能和内存的分配性能,应用程序使用缓存也处于类似的原因。将经常执行的操作结果保存在本地缓存中以备后用,而非总是执行开销较高的操作。
3.缓冲区
  为了提高写操作性能,数据在送入下一层级之前会合并并放在缓冲区中。这样会增加写延时,因为第一次写入缓冲区后,在发送之前,还要等待后续的写入。

  1. 并发和并行
      并行:装在和开始执行多个可运行程序的能力(比如,同时接电话和吃饭)。为了利用多核处理器系统的优势,应用程序需要在同一时间运行在多颗CPU上,这种方式称为并行。应用程序通过多进程或多线程实现。
      并发:有处理多个任务的能力,不一定要同时。比如,接完电话在去吃饭,存在资源抢占;
      同步原语:同步原语监管内存的访问,当不允许访问时,就会引起等待时间(延时)。常见三种类型:
      mutex锁:只有锁持有者才能操作,其他线程会阻塞并等待CPU;
      自旋锁:自旋锁允许锁持有者操作,其他的需要自旋锁的线程会在CPU上循环自选,检查锁是否被释放。虽然这样可以提供低延时的访问,被阻塞的线程不会离开CPU,时刻准备着运行知道锁可用,但是线程自旋、等待也是对CPU资源的浪费。
      读写锁:读/写锁通过允许多个读者或者只允许一个写者而没有读者,来保证数据的完整性。
      自适应自旋锁:低延迟的访问而不浪费CPU资源,是mutex锁和自旋锁的混合。
    5.绑定CPU

关于CPU性能分析

uptime:
  系统负载,通过汇总正在运行的线程数和正在排队等待运行的线程数计算得出。分别反映1/5/15分钟以内的负载。现在的平均负载不仅用来表示CPU余量或者饱和度,也不能单从这个值推断出CPU或者磁盘负载。

vmstat:
  虚拟内存统计信息命令。最后几列打印系统全局范围内的CPU使用状态,在第一列显示可运行进程数。如下所示:

1234 [[email protected] ~]# vmstat procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----r  b   swpd   free   buff   cache   si   so    bi    bo   in   cs us sy id  wa  st0  0   0    14834208 158384 936512  0     0     0     0    1   3   0  0 100  0  0

提示:

  r: 运行队列长度和正在运行的线程数;

  b: 表示阻塞的进程数;

  swpd:
虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器;

  si: 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。

  so: 每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上;

  bi: 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒;

  bo: 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整;

  in: 每秒CPU的中断次数,包括时间中断;

  cs:  每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。

  st: cpu在虚拟化环境上在其他租户上的开销;

mpstat:
  多处理器统计信息工具,能够报告每个CPU的统计信息。

1234567891011121314151617 [[email protected] ~]# mpstat -P ALL 1Linux 2.6.32-573.el6.x86_64 (zbredis-30104)     09/14/2017  _x86_64_    (12 CPU) 03:14:03 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle03:14:04 PM  all    0.00    0.00    0.08    0.00    0.00    0.00    0.00    0.00   99.9203:14:04 PM    0    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    2    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    3    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    4    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    5    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    6    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    8    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM    9    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM   10    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.0003:14:04 PM   11    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

提示:

  irq: 硬件中断CPU用量;

  sofr: 软件中断CPU用量;
  steal: 耗费在服务其他租户的时间;
  guest: 花在访客虚拟机的时间;

  重要关注列有%user/%sys/%idle。显示了每个CPU的用量以及用户态和内核态的时间比例。可以根据这些值查看那些跑到100%使用率(%user
+
%sys)的CPU,而其他CPU并未跑满可能是由单线程应用程序的负载或者设备中断映射造成。

sar:

  系统活动报告器。用来观察当前的活动,以及配置用以归档和报告历史统计信息。基本上所有资源使用的信息,它都能够查看到。具体的参数说明如下所示:

  -A: 所有报告的总和,类似”-bBdqrRSuvwWy -I SUM -I XALL -n ALL -u ALL
-P ALL”参数一起使用;
  -b: 显示I/O和传输速率的统计信息;
  -B:显示分页状态;
  -d:硬盘使用报告;
  -r:内存和交换空间的使用统计;
  -g:串口I/O的情况;
  -b:缓冲区使用情况;
  -a:文件读写情况;
  -c:系统调用情况;
  -n: 统计网络信息;
  -q:报告队列长度和系统平均负载;
  -R:进程的活动情况;
  -y:终端设备活动情况;
  -w:系统交换活动;
  -x { pid | SELF | ALL
}:报告指定进程ID的统计信息,SELF关键字是sar进程本身的统计,ALL关键字是所有系统进程的统计;

常用参数组合:

  查看CPU:

  整体CPU统计— sar -u 3 2,表示采样时间为3秒,采样次数为2次;
  各个CPU统计— sar -P ALL 1 1,表示采样时间为1秒,次数为1次;

    1. 若 %iowait 的值过高,表示硬盘存在I/O瓶颈;
    2. 若 %idle 的值高但系统响应慢时,有可能是 CPU
等待分配内存,此时应加大内存容量;
    3. 若 %idle 的值持续低于1,则系统的 CPU
处理能力相对较低,表明系统中最需要解决的资源是 CPU;

  查看内存:

  查看内存使用情况 – sar -r 1 2

    kbcommit:保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap);
    %commit:这个值是kbcommit与内存总量(包括swap)的一个百分比;

  pidstat:主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存、设备IO、任务切换、线程等。

  cpu使用情况统计
    执行 “pidstat -u” 与单独执行 “pidstat”
  内存使用情况统计
    pidstat -r -p PID 1

    minflt/s: 每秒次缺页错误次数(minor page
faults),次缺页错误次数意即虚拟内存地址映射成物理内存地址产生的page
fault次数;
    majflt/s: 每秒主缺页错误次数(major page
faults),当虚拟内存地址映射成物理内存地址时,相应的page在swap中,这样的page
fault为major page fault,一般在内存使用紧张时产生;
  IO情况统计
    pidstat -d 1 2

关于CPU方面的优化

  1.编译器优化
  2.调度优先级和调度类(设置nice值)
    例如,nice -n 19 command
    renice 更改已经运行进程的优先级;
    chrt 命令显示并直接修改优先级和调度策略;
  3.进程绑定(一个进程可以绑定在一个或者多个CPU上)
    例如,taskset -pc 0-3 10790

  4.独占CPU
  5.BIOS调优

    启用睿频

出处:

参考:

查看评论

前言
何为性能优化?个人认为,性能优化是为了提高应用程序或系统能力为目的。那么如何才能实现对应用程序的性能…

一:CPU

  1. 用户态CPU是指执行应用程序代码的时间占总CPU时间的百分比。

系统态CPU是指应用执行操作系统调用的时间占总CPU时间的百分比。系统态CPU高意味着共享资源有竞争或者I/O设备之间有大量的交互。

提高应用性能和扩展性的一个目标就是尽可能降低系统态CPU使用率。

  1. CPU运行队列就是那些已经准备好运行、正等待可用CPU的轻量级进程。

当运行队列长度达到处理器的4倍或者更多时,系统的相应就非常迟缓了。

解决运行队列长有两种办法:

1). 增加CPU以分担负载;

2). 分析系统中运行的应用,改进CPU使用率;

1.top命令

1. vmstat

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 104956    868 825812    0    0     1     5   16   25  0  0 100  0  0

r:CPU运行队列长度,值是运行队列中轻量级进程的实际数量

us:用户态CPU使用率

sy:系统态CPU使用率

id:CPU空闲率

top命令能够实时显示系统中各个进程的资源占用状况。使用top命令输出如下:

2. top

top - 09:42:04 up 3 days, 3 min,  1 user,  load average: 0.00, 0.01, 0.05
Tasks: 108 total,   3 running, 105 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1015472 total,   104568 free,    84224 used,   826680 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   727760 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                          
  784 root      20   0  553064  16340   5748 S  0.0  1.6   0:21.48 tuned                                                                                            
  743 root      20   0  110512  13140    676 S  0.0  1.3   0:00.13 dhclient                                                                                         
 9678 polkitd   20   0  527456  13128   4680 S  0.0  1.3   0:00.09 polkitd                                                                                          
    1 root      20   0   43684   6176   3804 S  0.0  0.6   0:05.08 systemd                                                                                          

上半部分是整个系统的统计信息,下半部分是进程的统计信息。

P 按CPU占用率排序
M 按内存占用率排序
T 按CPU占用时间排序
H 查看详细线程信息

图片 1

二:内存

1.
系统在使用页面交换或虚拟内存时,访问swap中内存以及JVM垃圾回收swap中内存时,都存在内存置换(从swap中置换到内存),性能肯定有问题;

2.
锁竞争,一般来说让步时钟周期占用3%—5%或更多,说明java应用正面临锁竞争;

前半部分是统计信息,后半部分是进程信息。

vmstat

free:可用空闲内存;

si:内存页面换入;

so:内存页面换出;

       统计信息中:

pidstat

[test ~]$ pidstat -w -I -p 7938 5
Linux 3.10.0-229.20.1.el7.x86_64 (test)     11/13/2016  _x86_64_    (1 CPU)

07:56:42 PM   UID       PID      cswch/s     nvcswch/s  Command
07:56:47 PM     0      7938      3500.00     0.00  java
07:56:52 PM     0      7938      3500.00     0.00  java
07:56:57 PM     0      7938      3500.00     0.00  java

Average:        0      7938      3500.00     0.00  java

cswch/s:让步式上下文切换;

例如:处理器为3.0GHz双核,每个处理器上下文切换3500/2=1750,耗费的时钟周期1750*80000=140000000,因此上下文切换所占比例为:140000000/3000000000=4.7

 
 第一行:任务队列:<=>uptime命令。左->右依次:系统当前时间、系统运行时间、当前登录用户数。load
average:系统的平均负载,即任务队列的平均长度,3个值分别表示:1分钟,5分钟,15分钟登到现在的平均值。

三:网络

分布式Java应用的性能和扩展性受限于网络带宽或网络I/O的性能。

 
 第二行:进程统计信息:左->右依次:正在运行的进程数、睡眠进程数、停止的进程数、僵尸进程数。

nicstat

需要编译安装()

    Time      Int   rKB/s   wKB/s   rPk/s   wPk/s    rAvs    wAvs %Util    Sat
13:25:57     eth0    2.34    1.77    2.84    2.29   842.6   789.6  0.00   0.00
13:25:57       lo    0.00    0.00    0.00    0.00   85.49   85.49  0.00   0.00

Int:网络接口设备名

rKb/s:每秒读取的KB数

wKb/s:每秒写入的KB数

%Util:网络使用率

Sat:饱和度

  第三行:CPU统计信息,

四:磁盘

              us:用户空间CPU占用率、

iostat

[test ~]$ iostat -xm
Linux 3.10.0-229.20.1.el7.x86_64 (test)     11/13/2016  _x86_64_    (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.26    0.00    0.22    0.06    0.24   99.23

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvda              0.00     0.22    0.11    0.38     0.00     0.00    16.79     0.00    6.15    7.51    5.74   2.05   0.10
xvdb              0.00     0.00    0.00    0.00     0.00     0.00    18.07     0.00    7.04   10.93    6.36   2.75   0.00

              sy:内核空间CPU占用率、

五:统计

              ni:用户进程空间改变过优先级的进程CPU占用率、

sar

sar 1 3 查看当前CPU数据,每一秒刷新一次,统计三次
sar -q 查看平均负载
sar -r 查看内存使用状况
sar -W 查看页面交换发生状况
sar –b 查看I/O和传送速率的统计信息

              id:空闲CPU占用率、

              wa:等待输入输出的CPU时间百分比、

              hi:硬件中断请求、

              si:软件中断请求。

  第四行:左->右依次:内存总量、已使用内存、空闲内存、内核缓冲。

  第五行:  交换区总量、已使用交换区、空闲交换区大小、缓冲交换区

     后半部分

 PR= Priority:优先级

 NI= Nice value:负值优先级>正值优先级

 VIRT= Virtual Image (kb):进程使用的虚拟内存总量,单位KB。VIRT=SWAP+RES

 RES= Resident size (kb):进程使用的、未被换出的物理内存大小,单位KB

 SHR= Shared Mem size (kb):共享内存大小,单位KB

 S= Process
Status:进程状态,D:不可中断的睡眠状态,R:运行,T:跟踪/停止,Z:僵尸进程

 TIME+= CPU Time, hundredths:进程使用的CPU时间总计,单位1/100秒

 COMMAND= Command name/line:命令名或者命令行

还可能会出现的信息(top命令时可按下f键进行选择)

 PPID       = Parent Process Pid                                      

 RUSER      = Real user name                                          

 UID        = User Id                                                  

 GROUP      = Group Name:所有进程者的组名

 TTY        = Controlling
Tty:启动进程的终端名,不是从终端启动的进程显示为2

 P        = Last used cpu (SMP) :最后使用的cpu,仅在多cpu的情况下有意义

 SWAP       = Swapped size (kb):进程使用的虚拟内存中被换出的大小

 TIME       = CPU Time:进程使用的CPU时间总计,单位秒

 CODE       = Code size (kb):可执行代码占用物理内存大小

 DATA       = Data+Stack size
(kb):可执行代码以外的部分(数据段+栈)占用物理内存大小

 nFLT       = Page Fault count:页面错误次数

 nDRT       = Dirty Pages count:最后一次写入到现在,被修改的页面数

 WCHAN      = Sleeping in
Function:若该进程在休眠,则显示睡眠中的系统函数名

 Flags      = Task Flags <sched.h>:任务标志

2.sar命令

sar [options][<interval>[<count>]]