Linux环境下C++程序问题诊断与调优总结

1、 CPU问题

  • 机器负载高
  • CPU消耗高
  • 响应时耗高
  • 资源消耗低,但是压力上不去
  • 上下文切换频繁,cache miss率高
  • 锁冲突严重

CPU问题分析总结

粗看系统负载情况: uptime,vmstat

开发测试环境+线上环境

机器实时的CPU资源消耗详细情况top

开发测试环境+线上环境

分析系统调用: strace

开发测试环境

分析函数的热点:perf,可以输出成火焰图便于直观观察

开发测试环境+线上环境

分析各个线程的资源消耗情况,线程内的函数消耗情况: valgriand

开发测试环境

分析程序各个线程的堆栈执行情况: pstack & pt-pmp

开发测试环境

2、磁盘IO问题

  • IO消耗太多,引起系统影响慢
  • 大量随机IO
  • 句柄泄漏
  • swap引起系统响应变慢
  • 写入磁盘的数据丢失,磁盘损坏等

使用dd和fio测试IO的性能4.iostat输出结果会解读
iotop观察具体进程IO的消耗情况
通过proc文件系统和lsof分析句柄的使用,定位是否有句柄泄漏,某个句柄具体对应哪个文件

3、网络IO问题

  • 网络不通
  • 延时大
  • 网络超时,丢包
  • 连接异常
  • 大量无效连接
  • 网卡跑满
  • CPU处理网卡中断繁忙

1.通过netstat查看网络连接状况
2.lsof分析具体端口被谁占用
3.通过sar查看网卡流量
4.利用tcpdump& wireshark进行网络包的分析

4、内存问题

  • 内存消耗多,内存泄漏,内存碎片
  • 内存分配回收性能差
  • 内存越界,空指针,野指针
  • 系统coredump或者数据异常

1.C++开发的时候必须掌握智能指针
2.熟练使用valgriand分析内存泄漏
3.了解多线程内存库jemalloc/tcmalloc
4.free的输出结果会解读
5.建议关闭swap
6.熟悉/proc/sys/vm/下的参数,比如控制刷脏页的频率,脏页占有量,swappinness等

其他

程序调试工具gdb

gdb∶常见的调试入口信息

  1. gdb ./testperf通过调试的方式启动程序
  2. gdb-p 81369对指定的进程进行调试
  3. gdb testperf core-testperf-52784-1555319546程序异常退出产生core,可以用来调试

[译]Linux性能分析的前60000毫秒

总结

1.假如运营人员突然反馈你负责的系统响应变慢,并给出了具体的IP机器,如何分析问题
回答:
系统响应变慢,说明系统内的机器负载较高,对CPU的消耗也在增高,此时我可以从以下几个步骤对具体IP的机器进行测试:

(1)首先使用uptime分析该机器的load average,查看该机器是否负载数量突然增多,超出承受范围;
(2)进一步,使用vmstat指令整个机器的CPU、内存和IO的使用情况,如果r经常大于4,且id经常少于40,表示cpu的负荷很重;如果pi,po长期不等于0,表示内存不足;如果disk经常不等于0,且在b中的队列大于3,表示io性能不好;
(3)进一步,对该机器内不同进程、线程占用的CPU情况进行查看,首先使用top指令查看进程的CPU占用情况,然后使用top -Hp (PID号)查看线程的占用情况,进而定位到该机器的具体线程或进程。根据不同步骤的结果,针对不同的情况,做出不同的解决方案,如提升系统性能、等待用户不使用机器、关掉CPU占用过高且不必要的进程或线程。

学习资料:Linux vmstat命令实战详解

2.线上某个多线程程序的CPU突然有大量CPU消耗,如何定位到哪个线程或者函数最消耗资源
回答:

此时我们可以按照以下顺序进行操作:
(1)使用top命令查看cpu占用情况,查看各个进程的PID编号和%CPU的值,可以获得占用CPU过高的进程;
(2)执行top -Hp (PID号),针对指定进程查看进程中的每个程序或线程的CPU消耗情况,然后就可以定位到哪个线程最消耗资源;
(3)使用valgriand指令分析线程内的函数消耗情况,然后就可以定位到具体的函数。
学习资料:https://bestxf.blog.csdn.net/article/details/118193165

