[面试] Linux

207 阅读5分钟

06 Linux

性能优化

1. 概述

# 主要思路
  - 找到应用或系统的瓶颈, 然后设法避免或解决它;
# 核心指标
  - 网络型应用, 提升吞吐率;
  - 批处理应用, 加快计算速度;

2. 查看资源使用概况 (top 或 /proc)

# 1.查看资源使用概况
  - 使用 `top` 查看系统整体资源的使用情况, 尤其是所有进程的资源使用情况;
  - 使用 `free` 查看内存使用概况;
  - 使用 `iostat` 查看磁盘使用概况;
  - 使用 `iftop` 查看流量使用概况;

# 更详细地, 可以查看 /proc 文件夹下的文件
  - /proc : 该文件夹是伪文件系统, 它通过文件系统的形式展现内核和进程的动态资源
  - cpuinfo 文件: CPU 资源使用情况;
  - meminfo 文件: 内存资源使用情况;
  - /proc/num 文件夹: pid 为 num 进程的资源文件, 可以看到 `cmdline` 进程启动命令, `environ` 环境变量配置等等;
  - 还可以直接通过修改文件的值, 改变内核参数, 如: 修改 icmp_echo_ignore_all 参数, 控制主机不响应 ping 命令;

3. 查看进程系统调用 (strace)

# 查看系统调用
  - `strace` 命令可以监控进程运行过程中的系统调用, 信号传递等;
  - 如果一个进程无法启动的原因在于系统调用, `strace` 可以找出在哪个系统调用时出错, 如: 用 open() 打开了不存在的文件;
  - 如果一个进程打开后被关闭, `strace` 可以找出被哪个进程发出的 kill 信号关闭的;
  - 如果一个进程效率低, `strace` 可以记录运行过程中触发的所有系统调用信息, 一般频繁的创建和销毁子进程非常耗时;

4. 查看进程资源分类使用情况 (pidstat)

# 思路
  - 利用 `pidstat -u` 查看进程 CPU 分类时间的占用情况, 定位进程在哪个方面存在问题和瓶颈;
# CPU 时间分类
  - 诺用户 CPU 占用过高: 问题出在用户逻辑代码端, 比如算法复杂度过高, 优化算法; 
  - 诺系统 CPU 占用过高: 问题出在系统调用, 比如大量系统调用, 创建子进程等;
  - 诺I/O等待 CPU 过高: 问题出在磁盘或网络的读写, 可能是阻塞的方式, 可以改用非阻塞或 I/O 复用的方式优化;
# 更具体地
  - 利用 `pidstat -r` 查看进程 内存 分类的占用情况, 定位进程在哪个方面存在问题和瓶颈;
  - 利用 `pidstat -d` 查看进程 IO 分类的占用情况, 定位进程在哪个方面存在问题和瓶颈;
  - 利用 `pidstat -w` 查看进程 上下文切换 的情况, 定位进程在哪个方面存在问题和瓶颈;

5. 性能统计分析工具 (perf)

# 思路
  - 通过不同类型的中断, 来触发计数器进行采样统计的性能分析工具, 具有系统级(top), 进程级(stat), 函数级(record) 三种不同的粒度;
# 触发事件分类
  - (硬件)时钟中断, 缺页中断等;
  - (软件)上下文切换;
# 分析流程
  - 主要可以用时钟中断的方式, 对程序的性能进行分析;
  - 首先, 用 `perf top`, 找出占用整个 CPU 时间最多的进程;
  - 再用 `perf stat`, 指定该进程, 查找它哪个类型的 CPU 时间占用最多;
  - 最后, 用 `perf record`. 进一步找到该进程哪个函数的 CPU 时间占用最多;

其他

1. 文件软硬连接

# 文件存储架构
  - 文件路径 : 描述文件对象
  - inode表 : 记录文件路径 和 对应的 inode 编号
  - metadata : 根据 inode 编号, 可以找到文件元数据信息
  - data block : 文件元数据中记录了数据的具体信息, 包括数据块数量和具体存放位置

# 硬连接
  - ln a b
  - 多个文件名 指向 一个文件 来解决源文件共享的问题
  - 存在问题: 无法跨分区创建链接

# 软连接
  - ln -s a b
  - 独立文件, 包含文件名称, inode 编号, metadata 数据, block
  - block 中存放的数据是 被链接文件的指向

2. 僵尸进程排查

# Kill 父进程
  - 找到父进程, 然后把它杀死;
  - 僵尸进程自动过继给 init 进程, 由其杀死;

# 修改代码
  - 在代码中定位 fork 函数, 或者是其他可能产生子进程的函数;
  - 检查产生子进程后, 是否调用 wait 函数将其资源作回收;

3. 内存泄露排查

# 智能指针
  - 使用智能指针代替普通指针;
  - 完成对象资源的自动回收;
# 自定义对象计数器
  - 在类中定义计数器变量;
  - 在类对象构造时, 计数器++. 类对象析构时, 计数器--;
  - 定时打印类对象名称和数量, 诺发现有类对象的数量一直增长, 就说明它有内存泄露的问题;

4. make 和 makefile

# make
  - 用于实现大型 C++ 项目的 ‘自动化编译’;
  - 主要通过编写 makefile 文件, 确定文件的依赖关系和文件编译的先后顺序, 然后直接通过 make 命令生成可持续文件;
# makefile 编写规则
  - all: tag1 tag2 ...
    * 执行 make 后编译的标签清单;
  - tag1: file1 file2 ...
    * 依赖于标签 tag1 的源文件, 如果依赖的源文件内容发生了变化,再次执行 make 的时候就会重新编译 tag1;
  - [tab] gcc -o ...
    * 编译命令,和在操作系统命令行输入的命令一样,但前面要用 tab 空开, 可以输入多行命令;
  - clean:
          cmd1 ...
    * clean 不依赖于任何文件;
    * 使用 make clean 执行的命令, 可以省略;
# 变量
  - 设置: CC=gcc
  - 使用: $(CC)
  - 好处
    * 让文件更加简洁;
    * 便于修改, 只要修改变量的设定, 就可以改变全局;
#