Linux_性能优化_1.性能优化概述(perf)

目录:

优化

系统级优化

如何做优化?

1、任务调度带来任务切换的开销
perf性能检测工具的安装栈空间速度比堆空间快的原因例:线程池
2、系统调用带来用户态和内核切换的开销
3、代码级别优化
热点函数,文件收集性能优化工具




优化

1. 算法优化,选择优秀的数据结构和算法。

2. 代码优化,提高执行速度,减少内存占用。



系统级优化

更加有效地利用硬件和操作系统资源

  • 上下文切换次数评估 —> 降低OS开销
  • 缺页异常次数评估 —> 减少页面交换
  • IPC 评估 —> 提高CPU利用率



如何做优化?

对症下药:系统性能瓶颈在哪里?

提高cpu使用效率。做更多计算任务


1、任务调度带来任务切换的开销

避免不必要的上下文切换

引起上下文切换的原因:

  • 时间片用完,CPU正常调度下一个任务

  • 被其他优先级更高的任务抢占

  • 执行任务碰到IO阻塞,调度器挂起当前任务,切换执行下一个任务

  • 用户代码主动挂起当前任务让出CPU时间( pthread_cond_wait )

  • 多任务抢占资源,由于没有抢到被挂起(mutex )
    (加锁的粒度要细化)

  • 硬件中断/软中断

perf性能检测工具


perf性能检测工具的安装

   sudo apt install linux-tools-common
   
   sudo apt install linuex-tools-4.15***-generic
   
   sudo apt install linux-tools-generic

输入sudo perf stat ls,执行ls命令,收集特定进程的性能概况,

[yola2626@ubuntu ~]$sudo perf stat ls

//ls执行的打印...

 Performance counter stats for 'ls':

// 任务真正占用的处理器时间,单位为 ms。
              0.94 msec task-clock                #    0.309 CPUs utilized //CPU 的占用率。  
// 程序在运行过程中上下文的切换次数      
                21      context-switches          #    0.022 M/sec 
// 程序在运行过程中发生的处理器迁移次数。
                 0      cpu-migrations            #    0.000 K/sec
// 缺页异常的次数
               100      page-faults               #    0.107 M/sec                  
   <not supported>      cycles                                                      
   <not supported>      instructions                                                
   <not supported>      branches                                                    
   <not supported>      branch-misses                                               

       //花费时间
       0.003022606 seconds time elapsed

       0.000000000 seconds user
       0.001261000 seconds sys

CPU-migrations:程序在运行过程中发生的处理器迁移次数。
Linux为了维持多个处理器的负载均衡, 在特定条件下会将某个任务从一个CPU迁移到另一个CPU。

CPU迁移和上下文切换:
发生上下文切换不一定会发生CPU迁移,而发生CPU迁移时肯定会发生上下文切换。发生上下文切换有可能只是把上下文从当前CPU中换出,下一次调度器还是将进程安排在这个 CPU上执行。

page-faults:缺页异常的次数

  • 当应用程序请求的页面尚未建立、请求的页面不在内存中

  • 请求的页面虽然在内存中,但物理地址和虚拟地址的映射关系尚未建立时,都会触发一次缺页异常

  • 另外 TLB 不命中,页面访问权限不匹配等情况也会触发缺页异常。

栈空间速度比堆空间快的原因

1. 栈空间在申请空间时是4K的整数倍,跟物理页是对等的,缺页异常次数较少
2. 硬件上,栈顶指针时刻在寄存里,不会从寄存器唤出,效率高

物理内存不足

LRU (最近最少使用算法)
比较冷的物理页 — 放入 Windows 虚拟内存 / Linux swap分区 (缺页异常)

TLB快表
| 虚拟地址 | 物理地址|
|         |        |

TLB未命中,通过多级页表进行翻译得到物理地址


cycles:消耗的处理器周期数。
如果把被 ls 使用的 cpu cycles 看成是一个处理器的,那么它的主频可以用cycles / task-clock算出。

stalled-cycles-frontend:
指令读取或解码的质量步骤,未能按理想状态发挥并行左右,发生停滞的时钟周期。


stalled-cycles-backend: 指令执行步骤,发生停滞的时钟周期。

instructions: 执行了多少条指令。IPC为平均每个cpu cycle执行了多少条指令。

branches: 遇到的分支指令数。branch-misses是预测错误的分支指令数。

避免锁引起的调度,实现无锁设计



例:线程池

上下文切换开销

  1. 主线程 和 子线程 来回切换执行
  2. mutex 加解锁

情景1:
服务器16个核
1000个用户,每人下载10M大小的文件
最短时间

  1. 创建多少个线程数(16 / 1000)— 17 (16个线程 自动均衡到每个核 )
  2. 怎么设计加解锁 — 16个队列 锁的粒度 加解锁次数少

情景2:
1000个用户,每人下载100M大小的文件 每人时刻都在下载文件
63 new_fd 分给一个线程

假如使用
for()
{
 发给每个用户
}

结构体
struct{
 int new_fd;
 int pos; //mmap对应地址下标
}




