关于 Linux 内存回收的几个问题
kswapd 什么时候会被唤醒?
kswapd 是 Linux 内核中的内存管理进程,它负责在内存不足时释放不用的页面并将其交换到磁盘上。 kswapd 会被唤醒的时候有以下几种情况:
1.当内存使用率达到一定阈值时,kswapd 会被唤醒来释放不用的页面。
2.当进程请求内存时,如果内存不够用,kswapd 会被唤醒来释放页面。
3.当系统调用 swapoff()被执行时,kswapd 会被唤醒来释放交换空间。
4.当系统调用 sync()被执行时,kswapd 会被唤醒来将页面写回磁盘。
LRU 链表如何知道 page 的活动频繁程度?
Linux 内核中的 LRU 链表(Least Recently Used)通过跟踪每个页面的使用时间来确定页面的活动频繁程度。
页面的活动频繁程度越高,在 LRU 链表中就会越靠前。当页面被访问时,它会被移动到链表的头部,表示它是最近被使用的页面。而那些长时间未被使用的页面则会被移动到链表的尾部,当系统需要释放内存时,尾部的页面就是首先被释放的页面。
这样的策略可以有效的释放那些长时间未被使用的页面,并保留那些最近被使用的页面,这样可以提高系统的内存使用效率。
页面被访问的时候,会放在 LRU 链表中头部吗?这样还不会有性能问题?
您说得对,当页面被访问时,它会被移动到 LRU 链表的头部。这样做会有一些性能问题,因为在链表中插入和删除操作是很慢的。
为了解决这个问题,Linux 内核采用了一种叫做 Active/Inactive 页面分离的策略。 页面被分为两类:Active 页面和 Inactive 页面。 Active 页面是那些最近被使用过的页面,Inactive 页面是那些长时间未被使用的页面。
每当页面被访问时,它会被移动到 Active 页面的链表头部。如果 Active 页面的链表达到了一定长度,那么链表尾部的页面就会被移动到 Inactive 页面的链表头部。这样就可以避免在 LRU 链表中频繁的插入和删除操作,提高系统的性能。
访问 Active 链表中的页面会改变他在链表中的位置吗?
是的,当一个页面在 Active 链表中被访问时,它会被移动到链表的头部。这是因为 Active 链表中的页面是最近被使用过的页面,所以将它们移动到链表头部可以提高系统的性能。
将页面移动到链表头部并不会影响到页面在内存中的位置,只是影响到页面在 Active 链表中的位置而已。
需要注意的是,如果 Active 链表的长度超过了一定的阈值,那么链表尾部的页面会被移动到 Inactive 链表的头部,那些在 Inactive 链表中的页面就会有可能被释放掉。
kswapd 按照什么原则来换出页面?
kswapd 在换出页面时会采用 Least Recently Used (LRU)原则,即优先换出最近最少使用的页面。
在 Linux 中,每个页面都会被分到 Active 和 Inactive 链表中,kswapd 会优先换出 Inactive 链表中的页面。因为 Inactive 链表中的页面是那些长时间未被使用的页面,所以换出它们可以腾出空间给更加需要的页面。
如果 Inactive 链表中的页面都已经被换出,kswapd 会接着换出 Active 链表中的页面。但是,kswapd 可能会有一些特殊的策略来避免换出某些页面,比如说那些被系统标记为不可换出的页面。
kswapd 按照什么方向来扫描 zone?
kswapd 在扫描 zone 时会按照从前往后的顺序来扫描。
所谓 zone 就是内存管理中的一块连续的物理内存空间,在 Linux 中,zone 被分成了不同的类型,比如 DMA,DMA32,Normal 等。
当 kswapd 启动时,它会从 zone 链表的头部开始扫描,按照顺序扫描每一个 zone。在扫描过程中,kswapd 会优先换出 Inactive 链表中的页面,如果 Inactive 链表中的页面都已经被换出,kswapd 会接着换出 Active 链表中的页面。扫描完一个 zone 之后再扫描下一个 zone,直到所有的 zone 都被扫描完。
这种从前往后扫描的方式可以保证每个 zone 都有机会被扫描并释放不用的页面。
kswapd 以什么标准来退出扫描 LRU?
kswapd 在扫描 LRU 链表时会根据一些标准来决定是否退出扫描。
当页面交换区的使用率降低到一定的阈值时,kswapd 会退出扫描。
当 kswapd 扫描到链表的尾部并没有找到可以换出的页面时,会退出扫描。
当 kswapd 的运行时间超过一定的阈值时,会退出扫描。
当 kswapd 被系统其它进程中断时会退出扫描.
这些标准可以保证 kswapd 在扫描 LRU 链表时不会无限循环下去,并且可以保证系统在需要时可以立即响应。
手持设备例如 Android 系统,没有 swap 分区或者 swap 文件,kswapd 会扫描匿名页面 LRU 吗?
在手持设备上,如 Android 系统,由于空间限制,很多设备没有 swap 分区或者 swap 文件。
在这种情况下,kswapd 仍然会扫描匿名页面的 LRU 链表来释放不用的页面,但是因为没有可用的交换空间,kswapd 不能将页面交换到磁盘上,而是直接将页面释放掉。
另外,在 Android 系统中,由于系统优化的限制,kswapd 并不总是能够运行,它可能会被其它进程杀死或者被系统自动杀死。
当配置 zram 时,情况是怎样?
zram 是 Linux 内核中一种内存压缩技术,它可以将系统中的内存数据进行压缩然后存储在内存中,从而达到节省内存空间的目的。
当配置 zram 时,系统会创建一个或多个虚拟内存设备(zram 设备),每个 zram 设备都会有一个对应的内存块。当应用程序需要使用内存时,它会将数据写入 zram 设备中,zram 设备会将数据进行压缩后再存储在内存中。当应用程序需要读取数据时,zram 设备会将压缩的数据解压缩后返回给应用程序。
这样做可以有效的节省内存空间,提高系统的性能。而且 zram 能够和 kswapd 一起工作,当内存不够用时,kswapd 会将页面交换到 zram 设备中而不是磁盘上。
swappiness 的含义是什么?kswapd 如何计算匿名页面和 page cache 之间的扫描比重?
swappiness 是 Linux 内核中一个参数,它决定了系统在内存不够用时应该将页面交换到磁盘上的比例。值越大,表示系统越容易将页面交换到磁盘上,值越小,表示系统越不容易将页面交换到磁盘上。
默认情况下,swappiness 的值为 60,这意味着在内存不够用时,系统会将 60%的页面交换到磁盘上,40%的页面会被释放掉。
kswapd 会根据 swappiness 的值来计算匿名页面和 page cache 之间的扫描比重。当 swappiness 的值越大时,kswapd 会更多的扫描匿名页面;当 swappiness 的值越小时,kswapd 会更多的扫描 page cache。
这样做可以在保证系统的性能的同时,最大限度的利用系统内存。具体来说,当 swappiness 值较大时,系统会更容易将匿名页面交换到磁盘上以腾出空间给其它进程,保证系统的稳定性。而当 swappiness 值较小时,系统会更加保留匿名页面,保证系统的性能。
当系统中充斥着大量只访问一次的文件访问(use-one streaming IO)时,kswapd 如何来规避这种风暴?
当系统中充斥着大量只访问一次的文件访问时,这会导致系统频繁地进行页面交换,导致系统性能下降。
Kswapd 可以采用一些策略来规避这种风暴,来提高系统性能,具体策略有如下几种:
动态调整 swappiness 的值:当系统中出现大量只访问一次的文件访问时,可以适当降低 swappiness 的值,以减少页面交换的频率。
采用 Cache-Aware 的策略:当系统中出现大量只访问一次的文件访问时,kswapd 会优先将这些文件从内存中清除,以避免系统频繁地进行页面交换。
利用内存管理策略:在 Linux 系统中,可以采用如 ClearPageLRU、ClearPageActive、ClearPageReferenced 等内存管理策略来清除页面,以减少系统中页面交换的次数。
使用其它内存压缩技术(如 zram) 来代替交换到磁盘上,这样可以避免系统频繁地进行页面交换。
利用 IO scheduler 来进行优化,使用如 CFQ, deadline, noop 等不同的 IO scheduler 来优化系统的 IO 性能.
这些方法可以帮助 kswapd 规避大量的只访问一次的文件访问带来的性能问题,并提高系统的性能。
Cache-Aware 是什么?
Cache-Aware 是一种页面交换策略,它会优先将文件页面从缓存中清除,而不是将匿名页面换出。
Cache-Aware 策略的目的是保留热点数据(即经常被访问的数据)在内存中,而将不常用的数据换出。在这种策略下,文件页面(page cache)更容易被换出,而匿名页面更难被换出。这样做可以最大限度地保留热点数据在内存中,提高系统性能。
ClearPageLRU、ClearPageActive、ClearPageReferenced 各自特点是什么?
ClearPageLRU, ClearPageActive, ClearPageReferenced 是 Linux 内核中用来清除页面的内存管理策略.
ClearPageLRU: 优先清除最近最少使用(Least Recently Used, LRU)的页面。这种策略适用于大部分场景,保留了热点数据在内存中,减少页面交换的次数。
ClearPageActive: 优先清除活跃页面。当系统内存不足时,该策略会优先清除最近使用过的页面,以保证系统的稳定性。
ClearPageReferenced: 优先清除最近被引用过的页面。当系统内存不足时,该策略会优先清除最近被使用过的页面,以保证系统的性能。
这些策略的选择取决于系统的具体需求,如系统稳定性,性能或者某些特定场景下的使用。
在回收 page cache 时,对于 dirty 的 page cache, kswapd 会马上回写吗?
在回收 page cache 时,对于 dirty 的 page cache, kswapd 并不会马上回写,而是将它们加入到 writeback 队列中。在 Linux 内核中,有一个内核线程 kupdate,它会定期扫描 writeback 队列,将 dirty 的 page cache 回写到磁盘上。这样做的好处是可以避免频繁的磁盘 IO 操作,提高系统性能。
另外, Linux 内核还有一个叫做 bdflush 的内核线程,它会扫描 writeback 队列,并将需要回写的页面提交给对应的文件系统,进行写入操作。这样可以避免长时间的等待,提高系统的性能。
内核中有哪些页面会被 kswapd 写回交换分区?
在 Linux 内核中,有两种页面会被 kswapd 写回交换分区,分别是匿名页面和文件页面(page cache)。
匿名页面: 即没有与文件系统关联的页面,常被进程的堆栈和堆使用。这些页面在系统内存不足时会被回收,并写回交换分区。
文件页面(page cache): 即与文件系统关联的页面,常用于读取和写入文件。在系统内存不足时,这些页面也会被回收,并写回交换分区。
需要注意的是,在回收 page cache 时,对于 dirty 的 page cache, kswapd 并不会马上回写,而是将它们加入到 writeback 队列中,在内核线程 kupdate 定期进行回写。
文件页面有后备存储器,为什么 page cache 会被写回交换分区?
文件页面确实有后备存储器,也就是文件系统上的文件。但是将文件页面写回交换分区的原因是为了更有效地管理系统内存。
当系统内存不足时,kswapd 需要回收一些页面以释放空间给其他进程使用。如果只回收匿名页面,那么很有可能会导致系统中有些热点数据被回收,进而影响系统性能。而将文件页面写回交换分区可以避免这个问题,因为文件页面有后备存储器,所以即使被回收,这些数据也可以从文件系统中恢复。
另外,在实际使用中,写回交换分区的文件页面并不会被永久性地删除,而是等待下次访问时重新载入。这是因为在 Linux 内核中,还有一种页面状态叫做 swap cache,它会记录被写回交换分区的文件页面的位置信息。在下次访问时,如果文件页面在 swap cache 中,则会直接从交换分区中恢复,而不需要重新从文件系统中读取。这样做可以减少磁盘 IO 次数,提高系统性能。
因此,文件页面写回交换分区的目的是为了更有效地管理系统内存,避免系统中有些热点数据被回收,并且还可以提高系统性能。
直接从交换分区中恢复,而不需要重新从文件系统中读取为什么会减少 IO 次数?
直接从交换分区中恢复文件页面,而不需要重新从文件系统中读取会减少 IO 次数是因为交换分区和文件系统的 IO 读写速率不同.
交换分区是在磁盘上的一个特殊分区,它专门用来存储被换出来的页面。交换分区的读写速率比文件系统快得多。因此,直接从交换分区中恢复文件页面,而不需要重新从文件系统中读取可以减少 IO 次数,提高系统性能。
如果使用 swap 文件,这种优势还存在吗?
如果使用 swap 文件,这种优势依然存在。swap 文件也是在磁盘上的一个特殊文件,和交换分区类似,专门用来存储被换出来的页面。
当使用交换分区时,页面的读取和存储都在交换分区上完成,而在使用 swap 文件时,页面的读取和存储都在 swap 文件上完成。两者在实现上有些区别,但是在读写性能上还是有相似之处。
因此,使用 swap 文件和交换分区都可以减少 IO 次数,提高系统性能。但是, 有些系统使用 swap 文件可能会有一些性能损失,因为文件系统的读写速率一般比交换分区慢。
版权声明: 本文为 InfoQ 作者【SkyFire】的原创文章。
原文链接:【http://xie.infoq.cn/article/d5143b52ab4233dea90c981ff】。文章转载请联系作者。
评论