CPU品质优化,读书笔记6165金沙总站

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调优

    启用睿频

出处:

参考:

查看评论

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

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 查看详细线程信息

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:饱和度

三:网络

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

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

sar

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

二:内存

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

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

一:CPU

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

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

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

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

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

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

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

2). 分析系统中运行的应用,改进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

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空闲率

四:磁盘