多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 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 ~~~