3.什么场景下可以使用火焰图
回答:
首先当我们需要对程序的性能进行调优时,为了精确分析函数的性能,需要使用或沿途。另外,通过学习,我了解到常见的火焰图类型有 On-CPU, Off-CPU, 还有 Memory, Hot/Cold和Differential等,我们使用哪种或沿途取决于当前程序性能的瓶颈到底是什么, 如果是 CPU 则使用On-CPU火焰图, 如果是 IO、死锁等则使用 Off-CPU 火焰图。
学习资料:https://blog.csdn.net/gatieme/article/details/78885908/

4.线上程序突然被重启了,如何分析重启的原因
回答:
Linux线上重启的原因有很多,可以从以下方面查找重启的原因:
(1)硬件问题导致服务器重启:比如CPU温度过高重启,此时可以查看服务器日志,找到报错信息进行分析;
(2)程序占用CPU过高或内存过大,导致重启:在未重启时使用top指令和top -Hp PID查询线程的CPU占用率;使用perf指令分析,利用PMU、tracepoint和内核中的计数器来分析CPU瓶颈。
(3)代码优化、内存泄露问题:使用valgriand指令分析程序性能;检查线上程序的指针是否正确使用。
学习资料:
https://blog.csdn.net/weixin_39559097/article/details/116794316
https://baijiahao.baidu.com/s?id=1639738378446401682&wfr=spider&for=pc
https://www.sohu.com/a/292825608_467784

5.开发的程序锁冲突严重,如何定位是哪个地方的锁引起的
回答:
(1)我们可以使用pstack和gdb工具对死锁程序进行分析,pstack命令可显示每个进程的栈跟踪,pstack $pid即可,连续多次查看进程的函数调用关系堆栈,死锁线程将一直处于等锁状态,对比多次的函数调用堆栈输出结果,确定哪两个线程(或者几个线程)一直没有变化且一直处于等锁的状态。这样就可以查看是哪几个进程发生了死锁。
然后,通过gdb attach到死锁进程,查看线程的输出,分析是否出现了进程出现了交叉持锁的现象,最后去源代码中查看是否程序有问题。
(2)利用core文件来分析死锁。首先运行./deadlock(编译的时候加调试选项-g),并生成coredump文件;然用gdb来调试coredump文件,可以看到每个线程的信息和死锁的信息。
(3)利用valgrind来分析死锁。执行valgrind --tool=drd指令把互斥量相关的信息打印出来,查看是否是程序死锁的问题;然后执行valgrind --tool=helgrind,当程序发生死锁时,利用ctrl+c终止,可以在结果中看到程序是锁死在哪一行程序,这样就可以分析出是哪个地方的锁导致的。
学习资料:https://blog.csdn.net/weixin_29216353/article/details/116735394

6.如何查看机器脏页的数量,如何加快淘汰方式,page cache如何清理
回答:
脏页是page cache中被设置了PG_dirty标志的页面,输入指令:cat /proc/vmstat | egrep ‘dirty|writeback’,输出的nr_dirty代表脏页的数量。
加快淘汰方式:调节/proc/sys/vm/下的参数,例如/proc/sys/vm/ dirty_background_ratio文件表示脏页数据到达系统整体内存的百分比后,触发pdflush进程把脏数据写回磁盘;/proc/sys/vm/dirty_expire_centisecs文件表示如果脏数据在内存中驻留时间超过该值,pdflush进程在下一次将把这些数据写回磁盘。控制刷脏页的频率,脏页占有量等。
清理page cache,输入echo 1 >/proc/sys/vm/drop_caches ;
学习资料:
https://www.cnblogs.com/itfenqing/p/6118346.html
https://blog.csdn.net/csCrazybing/article/details/78127506
https://blog.csdn.net/reliveIT/article/details/112369197