2、系统调用带来用户态和内核切换的开销

查看使用 ls 系统调用次数

[yola2626@ubuntu ~]$ sudo perf stat -e raw_syscalls:sys_enter ls

Performance counter stats for 'ls':

                94      raw_syscalls:sys_enter                                      

       0.003045539 seconds time elapsed

       0.001715000 seconds user
       0.000000000 seconds sys

系统调用造成用户态上下文栈压栈弹栈,有损耗。降低系统调用使用次数

例如:

  • 反复的read,write,就改为mmap,消息队列没有共享内存实现的消息队列快

  • 多次的malloc可以升级为一次malloc

  • 持久使用一块内存可以用大页 4K 2M 1G hugepages 避免发生tlb miss

  • 通过使用 sendfile及splice 降低系统调用带来的开销 零COPY
    进程池sendfile和splice




3、代码级别优化

热点函数,文件收集

使用示例程序:

#include <stdio.h>

#define N 1000000

void cal()
{
    int i = 0;
    for(i = 0; i < 100; i++)
    {
    }
}

int main()
{
    int i;
    printf("I am printf\n");
    for(i = 0; i < N; i++)
    {
        cal();
    }
}

使用 perf 指令

//生成perf.data文件
sudo perf record -g ./a.out

//读取perf record生成的perf.data文件,并显示分析数据 
sudo perf report -i perf.data

得到

Samples: 158  of event 'cpu-clock:pppH', Event count (approx.): 39500000                                                                                     
  Children      Self  Command  Shared Object     Symbol                                                                                                      
+  100.00%     0.00%  a.out    [unknown]         [.] 0x0706258d4c544155                                                                                     ?
+  100.00%     0.00%  a.out    libc-2.27.so      [.] __libc_start_main                                                                                      ?
+   99.37%     1.90%  a.out    a.out             [.] main                                                                                                   ?
+   98.10%    98.10%  a.out    a.out             [.] cal 

热点函数为 cal

高频的文件打开,需要持久打开,或者常驻内存
打开以后,队列里面去

Mysql数据库 访问过多,拒绝访问,怎么办?

100个连接,队列机制,建立连接池( 队列 )


使用 Redis — 内存数据库( Redis 是一个高性能的key-value数据库。 )【Redis



lsof (命令)统计系统打开的所有文件

函数热点分支收集



性能路径频繁调用的小函数内联化

修改为static inline实现函数内联 (函数前加static inline

static inline void cal()



cache tlb 及分支预取优化
http://www.cnblogs.com/lirunzhou/p/5883698.html http://blog.csdn.net/adam040606/article/details/49563453



性能优化工具列表

perf,oprofile,gprof,systemtap

linux有许多非常好用的性能分析工具,这里是最常用的几个:

  1. perf 应该是最全面最方便的一个性能检测工具。由linux内核携带并且同步更新,基本能满足日常使用。推荐使用。
  2. oprofile 差不多是一个较过时的性能检测工具了,基本被 perf 取代,命令使用起来也不太方便。 比如opcontrol –no-vmlinux , opcontrol –init 等命令启动,然后是 opcontrol –start, opcontrol – dump, opcontrol -h 停止,opreport 查看结果等,一大串命令和参数。有时候使用还容易忘记初始化,数据就是空的。
  3. gprof 主要是针对应用层程序的性能分析工具,缺点是需要重新编译程序,而且对程序性能有一些 影响。不支持内核层面的一些统计,优点就是应用层的函数性能统计比较精细,接近我们对日常性 能的理解,比如各个函数时间的运行时间,,函数的调用次数等,很人性易读。
  4. systemtap 其实是一个运行时程序或者系统信息采集框架,主要用于动态追踪,当然也能用做性 能分析,功能最强大,同时使用也相对复杂。不是一个简单的工具,可以说是一门动态追踪语言。 如果程序出现非常麻烦的性能问题时,推荐使用 systemtap。


Gcov,lcov 统计代码覆盖率

工具功能
gcov生成代码覆盖信息
lcov把文字的代码覆盖率信息转换成更直观的图形表格模式



Benchmark

Benchmark简介
Benchmark是一个评价方式,在整个计算机领域有着长期的应用。Benchmark在计算机领域应用最成功的就是性能测试,主要测试负载的执行时间、传输速度、吞吐量、资源占用率等。
性能调优的两大利器是 Benchmark 和 profile工具。Benchmark用压力测试挖掘整个系统的性能状况,而profile工具最大限度地呈现系统的运行状态和性能指标,方便用户诊断性能问题和进行调优。

Benchmark的组成
Benchmark的核心由3部分组成:数据集、 工作负载、度量指标。

kememleak 内存泄漏检测工具
memcheck 内存检查工具

valgrind 检测内存泄漏


推荐的一些文章:

Linux内核 TCP/IP、Socket参数调优

十条命令在一分钟内检查 Linux 服务器性能

高并发性能调试经验分享

最高效的进(线)程间通信机制–eventfd

linux新API—signalfd的使用方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值