本网站相关文章:

性能

在平常开发工作中, 我们实际上很少去关注程序运行的时长, 程序运行的健壮性, 程序运行的资源损耗, 如果程序遇到问题, 大不了关闭调试, 关闭进程, 重新来一遍. 犹记得大四学习的软件工程, 软件开发流程的瀑布模型: 需求分析->设计->实现->测试->整合测试->部署->维护. 在代码开发开发阶段的主要关注点是功能的实现, 关于性能损耗会在设计阶段或者后续测试维护才考虑.

对于小公司, 开发者往往负责了设计, 实现, 测试,整合测试的大部分工作, 因为时间分配的问题, 导致很多项目在前期往往没有很好的考虑程序的性能问题, 只能在后期根据项目的具体使用量来进行优化. 那么,对于一个准备运行或者已运行在线上的项目, 我们有如下的疑问:

  • 我们如何做基准测试, 估计程序的最高处理负载?
  • 我们如何监控线上程序运行性能?
  • 我们如何有针对性的优化线上程序?

这三个问题时刻伴随着每一个开发者, 确保自己开发的程序能够健壮无误的运行在线上. 这篇文章我们主要简单的介绍性能测试工具, 性能监控工具, 性能调整工具. 之后重点介绍一下strace命令.

工具集

让我们首先了解一下各种工具在整个系统中的定位, 从而加深工具的用途, 在排查问题的时候有针对性的根据不同的命令进行排查. 当然, 大部分情况下, 我们仅仅需要了解其中的几个工具, 然后形成自己的工作流就可以, 就像基于 VIM 而形成的开发工具链, 基于 IDE 而形成的便捷的开发工具链, 各有各有的优势, 萝卜青菜各有所爱.

A) 让我们先看一下性能基准测试工具:

optimize-benchmark-tool

其中:

  • ab用于 web api 的压力测试;
  • sysbench 是高性能MYSQL极力推荐的模块化, 跨平台的多性能测试工具, 用于 IO, 内存, CPU, 数据库的性能测试;
  • openssl用于提供加密传输功能;
  • dd用于磁盘 IO 测试
  • swap用于增加交换内存;
  • ping 和 traceroute用于 ICMP 协议的网络连通性测试.

B) 让我们了解一下性能观察监控工具:

optimize-observability-tool

其中:

  • netstatlsof在查找进程占用协议端口, 占用文件资源方面是运维开发人员利器, 记住, linux 中一切皆是文件;
  • top, htop, free, sar, vmstat 等用于实时监控系统所有进程资源占用以及系统总资源配置;
  • iostat, iotop用于监控进程 IO 占用情况;
  • tcpdump用于网络数据包的抓取和捕获, 这个在线上处理网络请求的时候非常有用;
  • swapon用于系统 swap 的增加, 常常用于机器内存不足的情况下;
  • ethtool, netstat则用于网卡硬件设备检测工作.

C) 让我们了解一下系统性能优化调整工具:

optimize-tunning-tool

在了解了上述各种与系统性能相关的工具, 之后, 让我们重点了解一下strace, ltrace, 让我们带着问题往下了解相关知识点:

  • strace 是什么? 原理是什么?
  • strace 能够解决何种问题? 在何种应用场景中使用
  • strace 如何排查问题?

strace

介绍

场景: 在线程进程运行过程中, 有时候会发生进程不知名的卡顿, segment fault, 运行速度变慢等, 向此类疑难问题常常无法在线下测试环境中复现, 无法快速的通过代码来定位, 这时候就需要一些系统性能检测工具.

原理: strace用来 跟踪一个进程的系统调用或信号产生的情况, ltrace用来跟踪进程调用库函数的情况. 其中 strace 常常结合ps, lsof来查看某一个具体进程的系统调用以及信号触发情况. 其中 strace 和 ltrace 的原理都是类似, 使用 ptrace(拦截系统调用)系统调用跟踪调试运行中的进程, 依赖于系统支持.

注意, 这两者都仅仅针对已经在运行中的在介绍完strace相关的原理以及应用场景之后, 让我们了解一下strace命令的用法, 其常用命令如下:

  • -f: 除了跟踪当前进程外, 还跟踪其子进程
  • -o file: 将输出信息写到文件 file 中, 而不是显示到标准错误输出 stderr
  • -D: 显示调用时间戳
  • -p pid: 绑定到一个由 pid 对应的正在运行的进程, 此参数常用来调试后台进程

其中 strace 命令的输出说明:

1
2
3
brk(0)                                  = 0x8062aa8
brk(0x8063000) = 0x8063000
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0x92f) = 0x40016000

其中每一行都是一条系统调用, 等号左边是系统调用的函数名及其参数, 右边是该调用的返回值.

例子

现在让我们介绍一个排查线上 python 进程卡死的实例.

a) 查看卡死进程 ID, 并查看系统调用堆栈

1
2
3
ps -ef|grep visa_schedule
# 查看进程
strace -p <pid>

根据输出了解到整个进程一直卡死在读取 24 描述符, 那么如何知道 24 描述是干嘛呢?

b) 查看进程打开的某一个 fd 描述符

1
2
3
4
5
6
7
8
9
10
# 进入进程文件夹
cd /proc/<pid>/fd

# 查看进程当前的状态
cat status
# 查看进程堆栈信息
cat stack

# 查看该进程打开的所有描述符
ls -l

c) 利用 lsof 查看某一个文件描述符或者某一个进程的资源

1
2
3
4
5
# 查看进程打开的所有文件
lsof -p <pid>

# 查看所有打开24描述符的进程
lsof -d 24

参考