AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 533739
Accepted
sourcejedi
sourcejedi
Asked: 2019-08-04 11:22:14 +0800 CST2019-08-04 11:22:14 +0800 CST 2019-08-04 11:22:14 +0800 CST

Linux 是否执行“机会交换”,还是一个神话?

  • 772

假设一个程序请求一些内存,但没有足够的可用内存。Linux 有几种不同的响应方式。一种反应是选择其他一些最近没有被访问过的使用过的内存,并将这个不活动的内存移动到交换。

但是,我看到许多超出此范围的文章和评论。他们说即使有大量空闲内存,Linux 有时也会决定将非活动内存写入交换。提前写入交换意味着当我们最终要使用这块内存时,我们不必等待磁盘写入。他们说这是优化性能的深思熟虑的策略。

他们是对的吗?或者这是一个神话?引用您的来源。

请使用以下定义来理解这个问题:

  • 交换
  • free memory - free命令显示的“空闲”内存。这是MemFree来自 的值/proc/meminfo。 /proc/meminfo是内核提供的虚拟文本文件。请参阅proc(5)或RHEL 文档。
  • 即使有大量空闲内存——为了论证的目的,假设有超过 10% 的空闲内存。

参考

以下是一些搜索词:linux“机会交换”或(交换“当系统无事可做时”或“当它无事可做时”或“当系统空闲时”或“在空闲时间”)

在 Google 的第二高结果中,StackExchange 用户询问“为什么在 RAM 中有足够多的可用空间时使用交换?”,并复制free显示大约 20% 可用内存的命令结果。在回答这个具体问题时,我看到这个答案被高度评价:

Linux 在 RAM 被填满之前开始交换。这样做是为了提高性能和响应能力:

  • 性能提高了,因为有时 RAM 更适合用于磁盘缓存而不是存储程序内存。所以最好换掉一段时间不活动的程序,而将常用文件保存在缓存中。

  • 通过在系统空闲时换出页面来提高响应能力,而不是在内存已满并且某些程序正在运行并请求更多 RAM 来完成任务时。

当然,交换确实会减慢系统速度——但交换的替代方法不是不交换,而是拥有更多的 RAM 或使用更少的 RAM。

Google 上的第一个结果已被标记为与上述问题的重复 :-)。MemFree在这种情况下,提问者从 16GB 中复制了显示 7GB 的详细信息。这个问题有一个自己被接受和赞成的答案:

仅当没有空闲内存时才进行交换,只有设置swappiness为 0 时才会发生这种情况。否则,在空闲时间,内核将交换内存。在这样做时,数据不会从内存中删除,而是在交换分区中制作一个副本。

这意味着,如果出现内存耗尽的情况,它不必当场写入磁盘。在这种情况下,内核可以只覆盖已经交换的内存页面,因为它知道它有一份数据副本。

该swappiness参数基本上只是控制它执行此操作的程度。

另一个引用没有明确声称交换的数据也保留在内存中。但是,如果您在有 20% 可用内存的情况下进行交换,那么您似乎更喜欢这种方法,并且这样做的原因是为了提高性能。

据我所知,Linux 确实支持在主内存和交换空间中保留相同数据的副本。

我还注意到“机会交换”发生在“空闲时间”的普遍说法。我知道它应该有助于让我放心,这个功能通常对性能有好处。我没有在上面的定义中包含这个,因为我认为它已经有足够的细节来提出一个很好的明确问题。我不想让这变得比它需要的更复杂。

原始动机

当我有千兆字节的可用内存时,顶部显示“swout”(交换)。为什么?

有一些这样的报告,当有足够的可用内存时,Linux 会写入交换。“机会性交换”可以解释这些报告。同时,至少提出了一个替代原因。作为查看可能原因的第一步:Linux 是否曾经执行过上述定义的“机会交换”?

在我报告的示例中,问题现已得到解答。原因不是机会主义的交换。

linux memory
  • 2 2 个回答
  • 2722 Views

