사용 가능한 메모리가 기가바이트이면 상단에 "swout"이라고 표시됩니다. 왜?

사용 가능한 메모리가 기가바이트이면 상단에 "swout"이라고 표시됩니다. 왜?

사용 가능한 메모리가 기가바이트인데 왜 atop20,000페이지(80MB 이상) 이상을 교환한다고 표시됩니까 ?

나는 이것에 대한 성능 문제를 발견하지 못했습니다. 저는 이 기회를 통해 지식을 늘리고 싶었습니다 :-).

atop10초마다 새로 고쳐집니다. 새로 고칠 때마다 마지막 새로 고침 이후의 활동이 표시됩니다.

MEM | tot     7.7G | free    3.7G | cache 608.3M | buff   19.1M | slab  264.6M |
SWP | tot     2.0G | free    1.4G |              | vmcom  13.4G | vmlim   5.8G |
PAG | scan  167264 | steal 109112 | stall      0 | swin       0 | swout  23834 |

                                "swout" is non-zero and coloured in red  ^

커널 메모리 정보:

$ head -n 5 /proc/meminfo
MemTotal:        8042664 kB
MemFree:         3563088 kB
MemAvailable:    3922092 kB
Buffers:           20484 kB
Cached:           775308 kB

커널 버전:

$ uname -r
5.0.16-200.fc29.x86_64

  1. 이것이 영향을 받을지는 불분명합니다 vm.swappiness. 이 설정은 캐시 제거와 스와핑의 균형을 유지합니다. 그러나 많은무료기억, 그렇다면 애초에 기억을 되찾아야 하는 이유는 무엇입니까?

  2. 보시다시피 이것은 작은 시스템입니다. NUMA를 사용하지 않습니다. 체크인한 결과 /proc/zoneinfo"Node 0" 노드가 하나만 있는 것으로 나타났습니다. 그래서 이것은 아니다NUMA로 인해 발생함.

  3. 관련 질문과 답변에는 "기회적 스와핑", "시스템이 할 일이 없을 때", "나중에 메모리 부족이 발생하는 경우" 등과 같은 아이디어가 언급되어 있습니다. 나는 이러한 아이디어가 커널 문서와 모순되기 때문에 신뢰할 수 없다고 생각합니다. 바라보다 Linux는 "기회적 교환"을 수행합니까, 아니면 신화입니까?

  4. 이 기능을 사용할 때 RAM 사용량에는 설정된 제한이 없습니다 systemd.resources. 즉 systemd, 모든 장치의 RAM 사용 제한이 "무제한"으로 설정되어 있는 것 같습니다 .

    $ systemctl show '*' | \
        grep -E '(Memory|Swap).*(Max|Limit|High)' | \
        grep -v infinity
    $
    
  5. 편집: 나는 이것이 투명한 거대한 페이지와 관련이 있다고 생각합니다. 가상 머신은 게스트 메모리를 효율적으로 할당하기 위해 투명한 hugepage를 사용하는 것으로 나타났습니다. 거대한 페이지를 사용하는 유일한 사용자 프로그램입니다.내 시스템에서.

    비슷한 질문이 있습니다:사용 가능한 메모리가 Pages_high 워터마크보다 훨씬 높으면 kswapd를 활성화할 수 있습니까?모든 애플리케이션에 대해 대형 페이지를 지원하는 RHEL 6에 대해 묻고 있습니다.

이 결과를 재현하는 방법을 잘 모르겠습니다.

이는 가상 머신을 시작할 때 발생합니다. libvirt를 사용하여 가상 머신을 실행합니다. 기본적으로 VM 디스크 읽기는 호스트 페이지 캐시를 사용하여 캐시됩니다. (캐시 모드: "하이퍼바이저 기본값"은 "쓰기 저장"을 의미합니다).

가상 머신, FADVISE_DONTNEED이미지 파일을 중지하고 다시 시도했습니다. 그러나 같은 일은 일어나지 않았습니다.

그런 다음 다른 가상 머신으로 다시 시도했는데 이 문제가 잠시 동안 발생했습니다. 나는 그것을 잡았다 vmstat. 나는 "swout"이 다른, 더 높은 숫자를 나타내는 것이라고 생각했지만 atop그것을 잡지 못했습니다.

$ vmstat 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 770168 5034300  28024 936256    0    2    21    86   60  101 22  9 68  1  0
 0  0 770168 5033852  28048 935904    0    0     0     8  372  633  1  1 97  0  0
 1  0 770168 4974048  28252 948152    3    0  1137   194 1859 2559 11  7 79  3  0
 0  1 770168 4557968  28308 1037512    0    0  8974    45 3595 6218 16  6 57 21  0
 6  3 770168 4317800  28324 1111408    0    0  7200   609 6820 6793 12  5 38 44  0
 0  4 770168 4125100  28348 1182624    0    0  6900   269 5054 3674 74  3  8 15  0
 0  5 770168 3898200  27840 1259768    2    0  9421   630 4694 5465 11  6 11 71  0
 1  3 770168 3760316  27672 1300540    0    0  9294   897 3308 4135  5  4 28 63  0
 0  1 770168 3531332  27032 1356236    0    0 10532   155 3140 4949  8  5 63 25  0
 0  0 783772 3381556  27032 1320296    0 1390  7320  4210 4450 5112 17  5 43 35  0
 0  0 783772 3446284  27056 1335116    0    0   239   441  995 1782  4  2 92  2  0
 0  0 783772 3459688  27076 1335372    0    0     3   410  728 1037  2  2 95  1  0

systemd또한 libvirt가 우회 하고 실수로 자체 스왑하는 경우를 대비하여 VM의 cgroup 메모리 제한도 확인했습니다 .

$ cd /sys/fs/cgroup/memory/machine.slice/machine-qemu\x2d5\x2ddebian9.scope
$ find -type d  # there were no sub-directories here
$ grep -H . *limit_in_bytes
memory.kmem.limit_in_bytes:9223372036854771712
memory.kmem.tcp.limit_in_bytes:9223372036854771712
memory.limit_in_bytes:9223372036854771712
memory.memsw.limit_in_bytes:9223372036854771712
memory.soft_limit_in_bytes:9223372036854771712
$ cd ../..
$ find -name "*limit_in_bytes" -exec grep -H -v 9223372036854771712 \{\} \;
$

답변1

나는 비슷한 문제에 대해 생각하고 있었습니다. kswapd 및 영역 워터마크에 대한 내 게시물을 보셨을 겁니다. 제 경우(그리고 아마도 귀하의 경우에도 마찬가지)의 대답은 메모리 조각화였습니다.

메모리가 충분히 단편화되면 고차 할당이 실패하여 (다른 많은 요인에 따라) 직접 회수가 발생하거나 kswapd가 깨어나 영역 회수/압축을 시도합니다. 내 게시물에서 몇 가지 추가 세부정보를 확인할 수 있습니다.

이와 같은 문제를 다룰 때 간과될 수 있는 또 다른 사항은 메모리입니다.분할. 즉, 아마도 메모리가 충분할 것입니다.포괄적인(충분한 연속 블록을 포함할 수도 있습니다.) 그러나 DMA32로 제한될 수 있습니다(64비트 아키텍처를 사용하는 경우). 어떤 사람들은 DMA32를 "작다"고 무시하는 경향이 있지만(아마도 그들이 32비트 생각에 익숙하기 때문일 것입니다), 4GB는 실제로 "작다"는 것이 아닙니다.

귀하의 사건에서 무슨 일이 일어났는지 판단하는 방법에는 두 가지가 있습니다. 하나는 통계를 분석하는 것입니다. /proc/buddyinfo, /proc/zoneinfo, /proc/vmstat 등의 주기적 스냅샷을 찍도록 작업을 설정하고 현재 보고 있는 내용을 이해하려고 노력할 수 있습니다.

작동하게 되면 또 다른 접근 방식이 더 간단하고 안정적입니다. 스왑 이벤트로 이어지는 코드 경로를 캡처해야 하며 커널 계측 추적점을 사용하여 이 작업을 수행할 수 있습니다(특히 vmscan 이벤트가 많이 있음).

그러나 낮은 수준의 계측기가 항상 원래대로 작동하는 것은 아니기 때문에 이를 작동시키는 것이 어려울 수 있습니다. 내 경우에는 ftrace 인프라를 설정하는 데 시간이 좀 걸렸지만 결국 우리에게 필요한 function_graph 프로브가 어떤 이유로 작동하지 않는다는 사실을 발견했습니다. 우리가 시도한 다음 도구는 perf였지만 첫 번째 시도에서도 작동하지 않았습니다. 그러나 마침내 관심 있는 이벤트를 캡처하면 그 어떤 글로벌 카운터보다 더 빠르게 답변을 얻을 수 있습니다.

감사합니다, 니콜라

관련 정보