7.内存泄漏用啥工具检测,检测的原理是什么
回答:
在Linux下,主要使用valgriand来分析源代码的内存问题,内存泄漏适合使用valgriand中的memcheck工具来检测。
原理:Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。
Memcheck 能够检测出内存问题,关键在于其建立了Valid-Value和Valid-Address两个全局表,在Valid-Value表中,对于进程的整个地址空间中的每一个字节,都有与之对应的8个 bits;对于CPU的每个寄存器,也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。在Valid-Address 表中,对于进程整个地址空间中的每一个字节,还有与之对应的bit,记录该地址是否能够被读写。
当要读写内存中某个字节时,首先检查这个字节对应的 A bit。如果该A bit显示该位置是无效位置,memcheck 则报告读写错误。当内存中的某个字节被加载到CPU 中时,该字节对应的V bit也被加载到虚拟的CPU环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则memcheck会检查对应的V bits,如果该值尚未初始化,则会报告使用未初始化内存错误。
学习资料:
https://blog.csdn.net/qq_36219792/article/details/78095343
Memcheck: a memory error detector

8.如何查看本机网卡是否有丢包现象
回答:
(1)wireshark抓包分析:在wireshark软件中对指定IP地址进行抓包,将抓取到的数据包数量与发送的包数量进行对比。
(2)使用ping的方式:在终端命令界面输入ping + IP,查看丢包率。

学习资料:
https://blog.csdn.net/qq_28948353/article/details/82015745?spm=1001.2014.3001.5501
https://blog.csdn.net/hs_shengxiaguangnian/article/details/100552518

9.怎么查看本机是否time wait状态的网络连接,如果存在大量这种连接,如何处理,处理方案是否存在风险
服务端在完成一次请求后会主动关闭连接,等到2MSL时间之后,彻底关闭回收资源,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,此时我们可以通过指令netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'来查看处于TIME_WAIT的连接数。
通过调整/etc/sysctl.conf文件中的参数,让服务器能够快速回收和重用那些处于TIME_WAIT状态的资源来处理。在文件中加入以下内容:
net.ipv4.tcp_syncookies = 1//开启SYN cookies
net.ipv4.tcp_tw_reuse = 1//将TIME-WAIT sockets重新用于新的TCP连接
net.ipv4.tcp_tw_recycle = 1//开启TCP连接中TIME-WAIT sockets的快速回收
net.ipv4.tcp_fin_timeout = 30//修改系統默认的 TIMEOUT 时间
这样做可以在一定程度上减少处于time wait状态的网络连接数,但是存在风险:(1)在2MSL时间内刚断开连接的请求可能会造成干扰,即上一次连接中的包重新出现,影响新连接;(2)TCP关闭存在不可靠情况:主动关闭方发送的最后一个ack(fin),有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是CLOSED。
学习资料:
https://blog.csdn.net/shootyou/article/details/6622226
https://www.cnblogs.com/sidesky/p/6844565.html

10.如何查看机器历史某一天IO的消耗情况,能查看哪些指标,时间精度是咋样的,查看是平均值还是峰值
回答:
使用iostat指令和iotop指令。
iostat用于输出CPU和磁盘I/O相关的统计信息,显示的结果为从系统开机到当前执行时刻的统计信息。iostat可以查看的信息和精度如下:
在这里插入图片描述

iotop命令是一个用来监视磁盘I/O使用状况的top类工具,可以观察各个进程的IO消耗情况,可查看的信息和精度如下:

学习资料:
https://blog.csdn.net/tiancityycf/article/details/106746145
https://blog.csdn.net/qq_34944965/article/details/81117943

其他指令

1、Nmap(Network Mapper),是Linux下的网络扫描和嗅探工具包,具有以下功能:(1)扫描主机端口,嗅探所提供的网络服务(2)探测一组主机是否在线(3)推断主机所用的操作系统,到达主机经过的路由,系统已开放端口的软件版本。
2、free命令,查看系统实际使用内存的情况
在这里插入图片描述

3、ifconfig指令,查看本机的IP信息,
在这里插入图片描述

4、ping命令:测试网络连接

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值