本文共 5596 字,大约阅读时间需要 18 分钟。
【Android Linux内存及性能优化】六 系统内存的优化
本文接着
《》 《》 《》 《》 《》一、内存篇
1.1 系统当前可用内存
1.2 进程的内存使用
1.3 进程内存优化
1.4 系统内存优化
1.4.1 守护进程的内存使用
在设备开机之后,你会发现已经有很多进程在运行,这些进程将一直存活,直到设备关机,我们把这类进程称为守护进程。
守护进程对系弘的内存使用影响巨大:
(1)由于守护进程一直存活,所以其所占用的内存将不会被释放。 (2)一个进程即使什么事情都不做,它引用了一些动态库,也会占用大量的物理内存。 (3)由于守护进程的生存周期很长,其哪怕只有一点内存泄漏,也会导致系统的内存耗尽。进程一旦退出,其所占用的内存存将被 Linux内核收回,所以对那些生存周期很短的进程来讲,即使有些内存泄漏,其对系统内存使用影响并不大。
因些应该尽量减少系统中守护进程的数量,对于那些提供服务的守护进程来讲,尽量做到在进程需要的时候来启动,在不需要的时候退出。
下面就来详细描述如何减少守护进程的数量。
首先为什么会存在守护进程? 原因主要两点:
-
系统需要守护进程来侦听某些事件。
在设计守护进程时,开发人员往往没有区分其中的常驻部分和非常驻部分, 在侦听到一个事件后,直接启动相应的业务逻辑,而在这些业务逻辑执行完之后,并不会将本已无用的业务逻辑部分释放。 这样就造成了侦听部分与业务逻辑部分混在一起都作为守护进程, 而使得守护进程部分逻辑比较复杂,一方面占用了大量的内存,另一方面也增大了内存泄漏的几率。因些建议将守护进程明确分为常驻部分和非常驻部分,分别让不同的进程来完成,将常驻内存部分的逻辑尽量简化。
更进一步,可以考虑将几个守护进程的侦听事件部分合并到一个守护进程,当负责侦听的守护进程收到消息后,再去启动相应的业务逻辑。
在这一方面,inetd 是最好的例子,其常驻内部部分可以侦听 telnet、ftp等端口,在有用户该问后,又会创建相应的进程为用户提供服务。
- 有些进程提供服务的响应时间达不到要求,开发人员便将其放在设备开机时启动,所以转变为了守护进程。 首先需要考虑加快进程的启动速度,从而使服务进程达到按需启动的需求,这个后续分析。 除了优化加载动态库、使用 Prelink 等方法外,还可以采用一些进程调度的方法来减少守护进程对于内存的影响。
1.4.2 tmpfs 分区
在LInux 中,为了加快对文件的读写,基于内存建立了一个文件系统,称为 ramdisk 或者 tmpfs。
对于该文件系统的访问,都将直接操作物理内存,因此而要比访问Flash 快得多。在做系统内存优化时,不要忘掉这块内存。
ciellee@sh:~/work/code/simcom_220c_sop_1028_0426$ df -HFilesystem Size Used Avail Use% Mounted onudev 8.4G 0 8.4G 0% /devtmpfs 1.7G 11M 1.7G 1% /run/dev/sda8 706G 520G 150G 78% /tmpfs 8.4G 180M 8.2G 3% /dev/shmtmpfs 5.3M 4.1k 5.3M 1% /run/locktmpfs 8.4G 0 8.4G 0% /sys/fs/cgroup/dev/loop0 99M 99M 0 100% /snap/core/9066
可以看出,tmpfs 文件分区为8.4G。
在对这个文件分区进行读写时,要时刻提醒自已,它是占用物理内存的,在该分区上的文件,不需要的时候应及时删除。
1.4.3 Cache 缓存 和 Buffer 缓冲
前面讲到, 系统中空闲内存 = MemFree + Buffers + Cached。
下面我们来看下 Cache 和 Buffer 分别是什么。1.4.3.1 Cache 缓存
Cache 也称缓存,是把从Flash 中读取的数据保存起来,
若再次读取该块数据时,就不需要去读取Flash 了,直接从缓存中读取,从而提高读取文件的速度。Cache 缓存的数据会根据读取频率进行组织,把最频繁读取的内容 放在最容易找到的位置,把不再读的内容不断往后排,直至从中删掉。
在程序执行过程中,发现某些指令不在内存中,便会产生 page fault,而将代码段的数据载入到物理内存。当进程退出后,代码段所占用的内存不会完全丢弃,而是作为Cache 缓存在Linux 系统中。当进程运行时,Cache 的代码指令越多,代码段产生 page fault 的几率越小,程序的执行速度也越快,这便是Cache 存在的理由。
1.4.3.2 Buffer 缓冲
Buffer 也称缓冲,是根据Flash 读写设计的,把分散的写操作集中进行,减小Flash 写的次数,从而提高系统性能。
Cache 和 Buffer 的区别,简单来说,两者都是RAM 中的数据,
Buffer 是缓冲即将写入磁盘的数据, 而 Cache 是缓存从磁盘中读取出来的数据。在系统内存不足时,Linux 内核会将一部分 Cache 和 Buffer 释放,供进程使用,因此Cache 和Buffer 对于进程的内存使用并没有影响。
可以通过 cat /proc/meminfo 来了解系统中 Cache 和Buffer 的大小:
ciellee@sh:~/work/code/simcom_220c_sop_1028_0426$ cat /proc/meminfo MemTotal: 16281312 kBMemFree: 178828 kBMemAvailable: 13359384 kBBuffers: 426416 kBCached: 13052476 kBSwapCached: 0 kBActive: 2841180 kBInactive: 12108016 kB
1.4.3.3 内存回收
在 LInux 中,有一个内核进程 kswapd ,其专门负责回收内存。
在 kswapd 中,有2 个阈值: pages_high 和 pages_low ,
当空闲内存页的数量低于 pages_low 的时候,kswapd 进程就会扫描内存并且每次释放出 32 个 free pages,直到 free page 的数量到达 pages_high。(1)kswapd 回收内存有如下原则:
-
如果物理页面不量 dirty page,就将物理页面回收。
进程中如下内存可能是非 dirty page页面: (1)代码段:其权限是只读属性,不可能被改写,所以其所占的物理内存,都不是dirty page。 (2)数据段:其权限是可读、可写,所以其所占的物理内存可能是 dirty page,也可能不是。 (3)堆段:其权限是可读、可写,空容全是通过程序改写的,所以其所占用的物理内存,全部是 dirty page。 (4)栈段 和 堆段 相同,其所占的物理内存,全部是 dirty page。 (5)共享内存,其所占的物理内存,全部是 dirty page。综上: 这条规则主要面向的是进程的代码段 和 未修改的数据段。
如果你做过长时间的系统进程使用分析,就会发现,在进程跑了一段时间后,其代码所占的物理内存减少了,这就是代码段内存回收的结果。 -
如果物理页面已经修改 并且 可以备份回文件系统,就调用 pdflush 将内存中的内容 和文件系统进行同步。同步完成后,就可以将内存释放。
比如,当一个文件在内存中进行修改,pdflush 负责将其写回磁盘,其主要针对的是下 Buffers。 -
如果物理页面已经修改但是没有任何磁盘的备份,就将其写入 swap 分区。
实际上大部分嵌入式设备很少有交换分区,因此这条规则根本不起作用。
kswapd 在回收内存过程中还有两个重要的方法:
一是 LMR (Low on memory reclaiming),另一个是 OMK(Out of Memory Killer)。当分配内存失败的时候,LMR将会起作用,失败的原因是 kswapd 不能提供足够的空闲内存,这个时候LMR 会每次释放1024 个垃圾页直到内存分配成功。
当LMR 不能快速释放内存的时候,OMK 就开始起作用,OMK 会采用一个选择算法来决定杀死某些进程,选定进程后,就会发送信号 SIGKILL,这就会使内存立即被释放。(2)OMK 选择进程的标准如下:
- 进程占用大量的内存。
- 进程只会损失少量工作。
- 进程具有低的静态优先级。
- 进程不属于 root 用户。
1.4.3.4 /proc/sys/vm/优化
可以通过修改 /proc/sys/vm 下面的文件,设置一些参数,来影响 LInux内核的一些内存操作行为。
修改 /proc/ 下文件的方法:
-
该文件表示是否打开 Block Debug 模式,用于记录所有的读写及 Dirty Block写回动作。 缺省设置 :0,禁用 Block Debug。# echo 1 > /proc/sys/vm/block_dump
-
该文件表示脏数据到达系统整体内存的百分比,此时触发 pdflush 进程把脏数据写回磁盘。 缺省设置:10, 10%# echo 10 > /proc/sys/vm/dirty_background_ratio
-
该文件表示如果脏数据在内存中驻留时间超过该值,pdflush 进程在下一次将把这些数据写回磁盘。 缺省设置:3000, (1/100)s# echo 3000 > /proc/sys/vm/dirty_expire_centisece
-
该文件表示如果进程产生的脏数据到达系统整体内存的百分比,此时进程自行把脏数据写回磁盘。 缺省设置:40, 40%# echo 40 > /proc/sys/vm/dirty_ratio
-
该文件表示pdflush 进程周期间隔多久把脏数据写回磁盘。 缺省设置:500, (1/100)s# echo 500 > /proc/sys/vm/dirty_writeback_centisecs
-
该文件表示内核回收用于directory 和 inode cache 内存的倾向, 缺省 100 表示内核将根据 pagecache 和 swapcache ,把 directory 和 inode cache 保持在一个合理的百分比; 降低该值于 100,将导致内核倾向于保留 directory 和 inode cache 。 增加该值超过 100 ,将导致内核倾向于回收 directory 和 inode cache 。 缺省设置:100# echo 100 > /proc/sys/vm/vfs_cache_pressure
-
该文件表示强制 Linux VM 最低保留多少空闲内存(KB),缺省值:724# echo 724 > /proc/sys/vm/min_free_kbytes
-
该文件表示当前正在运行的 pdflush 进程数量,在I/O 负载高的情况下,内核会自动增加更多的pdflush 进程,缺省值:2(只读)# cat /proc/sys/vm/nr_pdflush_threads
-
该文件指定了内核针对内存分配的策略,其值可以是:0、1、2,缺省值:0 0:表示内核将检查是否有足够的可用内存供应进使用,如果有足够的可用内存,内存申请允许,否则内存申请失败,并把错误返回给应用进程。 1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何。 2:表示内核允许分配超进所有物理内存和交换空间总和的内存。# echo 0 > /proc/sys/vm/overcommit_memory
-
该文件表示,如果 overcommit_memory = 2 ,可以过载内存的百分比,通过以下公式来计算系统整估可用内存: 系统可分配内存 = 交换空间 + 物理内存 × overcommit_ratio / 100。 缺省设置:50%# echo 50 > /proc/sys/vm/overcommit_ratio
-
该文件表示在写一次到swap 区的时候写入的页面数量,0: 表示1页, 1:表示2页,2表示4页, 缺省3:2^3=8页。# echo 3 > /proc/sys/vm/page-cluster
-
该文件表示,系统进行交换行为的程序,数值(0~100)越高,越可能发生磁盘交换,缺省60# echo 60 > /proc/sys/vm/swapiness
-
该文件表示是否使用最新的32位共享内存 mmap() 系统调用,Linux 支持的共享内存分配方式包括mmap(), Posix, System VIPC,缺省 0 0:表示使用最新的32位 mmap() 系统调用 1:表示使用 2.4 内核提供的系统调用# echo 0 > /proc/sys/vm/legacy_va_layout
-
该文件表示系统保留的 hugetlb 页数。# cat /proc/sys/vm/nr_hugepages
转载地址:https://ciellee.blog.csdn.net/article/details/106357011 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!