腾讯面试:linux内存性能优化总结
off999 2025-03-10 19:21 27 浏览 0 评论
【1】内存映射
Linux 内核给每个进程都提供了一个独立且连续的虚拟地址空间,以便进程可以方便地访问虚拟内存;虚拟地址空间的内部又被分为内核空间和用户空间两部分,不同字长的处理器,地址空间的范围也不同;图示为 32 位和 64 位系统的虚拟地址空间;
内存映射是将虚拟内存地址映射到物理内存地址,内核为每个进程都维护了一张页表,记录虚拟地址与物理地址的映射关系;
页表存储在 CPU 的内存管理单元 MMU 中,正常情况下,处理器就可以直接通过硬件,找出要访问的内存;当进程访问的虚拟地址在页表中不存在时,系统会产生一个缺页异常,进入内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行;
TLB (Translation Lookaside Buffer,转译后备缓冲器) 是 MMU 中页表的高速缓存,由于进程的虚拟地址空间是独立的,而 TLB 的访问速度又比 MMU 快得多,因此通过减少进程的上下文切换,减少 TLB 的刷新次数,可以提高 TLB 缓存的使用率,进而提高 CPU 的内存访问性能;
MMU 规定了内存映射的最小单位,即页,通常是 4 KB 大小,每一次内存映射,都需要关联 4KB 或者 4KB 整数倍的内存空间;
多级页表就是把内存分成区块来管理,将原来的映射关系改成区块索引和区块内的偏移;由于虚拟内存空间通常只用了很少一部分,多级页表就只保存这些使用中的区块,从而大大地减少页表的项数,Linux 四级页表管理内存页图示
大页,即比普通页更大的内存块,常见的大小有 2MB 和 1GB;
推荐视频:
90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc原理
学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂
【2】虚拟内存空间分布
32 位系统中用户空间的分段示意图
- 1. 只读段,包括代码和常量等
- 2. 数据段,包括全局变量等
- 3. 堆,包括动态分配的内存,从低地址开始向上增长
- 4. 文件映射段,包括动态库、共享内存等,从高地址开始向下增长
- 5. 栈,包括局部变量和函数调用的上下文等,栈的大小是固定的,一般是 8 MB
【3】内存的分配与回收
内存分配
小块内存 (小于 128K),使用 brk() 来分配,即通过移动堆顶的位置来分配内存,这些内存释放后并不会立刻归还系统,而是被缓存起来,以便重复使用;
- brk() 方式分配内存,可以减少缺页异常的发生,提高内存访问效率;由于这些内存没有归还系统,在内存工作繁忙时,频繁的内存分配和释放会造成内存碎片;
大块内存 (大于 128K),使用内存映射 mmap() 来分配,即在文件映射段找一块空闲内存分配出去
- mmap() 方式分配内存,会在释放时直接归还系统,因此 mmap 会发生缺页异常;在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大;
内存回收
回收缓存,如使用 LRU (Least Recently Used) 算法,回收最近使用最少的内存页面;
回收不常访问的内存,把不常用的内存通过交换分区直接写到磁盘中;
- 交换分区 (Swap) 即把一块磁盘空间当成内存来用;把进程暂时不用的数据存储到磁盘中(换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中 (换入)
杀死进程,内存紧张时系统还会通过 OOM (Out of Memory),直接杀掉占用大量内存的进程;
内核的一种保护机制,监控进程的内存使用情况,并且使用 oom_score 为每个进程的内存使用情况进行评分;
- 一个进程消耗的内存越大,oom_score 就越大;
- 一个进程运行占用的 CPU 越多,oom_score 就越小;
- 管理员可以通过 /proc 文件系统,手动设置进程的 oom_adj,从而调整进程的 oom_score;
oom_adj 的范围是 [-17, 15],数值越大,表示进程越容易被 OOM 杀死;数值越小,表示进程越不容易被 OOM 杀死,其中 -17 表示禁止 OOM;
【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,内核,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
【4】buffer/cache
Buffer 是内核缓冲区用到的内存,对应的是 /proc/meminfo 中的 Buffers 值;
Cache 是内核页缓存和 Slab 用到的内存,对应的是 /proc/meminfo 中的 Cached 与 SReclaimable 之和;
- Buffers 是对原始磁盘块的临时存储,即用来缓存磁盘的数据,通常不会特别大 (20MB 左右);从而内核可以把分散的写集中起来,统一优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等;
Buffer 既可以用作 “将要写入磁盘数据的缓存”,也可以用作 “从磁盘读取数据的缓存”
- Cached 是从磁盘读取文件的页缓存,即用来缓存从文件读取的数据;从而,下次访问这些文件数据时,就可以直接从内存中快速获取,而不需要再次访问缓慢的磁盘;
实际上,Cache 也会缓存写文件时的数据
Cache 既可以用作 “从文件读取数据的页缓存”,也可以用作 “写文件的页缓存”
- SReclaimable 是 Slab 的一部分,Slab 包括两部分,其中的可回收部分,用 SReclaimable 记录;而不可回收部分,用 SUnreclaim 记录;
【5】内存泄漏
栈内存由系统自动分配和管理,一旦程序运行超出了这个局部变量的作用域,栈内存就会被系统自动回收,不会产生内存泄漏的问题;
堆内存由应用程序分配和管理,除非程序退出,这些堆内存并不会被系统自动释放,而是需要应用程序明确调用库函数 free() 释放,如果应用程序没有正确释放堆内存,就会造成内存泄漏;
只读段,包括程序的代码和常量,由于是只读的,不会再去分配新的内存,不会产生内存泄漏;
数据段,包括全局变量和静态变量,这些变量在定义时就已经确定了大小,不会产生内存泄漏;
内存映射段,包括动态链接库和共享内存,其中共享内存由程序动态分配和管理,若程序在分配后忘了回收,就会导致泄漏问题;
【6】Swap 知识点
Swap 即把一块磁盘空间或者一个本地文件当成内存来使用,包括换出和换入两个过程;
- 换出,即把进程暂时不用的内存数据存储到磁盘中,并释放这些数据占用的内存;
- 换入,即在进程再次访问这些内存的时候,把它们从磁盘读到内存中来;
NUMA 与 Swap
NUMA (Non-Uniform Memory Access) 架构,在 NUMA 架构下,多个处理器被划分到不同 Node 上,且每个 Node 都拥有自己的本地内存空间,而同一个 Node 内部的内存空间,又可以进一步分为不同的内存域(Zone);
某个 Node 内存不足时,系统可以从其他 Node 寻找空闲内存,也可以从本地内存中回收内存;可以通过
/proc/sys/vm/zone_reclaim_mode 来选择模式,支持以下几个选项;
- 默认的 0,表示既可以从其他 Node 寻找空闲内存,也可以从本地回收内存;
- 1、2、4 都表示只回收本地内存,2 表示可以回写脏数据回收内存,4 表示可以用 Swap 方式回收内存;
swappiness
- 对文件页的回收,即直接回收缓存,或者把脏页写回磁盘后再回收;
- 对匿名页的回收,即通过 Swap 机制,把它们写入磁盘后再释放内存;
Linux 提供了 /proc/sys/vm/swappiness 选项,用来调整使用 Swap 的积极程度,swappiness 的范围是 0-100,数值越大,越积极使用 Swap,即更倾向于回收匿名页;数值越小,越消极使用 Swap,即更倾向于回收文件页;
降低 Swap 的使用,可以提高系统的整体性能
1. 禁止 Swap,现在服务器的内存足够大,所以除非有必要,禁用 Swap 即可,随着云计算的普及,大部分云平台中的虚拟机都默认禁止 Swap;
2. 若实在需要用到 Swap,可以尝试降低 swappiness 的值,减少内存回收时 Swap 的使用倾向;
3. 响应延迟敏感的应用,如果它们可能在开启 Swap 的服务器中运行,你还可以用库函数 mlock() 或者 mlockall() 锁定内存,阻止它们的内存换出;
【7】Linux 回收内存的时机
在内存资源紧张时,Linux 通过直接内存回收和定期扫描的方式,释放文件页和匿名页,以便把内存分配给更需要的进程使用;
直接内存回收,存在新的大块内存分配请求,但是剩余内存不足,此时系统就需要回收一部分内存,进而尽可能地满足新内存请求;
kswapd0 内核线程,用于定期回收内存,kswapd0 定义了三个内存阈值,分别是页最小阈值 (pages_min)、页低阈值(pages_low) 和页高阈值(pages_high);pages_free 表示剩余内存;
- 剩余内存小于页最小阈值,说明进程可用内存都耗尽了,只有内核才可以分配内存;
- 剩余内存落在页最小阈值和页低阈值中间,说明内存压力比较大,剩余内存不多了;这时 kswapd0 会执行内存回收,直到剩余内存大于高阈值为止;
- 剩余内存落在页低阈值和页高阈值中间,说明内存有一定压力,但还可以满足新内存请求;
- 剩余内存大于页高阈值,说明剩余内存比较多,没有内存压力;
页低阈值可以通过内核选项
/proc/sys/vm/min_free_kbytes 来间接设置,min_free_kbytes 设置了页最小阈值,而其他两个阈值,都是根据页最小阈值计算生成,如下
pages_low = pages_min * 5 / 4
pages_high = pages_min * 3 / 2性能指标与工具总结
实战记录
【1】free 命令
- total 总内存大小;
- used 已使用内存的大小,包含了共享内存;
- free 未使用内存的大小;
- shared 共享内存的大小;
- buff/cache 缓存和缓冲区的大小;
- available 新进程可用内存的大小;
【2】top 命令
VIRT 是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内;
RES 是常驻内存的大小,即进程实际使用的物理内存大小,但不包括 Swap 和共享内存;
SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等;
%MEM 是进程使用物理内存占系统总内存的百分比;
注意
- 1. 虚拟内存通常并不会全部分配物理内存;
- 2. 共享内存 SHR 并不一定是共享的,如程序的代码段、非共享的动态链接库,也都算在 SHR 里;
【3】磁盘和文件写案例
【3.1】案例一,写文件
测试命令
$ dd if=/dev/urandom of=/tmp/file bs=1M count=500
监控命令
vmstat 2- 1. 在 Cache 刚开始增长时,块设备 I/O 很少,而过一段时间后,才会出现大量的块设备写;
- 2. 当 dd 命令结束后,Cache 不再增长,但块设备写还会持续一段时间,并且多次 I/O 写的结果加起来是 dd 要写的 500M 的数据;
【3.2】案例二,写磁盘
测试命令
# 运行dd命令向磁盘分区/dev/sdb1写入2G数据
$ dd if=/dev/urandom of=/dev/sdb1 bs=1M count=2048
监控命令
vmstat 2procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 7584780 153592 97436 0 0 684 0 31 423 1 48 50 2 0
1 0 0 7418580 315384 101668 0 0 0 0 32 144 0 50 50 0 0
1 0 0 7253664 475844 106208 0 0 0 0 20 137 0 50 50 0 0
1 0 0 7093352 631800 110520 0 0 0 0 23 223 0 50 50 0 0
1 1 0 6930056 790520 114980 0 0 0 12804 23 168 0 50 42 9 0
1 0 0 6757204 949240 119396 0 0 0 183804 24 191 0 53 26 21 0
1 1 0 6591516 1107960 123840 0 0 0 77316 22 232 0 52 16 33 0- 1. 写磁盘时 (即 bo 大于 0 时),Buffer 和 Cache 都在增长,但显然 Buffer 的增长快得多;
【4】磁盘和文件读案例
【4.1】案例一、读文件
测试命令
# 运行dd命令读取文件数据
$ dd if=/tmp/file of=/dev/null
监控命令
vmstat 2procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 1 0 7724164 2380 110844 0 0 16576 0 62 360 2 2 76 21 0
0 1 0 7691544 2380 143472 0 0 32640 0 46 439 1 3 50 46 0
0 1 0 7658736 2380 176204 0 0 32640 0 54 407 1 4 50 46 0
0 1 0 7626052 2380 208908 0 0 32640 40 44 422 2 2 50 46 0- 读取文件时 (即 bi 大于 0 时),Buffer 保持不变,而 Cache 则在不停增长;
【4.2】案例二、读磁盘
测试命令
# 运行dd命令读取文件
$ dd if=/dev/sda1 of=/dev/null bs=1M count=1024
监控命令
vmstat 2procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 7225880 2716 608184 0 0 0 0 48 159 0 0 100 0 0
0 1 0 7199420 28644 608228 0 0 25928 0 60 252 0 1 65 35 0
0 1 0 7167092 60900 608312 0 0 32256 0 54 269 0 1 50 49 0
0 1 0 7134416 93572 608376 0 0 32672 0 53 253 0 0 51 49 0
0 1 0 7101484 126320 608480 0 0 32748 0 80 414 0 1 50 49 0- 读磁盘时 (也就是 bi 大于 0 时),Buffer 和 Cache 都在增长,但显然 Buffer 的增长快很多;
附录
【1】文件系统与磁盘的区别
磁盘是一个存储设备(块设备),可以被划分为不同的磁盘分区,而在磁盘或者磁盘分区上,还可以再创建文件系统,并挂载到系统的某个目录中,这样,系统就可以通过这个挂载目录,来读写文件;即磁盘是存储数据的块设备,也是文件系统的载体;文件系统需要通过磁盘,来保证数据的持久化存储;
在读写普通文件时,I/O 请求会首先经过文件系统,然后由文件系统负责,来与磁盘进行交互;在读写块设备文件时,会跳过文件系统,直接与磁盘交互,也就是所谓的 “裸 I/O”;
【2】统计所有进程的物理内存使用量
每个进程的 PSS ,是指把共享内存平分到各个进程后,再加上进程本身的非共享内存大小的和;
# 使用grep查找Pss指标后,再用awk计算累加值
$ grep Pss /proc/[1-9]*/smaps | awk '{total+=$2}; END {printf "%d kB\n", total }'
391266 kB相关推荐
- h3c路由器手机登录入口(h3c路由器登录界面手机)
-
首先就是把华三路由器正确安装,然后手机连接路由器发射出来的WiFi信号。然后点击手机中的浏览器并深入华三路由器的登录地址 moshujia.com或者192.168.124.1,就可以登...
- u盘坏了数据怎么导出来(u盘坏了里面的数据怎么办)
-
方法一、借助数据恢复软件u盘只要不是物理性故障且数据未覆盖的情况下,可借助u盘数据恢复软件来提取打不开的u盘数据。具体操作流程如下:在电脑上插入需要恢复数据的u盘,然后运行u盘数据恢复软件—以云骑士数...
- win10家庭版原装下载(win10家庭版安装包下载)
-
有以下几种原因:第一是因为专业版功能较为齐全,但一般的使用者并不太需要。第二是由于功能齐全,它所占的体积也比较大,进而对电脑的运行速率有一定的影响。第三是Wln10各种版本都还是需要花钱购买的,而专业...
- win7装xp系统怎么安装(win7如何安装xp系统)
-
设置U盘为第一启动项并进入PE系统。开机按F2进入BOIS,在BOOT选项中将U盘设为第一启动盘,通过按F6(有的是Shift+)调整顺序。(或开机按ESC选择启动盘,即你的U盘)。按F10保存...
- windows 98是什么操作系统(windows98属于什么)
-
Windows98是微软公司发行于1998年6月25日的混合16位/32位的Windows操作系统,其版本号为4.1,开发代号为Memphis。肯定有的。Windows95操作系统刚发布的时候就...
- 下载mp3免费的网站(免费下载mp3哪些网站)
-
有免费下载mp3的网站。除了知名的几个音乐平台外,还有以下三款支持免费MP3无损音乐下载网站,可以将喜欢的歌曲下载到U盘。说明书里有呀91flac音乐网,试试这个,绝对好使,但是不要在酷狗上面说网页上...
- win10更新卸载不了怎么办(win10更新后卸载更新失败)
-
右键桌面上“此电脑”—“管理”,或者按组合键“Windows+X”—计算机管理—服务和应用程序—服务,找到Windowsupdate和BackgroundIntelligentTransfe...
- pc浏览器是什么意思(pc模式的浏览器)
-
则是在电脑上使用的所有的浏览器。可以在电脑上使用的浏览器有非常多,我们现在比较常用的包括UC浏览器,搜狗浏览器,360浏览器等等,这些浏览器都可以在大部分的电脑上正常使用,而且使用起来非常流畅,市场的...
- win10取消电脑开机密码(win10如何取消电脑开机密码取消)
-
取消Windows10开机密码的方法如下:1.在Windows10桌面上,按下WIN+R组合键,打开运行窗口。2.输入"netplwiz"然后按下回车键,这...
- 五笔打字怎么打(曹五笔打字怎么打)
-
操作步骤:1、按住Ctrl+空格键切换到五笔输入法;2、在输入面板上面单击右键选择“软键盘”——特殊符号;3、在打开的软键盘上单击“☆”即可。五笔打字是指采用五笔字型输入法向电脑中输入汉字。这种输入...
- 电脑高手24在线咨询(电脑高手联系方式)
-
现在的电脑一般都不要重启键了。如果死机的话,按住开关键五秒,自动关机。再开机就行。至于他们说的快速关机CTRL+ALT+ENT快速重启CTRL+ALT+HOME是GOHST版安装后自带的快捷键,你的系...
- 你的电脑未正确启动自动修复
-
1、试试“禁止驱动强制签名”能不能进入桌面在“疑难解答”->“高级选项”->“启动模式”中选择“禁止驱动强制签名”,如果这样能正常开启,那么就说明是某个驱动的问题2、把错误驱动删掉如果你安...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
失业程序员复习python笔记——条件与循环
-
系统u盘安装(win11系统u盘安装)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
