## SRS性能(CPU)、内存优化工具用法
## RTC
RTC是UDP的协议,先设置`网卡队列缓冲区`,下面命令是UDP分析常用的:
~~~bash
# 查看UDP缓冲区长度,默认只有200KB左右。
sysctl net.core.rmem_max &&
sysctl net.core.rmem_default &&
sysctl net.core.wmem_max &&
sysctl net.core.wmem_default
# 修改缓冲区长度为16MB
sysctl net.core.rmem_max=16777216
sysctl net.core.rmem_default=16777216
sysctl net.core.wmem_max=16777216
sysctl net.core.wmem_default=16777216
~~~
也可以修改系统文件`/etc/sysctl.conf`,重启也会生效:
~~~bash
# vi /etc/sysctl.conf
# For RTC
net.core.rmem_max=16777216
net.core.rmem_default=16777216
net.core.wmem_max=16777216
net.core.wmem_default=16777216
~~~
查看接收和发送的丢包信息:
~~~bash
# 查看丢包
netstat -suna
# 查看30秒的丢包差
netstat -suna && sleep 30 && netstat -suna
~~~
> 实例说明:
> `224911319 packets received`,这是接收到的总包数。
> `65731106 receive buffer errors`,接收的丢包,来不及处理就丢了。
> `123534411 packets sent`,这是发送的总包数。
> `0 send buffer errors`,这是发送的丢包。
> 备注:SRS的日志会打出UDP接收丢包和发送丢包,例如`loss=(r:49,s:0)`,意思是每秒有49个包来不及收,发送没有丢包。
查看接收和发送的长度:
~~~bash
netstat -lpun
~~~
> 实例说明;
> `Recv-Q 427008`,程序的接收队列中的包数。Established: The count of bytes not copied by the user program connected to this socket.
> `Send-Q 0`,程序的发送队列中的包数目。Established: The count of bytes not acknowledged by the remote host.
下面是netstat的一些参数:
> `--udp|-u` 筛选UDP协议。
> `--numeric|-n` 显示数字IP或端口,而不是别名,比如http的数字是80.
> `--statistics|-s` 显示网卡的统计信息。
> `--all|-a` 显示所有侦听和非侦听的。
> `--listening|-l` 只显示侦听的socket。
> `--program|-p` 显示程序名称,谁在用这个FD。
## PERF
PERF是Linux性能分析工具,参考\[PERF\](perf record -e block:block\_rq\_issue -ag)。
可以实时看到当前的SRS热点函数:
~~~dart
perf top -p `ps aux|grep srs|grep conf|awk '{print $2}'`
~~~
或者记录一定时间的数据:
~~~bash
perf record -p `ps aux|grep srs|grep conf|awk '{print $2}'`
# 需要按CTRL+C取消record,然后执行下面的
perf report
~~~
记录堆栈,显示调用图:
~~~dart
perf record -a --call-graph fp -p `ps aux|grep srs|grep conf|awk '{print $2}'`
perf report --call-graph --stdio
~~~
> Note: 也可以打印到文件`perf report --call-graph --stdio >t.txt`。
> Remark: 由于ST的堆栈是不正常的,perf开启`-g`后记录的堆栈都是错乱的,所以perf只能看SRS的热点,不能看堆栈信息;如果需要看堆栈,请使用`GPERF: GCP`,参考下面的章节。
## GPROF
GPROF是个GNU的CPU性能分析工具。参考[SRS GPROF](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fossrs%2Fsrs%2Fwiki%2Fv1_CN_GPROF),以及[GNU GPROF](https://links.jianshu.com/go?to=http%3A%2F%2Fwww.cs.utah.edu%2Fdept%2Fold%2Ftexinfo%2Fas%2Fgprof.html)。
Usage:
~~~csharp
# Build SRS with GPROF
./configure --with-gprof && make
# Start SRS with GPROF
./objs/srs -c conf/console.conf
# Or CTRL+C to stop GPROF
killall -2 srs
# To analysis result.
gprof -b ./objs/srs gmon.out
~~~
## GPERF
GPERF是google tcmalloc提供的cpu和内存工具,参考[GPERF](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fossrs%2Fsrs%2Fwiki%2Fv1_CN_GPERF)。
### GPERF: GCP
GCP是CPU性能分析工具,就是一般讲的性能瓶颈,看哪个函数调用占用过多的CPU。参考[GCP](https://links.jianshu.com/go?to=http%3A%2F%2Fgoogle-perftools.googlecode.com%2Fsvn%2Ftrunk%2Fdoc%2Fcpuprofile.html)。
Usage:
~~~python
# Build SRS with GCP
./configure --with-gperf --with-gcp && make
# Start SRS with GCP
./objs/srs -c conf/console.conf
# Or CTRL+C to stop GCP
killall -2 srs
# To analysis cpu profile
./objs/pprof --text objs/srs gperf.srs.gcp*
~~~
图形化展示,在CentOS上安装dot:
~~~bash
yum install -y graphviz
~~~
然后生成svg图片,可以用Chrome打开:
~~~bash
./objs/pprof --svg ./objs/srs gperf.srs.gcp >t.svg
~~~
### GPERF: GMD
GMD是GPERF提供的内存Defense工具,检测内存越界和野指针。一般在越界写入时,可能不会立刻导致破坏,而是在切换到其他线程使用被破坏的对象时才会发现破坏了,所以这种内存问题很难排查;GMD能在越界和野指针使用时直接core dump,定位在那个出问题的地方。参考[GMD](https://links.jianshu.com/go?to=http%3A%2F%2Fblog.csdn.net%2Fwin_lin%2Farticle%2Fdetails%2F50461709)。
Usage:
~~~tsx
# Build SRS with GMD.
./configure --with-gperf --with-gmd && make
# Start SRS with GMD.
env TCMALLOC_PAGE_FENCE=1 ./objs/srs -c conf/console.conf
~~~
### GPERF: GMC
GMC是内存泄漏检测工具,参考[GMC](https://links.jianshu.com/go?to=http%3A%2F%2Fgoogle-perftools.googlecode.com%2Fsvn%2Ftrunk%2Fdoc%2Fheap_checker.html)。
Usage:
~~~python
# Build SRS with GMC
./configure --with-gperf --with-gmc && make
# Start SRS with GMC
env PPROF_PATH=./objs/pprof HEAPCHECK=normal ./objs/srs -c conf/console.conf 2>gmc.log
# Or CTRL+C to stop gmc
killall -2 srs
# To analysis memory leak
cat gmc.log
~~~
### GPERF: GMP
GMP是内存性能分析工具,譬如检测是否有频繁的申请和释放堆内存导致的性能问题。参考[GMP](https://links.jianshu.com/go?to=http%3A%2F%2Fgoogle-perftools.googlecode.com%2Fsvn%2Ftrunk%2Fdoc%2Fheapprofile.html)。
Usage:
~~~python
# Build SRS with GMP
./configure --with-gperf --with-gmp && make
# Start SRS with GMP
./objs/srs -c conf/console.conf
# Or CTRL+C to stop gmp
killall -2 srs
# To analysis memory profile
./objs/pprof --text objs/srs gperf.srs.gmp*
~~~
## VALGRIND
VALGRIND是大名鼎鼎的C分析工具,SRS3之后支持了。SRS3之前,因为使用了ST,需要给ST打PATCH才能用。
~~~jsx
valgrind --leak-check=full ./objs/srs -c conf/console.conf
~~~
> Remark: SRS3之前的版本,可以手动给ST打PATCH支持VALGRIND,参考[state-threads](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fossrs%2Fstate-threads%23usage),详细的信息可以参考[ST#2](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fossrs%2Fstate-threads%2Fissues%2F2)。
## Syscall
系统调用的性能排查,参考[centos6的性能分析工具集合](https://links.jianshu.com/go?to=https%3A%2F%2Fblog.csdn.net%2Fwin_lin%2Farticle%2Fdetails%2F9377209)
## OSX
在OSX/Darwin/Mac系统,可以用Instruments,在xcode中选择Open Develop Tools,就可以看到Instruments,也可以直接找这个程序,参考[Profiling c++ on mac os x](https://links.jianshu.com/go?to=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F11445619%2Fprofiling-c-on-mac-os-x)
~~~undefined
instruments -l 30000 -t Time\ Profiler -p 72030
~~~
> Remark: 也可以在Active Monitor中选择进程,然后选择Sample采样。
还有DTrace可以用,参考[动态追踪技术(中) - Dtrace、SystemTap、火焰图](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.cnblogs.com%2Fwelhzh%2Fp%2F9221155.html)或者[浅谈动态跟踪技术之DTrace](https://www.jianshu.com/p/6acd36976fba)。
## 多核和软中断
多核时,一般网卡软中断在CPU0上,可以把SRS调度到其他CPU:
~~~bash
taskset -p 0xfe `cat objs/srs.pid`
~~~
或者,指定SRS运行在CPU1上:
~~~bash
taskset -pc 1 `cat objs/srs.pid`
~~~
调整后,可以运行`top`,然后按数字`1`,可以看到每个CPU的负载:
~~~bash
top # 进入界面后按数字1
#%Cpu0 : 1.8 us, 1.1 sy, 0.0 ni, 90.8 id, 0.0 wa, 0.0 hi, 6.2 si, 0.0 st
#%Cpu1 : 67.6 us, 17.6 sy, 0.0 ni, 14.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
~~~
或者使用`mpstat -P ALL`:
~~~bash
mpstat -P ALL
#01:23:14 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
#01:23:14 PM all 33.33 0.00 8.61 0.04 0.00 3.00 0.00 0.00 0.00 55.02
#01:23:14 PM 0 2.46 0.00 1.32 0.06 0.00 6.27 0.00 0.00 0.00 89.88
#01:23:14 PM 1 61.65 0.00 15.29 0.02 0.00 0.00 0.00 0.00 0.00 23.03
~~~
> 可以使用命令`cat /proc/softirqs`,查看所有CPU的具体软中断类型,参考[Introduction to deferred interrupts (Softirq, Tasklets and Workqueues)](https://links.jianshu.com/go?to=https%3A%2F%2F0xax.gitbooks.io%2Flinux-insides%2Fcontent%2FInterrupts%2Flinux-interrupts-9.html)。
> 如果将SRS强制绑定在CPU0上,则会导致较高的`softirq`,这可能是进程和系统的软中断都在CPU0上,可以看到si也比分开的要高很多。
如果是多CPU,比如4CPU,则网卡中断可能会绑定到多个CPU,可以通过下面的命令,查看网卡中断的绑定情况:
~~~bash
# grep virtio /proc/interrupts | grep -e in -e out
29: 64580032 0 0 0 PCI-MSI-edge virtio0-input.0
30: 1 49 0 0 PCI-MSI-edge virtio0-output.0
31: 48663403 0 11845792 0 PCI-MSI-edge virtio0-input.1
32: 1 0 0 52 PCI-MSI-edge virtio0-output.1
# cat /proc/irq/29/smp_affinity
1 # 意思是virtio0的接收,绑定到CPU0
# cat /proc/irq/30/smp_affinity
2 # 意思是virtio0的发送,绑定到CPU1
# cat /proc/irq/31/smp_affinity
4 # 意思是virtio1的接收,绑定到CPU2
# cat /proc/irq/32/smp_affinity
8 # 意思是virtio1的发送,绑定到CPU3
~~~
我们可以强制将网卡软中断绑定到CPU0,参考[Linux: scaling softirq among many CPU cores](https://links.jianshu.com/go?to=http%3A%2F%2Fnatsys-lab.blogspot.com%2F2012%2F09%2Flinux-scaling-softirq-among-many-cpu.html)和[SMP IRQ affinity](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.kernel.org%2Fdoc%2FDocumentation%2FIRQ-affinity.txt):
~~~bash
for irq in $(grep virtio /proc/interrupts | grep -e in -e out | cut -d: -f1); do
echo 1 > /proc/irq/$irq/smp_affinity
done
~~~
> Note:如果要绑定到`CPU 0-1`,执行`echo 3 > /proc/irq/$irq/smp_affinity`
然后将SRS所有线程,绑定到CPU0之外的CPU:
~~~bash
taskset -a -p 0xfe $(cat objs/srs.pid)
~~~
## 进程优先级
可以设置SRS为更高的优先级,可以获取更多的CPU时间:
~~~bash
renice -n -15 -p `cat objs/srs.pid`
~~~
> 说明:nice的值从`-20`到`19`,默认是`0`,一般ECS的优先的进程是`-10`,所以这里设置为`-15`。
可以从ps中,看到进程的nice,也就是`NI`字段:
~~~bash
top -n1 -p `cat objs/srs.pid`
# PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
# 1505 root 5 -15 519920 421556 4376 S 66.7 5.3 4:41.12 srs
~~~
- 前言
- 服务器开发设计
- Reactor模式
- 一种心跳,两种设计
- 聊聊 TCP 长连接和心跳那些事
- 学习TCP三次握手和四次挥手
- Linux基础
- Linux的inode的理解
- 异步IO模型介绍
- 20个最常用的GCC编译器参数
- epoll
- epoll精髓
- epoll原理详解及epoll反应堆模型
- epoll的坑
- epoll的本质
- socket的SO_REUSEADDR参数全面分析
- 服务器网络
- Protobuf
- Protobuf2 语法指南
- 一种自动反射消息类型的 Protobuf 网络传输方案
- 微服务
- RPC框架
- 什么是RPC
- 如何科学的解释RPC
- RPC 消息协议
- 实现一个极简版的RPC
- 一个基于protobuf的极简RPC
- 如何基于protobuf实现一个极简版的RPC
- 开源RPC框架
- thrift
- grpc
- brpc
- Dubbo
- 服务注册,发现,治理
- Redis
- Redis发布订阅
- Redis分布式锁
- 一致性哈希算法
- Redis常见问题
- Redis数据类型
- 缓存一致性
- LevelDB
- 高可用
- keepalived基本理解
- keepalived操做
- LVS 学习
- 性能优化
- Linux服务器程序性能优化方法
- SRS性能(CPU)、内存优化工具用法
- centos6的性能分析工具集合
- CentOS系统性能工具 sar 示例!
- Linux性能监控工具集sysstat
- gdb相关
- Linux 下如何产生core文件(core dump设置)