加入收藏 | 设为首页 | 会员中心 | 我要投稿 莱芜站长网 (https://www.0634zz.com/)- 云连接、建站、智能边缘云、设备管理、大数据!
当前位置: 首页 > 综合聚焦 > Linux > 正文

Linux性能优化

发布时间:2023-02-20 10:14:08 所属栏目:Linux 来源:互联网
导读:高并发和响应快对应着性能优化的两个核心指标:吞吐和延时。 应用负载角度:直接影响了产品终端的用户体验 系统资源角度:资源使用率、饱和度等 性能问题的本质就是系统资源已经到达瓶颈,但请求的处理还不够快,无法支撑更多的请求。性能分析实际上就是找出

 
  栈 包括局部变量和函数调用的上下文等,栈的大小是固定的。一般8MB
 
  内存分配与回收
 
  分配
 
  malloc对应到系统调用上有两种实现方式:
 
  brk() 针对小块内存(<128K),通过移动堆顶位置来分配。内存释放后不立即归还内存,而是被缓存起来。
 
  **mmap()**针对大块内存(>128K),直接用内存映射来分配,即在文件映射段找一块空闲内存分配。
 
  前者的缓存可以减少缺页异常的发生,提高内存访问效率。但是由于内存没有归还系统,在内存工作繁忙时,频繁的内存分配/释放会造成内存碎片。
 
  后者在释放时直接归还系统,所以每次mmap都会发生缺页异常。在内存工作繁忙时,频繁内存分配会导致大量缺页异常,使内核管理负担增加。
 
  上述两种调用并没有真正分配内存,这些内存只有在首次访问时,才通过缺页异常进入内核中,由内核来分配
 
  回收
 
  内存紧张时,系统通过以下方式来回收内存:
 
  回收缓存:LRU算法回收最近最少使用的内存页面;
 
  回收不常访问内存:把不常用的内存通过交换分区写入磁盘
 
  杀死进程:OOM内核保护机制 (进程消耗内存越大oom_score越大,占用cpu越多oom_score越小,可以通过/proc手动调整oom_adj)
 
  echo -16 > /proc/$(pidof XXX)/oom_adj
  如何查看内存使用情况?
 
  free来查看整个系统的内存使用情况
 
  top/ps来查看某个进程的内存使用情况
 
  VIRT 进程的虚拟内存大小
 
  RES 常驻内存的大小,即进程实际使用的物理内存大小,不包括swap和共享内存
 
  SHR 共享内存大小,与其他进程共享的内存,加载的动态链接库以及程序代码段
 
  %MEM 进程使用物理内存占系统总内存的百分比
 
  怎样理解内存中的Buffer和Cache?
  buffer是对磁盘数据的缓存,cache是对文件数据的缓存,它们既会用在读请求也会用在写请求中。
 
  如何利用系统缓存优化程序的运行效率
  缓存命中率
 
  缓存命中率是指直接通过缓存获取数据的请求次数,占所有请求次数的百分比。命中率越高说明缓存带来的收益越高,应用程序的性能也就越好。
 
  安装bcc包后可以通过cachestat和cachetop来监测缓存的读写命中情况。
 
  安装pcstat后可以查看文件在内存中的缓存大小以及缓存比例。
 
  #首先安装Go
  export GOPATH=~/go
  export PATH=~/go/bin:$PATH
  go get golang.org/x/sys/unix
  go ge github.com/tobert/pcstat/pcstat
  dd缓存加速:
 
  dd if=/dev/sda1 of=file bs=1M count=512 #生产一个512MB的临时文件
  echo 3 > /proc/sys/vm/drop_caches #清理缓存
  pcstat file #确定刚才生成文件不在系统缓存中,此时cached和percent都是0
  cachetop 5
  dd if=file of=/dev/null bs=1M #测试文件读取速度
  #此时文件读取性能为30+MB/s,查看cachetop结果发现并不是所有的读都落在磁盘上,读缓存命中率只有50%。
  dd if=file of=/dev/null bs=1M #重复上述读文件测试
  #此时文件读取性能为4+GB/s,读缓存命中率为100%
  pcstat file #查看文件file的缓存情况,100%全部缓存
  O_DIRECT选项绕过系统缓存:
 
  cachetop 5
  sudo docker run --privileged --name=app -itd feisky/app:io-direct
  sudo docker logs app #确认案例启动成功
  #实验结果表明每读32MB数据都要花0.9s,且cachetop输出中显示1024次缓存全部命中
  但是凭感觉可知如果缓存命中读速度不应如此慢,读次数时1024,页大小为4K,五秒的时间内读取了1024*4KB数据,即每秒0.8MB,和结果中32MB相差较大。说明该案例没有充分利用缓存,怀疑系统调用设置了直接I/O标志绕过系统缓存。因此接下来观察系统调用。
 
  strace -p $(pgrep app)
  #strace 结果可以看到openat打开磁盘分区/dev/sdb1,传入参数为O_RDONLY|O_DIRECT
  这就解释了为什么读32MB数据那么慢,直接从磁盘读写肯定远远慢于缓存。找出问题后我们再看案例的源代码发现flags中指定了直接IO标志。删除该选项后重跑,验证性能变化。
 
  内存泄漏,如何定位和处理?
  对应用程序来说,动态内存的分配和回收是核心又复杂的一个逻辑功能模块。管理内存的过程中会发生各种各样的“事故”:
 
  没正确回收分配的内存,导致了泄漏
 
  访问的是已分配内存边界外的地址,导致程序异常退出
 
  内存的分配与回收
 
  虚拟内存分布从低到高分别是只读段,数据段,堆,内存映射段,栈五部分。其中会导致内存泄漏的是:
 
  堆:由应用程序自己来分配和管理,除非程序退出这些堆内存不会被系统自动释放。
 
  内存映射段:包括动态链接库和共享内存,其中共享内存由程序自动分配和管理
 
  内存泄漏的危害比较大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把它们再次分配给其他应用。 内存泄漏不断累积甚至会耗尽系统内存.
 
  如何检测内存泄漏
 
  预先安装systat,docker,bcc:
 
  sudo docker run --name=app -itd feisky/app:mem-leak
  sudo docker logs app
  vmstat 3
  可以看到free在不断下降,buffer和cache基本保持不变。说明系统的内存一致在升高。但并不能说明存在内存泄漏。此时可以通过memleak工具来跟踪系统或进程的内存分配/释放请求:
 
  /usr/share/bcc/tools/memleak -a -p $(pidof app)
  从memleak输出可以看到,应用在不停地分配内存,并且这些分配的地址并没有被回收。通过调用栈看到是fibonacci函数分配的内存没有释放。定位到源码后查看源码来修复增加内存释放函数即可。
 
  为什么系统的Swap变高
  系统内存资源紧张时通过内存回收和OOM杀死进程来解决。其中可回收内存包括:
 
  缓存/缓冲区,属于可回收资源,在文件管理中通常叫做文件页
 
  在应用程序中通过fsync将脏页同步到磁盘
 
  交给系统,内核线程pdflush负责这些脏页的刷新
 
  被应用程序修改过暂时没写入磁盘的数据(脏页),要先写入磁盘然后才能内存释放
 
  内存映射获取的文件映射页,也可以被释放掉,下次访问时从文件重新读取
 
  对于程序自动分配的堆内存,也就是我们在内存管理中的匿名页,虽然这些内存不能直接释放,但是Linux提供了Swap机制将不常访问的内存写入到磁盘来释放内存,再次访问时从磁盘读取到内存即可。
 
  Swap原理
 
  Swap本质就是把一块磁盘空间或者一个本地文件当作内存来使用,包括换入和换出两个过程:
 
  换出:将进程暂时不用的内存数据存储到磁盘中,并释放这些内存
 
  换入:进程再次访问内存时,将它们从磁盘读到内存中
 
  Linux如何衡量内存资源是否紧张?
 
  直接内存回收 新的大块内存分配请求,但剩余内存不足。此时系统会回收一部分内存;
 
  kswapd0 内核线程定期回收内存。为了衡量内存使用情况,定义了pages_min,pages_low,pages_high三个阈值,并根据其来进行内存的回收操作。
 
  剩余内存 < pages_min,进程可用内存耗尽了,只有内核才可以分配内存
 
  pages_min < 剩余内存 < pages_low,内存压力较大,kswapd0执行内存回收,直到剩余内存 > pages_high
 
  pages_low < 剩余内存 < pages_high,内存有一定压力,但可以满足新内存请求
 
  剩余内存 > pages_high,说明剩余内存较多,无内存压力
 
  pages_low = pages_min 5 / 4 pages_high = pages_min 3 / 2
 
  NUMA 与 SWAP
 
  很多情况下系统剩余内存较多,但SWAP依旧升高,这是由于处理器的NUMA架构。
 
  在NUMA架构下多个处理器划分到不同的Node,每个Node都拥有自己的本地内存空间。在分析内存的使用时应该针对每个Node单独分析:
 
  numactl --hardware #查看处理器在Node的分布情况,以及每个Node的内存使用情况
  内存三个阈值可以通过/proc/zoneinfo来查看,该文件中还包括活跃和非活跃的匿名页/文件页数。
 
  当某个Node内存不足时,系统可以从其他Node寻找空闲资源,也可以从本地内存中回收内存。通过/proc/sys/vm/zone_raclaim_mode来调整。
 
  0表示既可以从其他Node寻找空闲资源,也可以从本地回收内存

(编辑:莱芜站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读