2 个回答

  • Voted
  1. Best Answer
    sourcejedi
    2019-08-04T11:28:17+08:002019-08-04T11:28:17+08:00

    Linux 不执行此问题中定义的“机会交换”。


    以下主要参考文献根本没有提到这个概念:

    1. 了解 Linux 虚拟内存管理器。梅尔·戈尔曼 (Mel Gorman) 的在线书籍。写于 2003 年,就在 Linux 2.6.0 发布之前。
    2. 文档/管理员指南/sysctl/vm.rst。这是 Linux 虚拟内存管理可调设置的主要文档。

    进一步来说:

    10.6 页面输出守护进程(kswapd)

    历史kswapd上每 10 秒唤醒一次,但现在它仅在达到区域中的 pages_low 空闲页面数时由物理页面分配器唤醒。[...] 在极大的内存压力下,进程将kswapd同步完成工作。[...]kswapd一直释放页面,直到达到 pages_high 水印。

    基于上述,当空闲页面的数量高于“高水位线”时,我们不会期望任何交换。

    其次,这告诉我们这样做的目的kswapd是为了让更多的空闲页面。

    当kswapd写入一个内存页进行交换时,它会立即释放内存页。 kswapd 不会在内存中保留交换页面的副本。

    Linux 2.6 使用“ rmap ”来释放页面。在 Linux 2.4 中,情况更加复杂。当一个页面被多个进程共享时,kswapd 无法立即释放它。这是古老的历史。所有链接的帖子都是关于 Linux 2.6 或更高版本的。

    交换性

    此控件用于定义内核交换内存页面的积极程度。较高的值会增加积极性,较低的值会减少交换量。值 0 指示内核在空闲和文件支持的页面数量小于区域中的高水位线之前不启动交换。

    此引用描述了一种特殊情况:如果您将swappiness值配置为0. 在这种情况下,我们不应该期待任何交换,直到缓存页面的数量下降到高水位线。换句话说,内核会在开始交换之前尝试丢弃几乎所有的文件缓存。(这可能会导致速度大幅下降。您需要有一些文件缓存!文件缓存用于保存所有正在运行的程序的代码 :-)

    水印是什么?

    上面的引用提出了一个问题:我的系统上的“水印”内存预留有多大?答:在“小型”系统上,默认区域水印可能高达内存的 3%。这是由于“min”水印的计算。在较大的系统上,水印的比例较小,接近内存的 0.3%。

    因此,如果问题是关于一个具有超过 10% 可用内存的系统,那么这个水印逻辑的确切细节并不重要。

    每个单独“区域”的水印显示/proc/zoneinfo在proc(5)中。我的 zoneinfo 的摘录:

    Node 0, zone    DMA32
      pages free     304988
            min      7250
            low      9062
            high     10874
            spanned  1044480
            present  888973
            managed  872457
            protection: (0, 0, 4424, 4424, 4424)
    ...
    Node 0, zone   Normal
      pages free     11977
            min      9611
            low      12013
            high     14415
            spanned  1173504
            present  1173504
            managed  1134236
            protection: (0, 0, 0, 0, 0)
    

    当前的“水印”是min、low和high。如果一个程序曾经要求足够的内存来减少free,min程序进入“直接回收”。程序在内核释放内存时等待。

    如果可能,我们希望避免直接回收。因此,如果free低于low水印,内核会唤醒kswapd。 kswapd通过交换和/或删除缓存来释放内存,直到再次free高于high。


    附加条件:kswapd还将运行以保护完整的 lowmem_reserve 数量,以供内核 lowmem 和 DMA 使用。默认的lowmem_reserve约为 RAM 的前 4GiB(DMA32 区域)的 1/256,因此通常在 16MiB 左右。

    Linux 代码提交

    mm:按内存比例缩放 kswapd 水印

    [...]

    watermark_scale_factor:

    这个因素控制着kswapd 的攻击性。它定义在 kswapd 被唤醒之前节点/系统中剩余的内存量以及在 kswapd 重新进入睡眠之前需要释放多少内存。

    单位是 10,000 的分数。默认值 10 表示水印之间的距离是节点/系统中可用内存的 0.1%。最大值为 1000,即内存的 10%。

    线程进入直接回收 (allocstall) 或 kswapd 过早进入睡眠 (kswapd_low_wmark_hit_quickly) 的线程率高可能表明 kswapd 出于延迟原因维护的空闲页面数量对于系统中发生的分配突发来说太小了。然后可以使用此旋钮相应地调整 kswapd 的积极性。

    proc: meminfo: 更保守地估计可用内存

    中的MemAvailable项目/proc/meminfo是为了向用户提示可分配多少内存而不会导致交换,因此它排除了区域的低水位线,因为用户空间不可用。

    但是,对于用户空间分配,kswapd实际上会回收,直到空闲页面达到高水位线和页面分配器的低内存保护的组合,该保护也从用户空间保留一定数量的 DMA 和 DMA32 内存。

    在计算 MemAvailable 时,从空闲页面的数量中减去我们知道的对用户空间不可用的全部数量。

    Linux 代码

    有时声称更改swappiness为0将有效地禁用“机会交换”。这提供了一个有趣的调查途径。如果有一种叫做“机会性交换”的东西,并且它可以通过交换性进行调整,那么我们可以通过找到所有读取的调用链来追踪它vm_swappiness。请注意,我们可以通过假设CONFIG_MEMCG未设置来减少搜索空间(即“内存 cgroup”被禁用)。调用链如下:

    • vm_swappiness
    • mem_cgroup_swappiness
    • get_scan_count
    • 收缩节点memcg
    • 收缩节点

    shrink_node_memcg被评论为“这是一个基本的每个节点页面更自由。被 kswapd 和直接回收使用”。即这个函数增加了空闲页面的数量。它不会尝试复制要交换的页面,以便可以在以后释放它们。但即使我们打折:

    上面的链是从三个不同的函数调用的,如下所示。正如预期的那样,我们可以将调用站点分为直接回收和 kswapd。在直接回收中执行“机会交换”是没有意义的。

    1. /*
       * 这是页面分配进程的直接回收路径。只有我们
       * 尝试从满足调用者分配的区域中回收页面
       * 要求。
       *
       * 如果一个区域被认为充满了固定页面,那么就给它一个亮点
       *扫描然后放弃它。
       */
      静态无效收缩区
      
    2. * kswapd 缩小处于或低于最高可用页面的节点
       * 当前不平衡的区域。
       *
       * 如果 kswapd 至少扫描了请求的页数,则返回 true
       * 回收或者如果由于写回页面而缺乏进展。
       * 这用于确定是否需要提高扫描优先级。
       */
      静态布尔kswapd_shrink_node
      
    3. * 对于 kswapd,balance_pgdat() 将从区域中跨节点回收页面
       * 在至少一个区域被调用之前有资格被调用者使用
       * 平衡。
       *
       * 返回 kswapd 完成回收的顺序。
       *
       * kswapd 在 highmem->normal->dma 方向扫描区域。它跳过
       * 具有 free_pages > high_wmark_pages(zone) 的区域,但一旦一个区域是
       * 发现有 free_pages <= high_wmark_pages(zone),该区域中的任何页面
       * 或更低的区域有资格进行回收,直到至少有一个可用区域被回收
       * 平衡。
       */
      静态 int balance_pgdat
      

    因此,可能声称 kswapd 以某种方式被唤醒,即使所有内存分配都立即从可用内存中得到满足。我查看了 的用法wake_up_interruptible(&pgdat->kswapd_wait),但没有看到任何这样的唤醒。

    • 17
  2. Nikolai
    2019-08-07T23:56:09+08:002019-08-07T23:56:09+08:00

    不,Linux 中不存在机会交换。我花了一些时间研究这个问题,所有来源(教科书、内核开发人员邮件列表上的电子邮件、Linux 源代码和提交评论,以及与 Mel Gorman 的一些 Twitter 交流)都告诉我同样的事情:Linux 只回收内存以响应某种形式的内存压力(明显的休眠除外)。

    关于这个主题的所有流行误解可能源于一个简单的事实,即 Linux 不能等到空闲内存的最后一个字节才开始交换。它需要某种缓冲来保护它免受极端形式的内存耗尽,并且有一些可调参数可以影响缓冲的大小(例如vm.min_free_kbytes)。但这与“交换,因为没有更好的事情可做”不同。

    不幸的是,页框回收算法相对于 2.6 变得更加复杂(当它在 Mel Gorman 的书中详细描述时),但基本思想或多或少是相同的:页回收是由失败的分配触发的,然后要么唤醒kswapd或尝试同步释放页面(取决于内存压力、分配标志和其他因素)。

    页面分配可能开始失败并剩余足够的可用内存的最明显原因是它们可能要求连续的内存,而实际上内存可能过于碎片化而无法满足请求。从历史上看,Linux 内核开发人员竭尽全力避免需要连续分配。尽管如此,一些设备驱动程序仍然需要这样做——或者因为它们不能进行多页内存 I/O(分散-聚集 DMA),或者它可能只是驱动程序开发人员的草率编码。透明大页面 (THP) 的出现为在物理上连续的块中分配内存提供了另一个原因。

    大约在同一时间范围内引入的区域压缩应该有助于解决内存碎片问题,但它并不总是产生预期的效果。

    有各种vmscan跟踪点可以帮助您了解在您的特定情况下到底发生了什么——当有特定的调用堆栈时,在 Linux 内核代码中找到您需要的东西总是更容易,而不是仅仅扫描看起来远程相关的所有内容。

    • 6

相关问题

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • 进程是否可以分配高速缓存,以便内核在必要时可以占用它?

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve