16GB의 물리적 메모리를 대부분 사용하는 애플리케이션을 실행하면 Linux 커널이 메모리의 페이지 대부분을 스왑합니다. 애플리케이션이 완료된 후 각 작업(명령 입력, 작업 공간 전환, 새 웹 페이지 열기 등)을 완료하는 데 오랜 시간이 걸립니다. 왜냐하면 관련 페이지를 먼저 교환에서 다시 읽어야 하기 때문입니다.
각 애플리케이션을 수동으로 건드리고 기다릴 필요 없이 Linux 커널에 페이지를 스왑에서 물리적 메모리로 다시 복사하도록 지시할 수 있는 방법이 있습니까? 나는 많은 응용 프로그램을 실행하므로 기다리는 것이 항상 고통스럽습니다.
나는 종종 swapoff -a && swapon -a
시스템이 다시 응답하도록 하기 위해 이것을 사용하지만, 이렇게 하면 스왑 페이지가 지워지므로 다음에 스크립트를 실행할 때 다시 작성해야 합니다.
커널이 스왑에서 모든 페이지를 읽도록 지시하는 커널 인터페이스(아마도 sysfs 사용)가 있습니까?
편집: 실제로 모든 스왑을 캐시 가능하게 만드는 방법을 찾고 있습니다. (DeRobert에게 감사드립니다!)
[추신 serverfault.com/questions/153946/…그리고serverfault.com/questions/100448/…관련 주제이지만 Linux 커널이 스왑을 지우지 않고 스왑에서 메모리로 페이지를 다시 복사하도록 하는 방법에 대한 문제는 다루지 않습니다. ]
답변1
도움이 될 수 있습니다 /proc/sys/vm/page-cluster
(기본값: 3).
커널 문서에서 ( sysctl/vm.txt
):
페이지 클러스터
페이지 클러스터는 한 번의 시도로 스왑에서 읽은 연속 페이지 수를 제어합니다. 이는 페이지 캐시 미리 읽기의 스왑 대응입니다. 언급된 연속성은 가상/물리적 주소가 아니라 스왑 공간의 연속성을 의미합니다. 즉, 서로 스왑된다는 의미입니다.
로그 값입니다. 0으로 설정하면 "1페이지"를 의미하고, 1로 설정하면 "2페이지"를 의미하고, 2로 설정하면 "4페이지"를 의미합니다. 0은 스왑 미리 읽기를 완전히 비활성화합니다.
기본값은 3(한 번에 8페이지)입니다. 워크로드가 스왑 집약적이라면 이를 다른 값으로 조정하면 약간의 이점이 있을 수 있습니다.
값이 낮을수록 초기 오류에 대한 대기 시간이 짧아지지만, 미리 읽기 연속 페이지의 일부인 경우 추가 오류 및 후속 오류에 대한 I/O 대기 시간이 희생됩니다.
문서에는 제한이 언급되어 있지 않으므로 모든 스왑을 매우 빠르게 다시 읽을 수 있도록 엄청나게 높게 설정할 수 있습니다. 물론, 이후에는 다시 정상값으로 되돌리세요.
답변2
마술처럼 "시스템을 다시 반응하게 만들" 수는 없는 것 같습니다. 즉시 페널티를 받거나, 페이지를 스왑 공간에서 메모리로 다시 읽어오거나, 나중에 페널티를 받거나 둘 중 하나를 선택해야 합니다. 그러나 어느 쪽이든 원인이 됩니다. 사실 비슷한 일을 했다면 swapoff -a && swapon -a
느낄 수도 있을 것입니다.더더 이상 필요하지 않은 특정 페이지를 메모리에 다시 복사하도록 강제하고 읽지 못한 채 삭제되기 때문에 덜 고통스럽습니다. (생각해 보십시오. 대부분의 힙이 교체되는 동안 애플리케이션을 종료합니다. 페이지는 메모리로 다시 읽히지 않고 완전히 폐기될 수 있습니다.
하지만 이렇게 하면 스왑 페이지가 지워지므로 다음에 스크립트를 실행할 때 스왑 페이지를 다시 작성해야 합니다.
글쎄, 스왑에서 메인 메모리로 다시 복사된 거의 모든 페이지는 수정될 것이므로 나중에 스왑으로 다시 이동해야 하는 경우 어쨌든 스왑으로 다시 작성해야 합니다. 스왑 영역은 읽기 전용 페이지(일반적으로 파일로 지원됨)가 아니라 주로 힙 메모리라는 점을 기억하세요.
나는 당신의 swapoff -a && swapon -a
트릭이 당신이 생각해 낼 수 있는 것만큼 훌륭하다고 생각합니다.
답변3
기반으로메모리 덤퍼처음에 발견여기지정된 응용 프로그램을 선택적으로 다시 메모리로 읽어들이는 스크립트를 만들었습니다. remember
:
#!/bin/bash
declare -A Q
for i in "$@"; do
E=$(readlink /proc/$i/exe);
if [ -z "$E" ]; then
#echo skipped $i;
continue;
fi
if echo $E | grep -qF memdump; then
#echo skipped $i >&2;
continue;
fi
if [ -n "${Q[${E}]}" ]; then
#echo already $i >&2;
continue;
fi
echo "$i $E" >&2
memdump $i 2> /dev/null
Q[$E]=$i
done | pv -c -i 2 > /dev/null
사용법: 유사
# ./remember $(< /mnt/cgroup/tasks )
1 /sbin/init
882 /bin/bash
1301 /usr/bin/hexchat
...
2.21GiB 0:00:02 [ 1.1GiB/s] [ <=> ]
...
6838 /sbin/agetty
11.6GiB 0:00:10 [1.16GiB/s] [ <=> ]
...
23.7GiB 0:00:38 [ 637MiB/s] [ <=> ]
#
스왑되지 않은 메모리(초당 기가바이트)를 빠르게 건너뛰고 스왑이 필요할 때 속도가 느려집니다.
답변4
여기에 아주 좋은 토론이 있습니다http://rudd-o.com/en/linux-and-free-software/tales-from-반응성랜드-why-linux-feels-slow-and-how-to-fix-that 이는 결국 상호 교환 가능성을 줄이는 것으로 귀결됩니다. 즉, 시스템의 인식된 응답성을 향상하려면 코드가 교환되는 것을 방지해야 한다는 아이디어입니다(이런 일이 발생합니다). 이것은 실제로 귀하의 질문에 대한 답변은 아니지만 문제를 예방할 수 있습니다(애플리케이션은 교체되지 않고 사용되지 않은 데이터 및 페이지 캐시만 교체됨).