- 메모리 관리 07 - 워킹셋2024년 10월 16일
- 묭묭.cpp
- 작성자
- 2024.10.16.:32
메모리 관리 07 - 워킹셋
워킹셋
- 물리 메모리 내에 상주하는 가상 페이지의 부분집합
워킹셋의 종류
- 프로세스 워킹셋
- 단일 프로세스 내의 스레드에 의해 참조되는 페이지
- 시스템 워킹셋
- 상주하는 페이징 가능한 시스템 코드의 부분집합, 페이지드 풀, 시스템 캐시
- 세션 워킹셋
어떤 페이지를 물리 메모리로 가져오고 유지하는 정책
요구 페이징
- 메모리 관리자는 페이지를 메모리로 로딩하기 위해 클러스트링을 갖는 요구 페이징(Demand Paging) 알고리즘 사용
- 페이지 폴트를 일으키면 페이지 폴트를 일으킨 페이지 앞뒤로 몇 개의 페이지를 더 읽어옴
- 페이징 I/O 수를 최소화하려는 시도
페이징 요구 정책의 부작용
- 프로세스의 처음 실행, 나중에 특정 시점에 실행을 다시 시작하는 경우
- 많은 페이지 폴트가 발생 가능
- 따라서 프로세스 시작 시점을 최적화하기 위해
- 논리적 프리패처(Logical Prefetcher)라는 지능적인 프리패치 엔진을 가짐
- 그 이상의 최적화는 슈퍼패치(SuperFetch)라는 컴포넌트에 의해 수행됨
논리적 프리패처
- 프로세스 시작 과정에서 폴트 -> 폴트 -> 폴트가 연계하여 발생
- 성능 저하
- 한 번에 여러 페이지를 프리패칭함으로 시작 과정의 속도를 최적화
프리패처가 활성화되면
- 메모리 관리자는 커널의 프리패처 코드에 페이지 폴트를 알려줌
- 두 가지의 폴트 종류
- 하드 폴트 : 페이지를 디스크부터 읽어와야 함
- 소프트 폴트 : 이미 메모리에 있는 데이터를 프로세스 워킹셋에 추가하기만 하면 됨
- 프리패처는 프로세스가 시작하는 처음 10초를 감시, 시스템 부팅은 30초
- 이 시간에 유저 셸이 시작하고 추적이 실패하면 윈도우 서비스가 초기화된지 60초 후나 시스템이 시작한 120초 후 중 먼저 도달하는 시점까지 추적
커널 수집 추적 정보
- NTFS 마스터 파일 테이블(MFT)
- 메타데이터 파일
- 참조된 파일
- 참조된 디렉터리에서 일어난 폴트
추적 정보로 무엇을 하는가?
- Svchost의 한 인스턴스에서 수행되는 슈퍼패치 서비스의 프리패처 컴포넌트로부터 요청을 대기
- 지금부터 추적 데이터를 질의할 것이란 걸 슈퍼패치 서비스에게 알리기 위해 PrefetchTracesReady 이벤트를 시그널
슈퍼 패치 서비스는 무엇을 하는가?
- 추적 데이터를 요청하기 위해 NtQuerySystemInformation 시스템 호출
- 논리적 프리패처는 이전에 수집된 데이터와 결합해 추적 데이터를 후처리함
- 그리고 %SystemRoot%\Prefetch 폴더에 파일로 저장
- .pf 확장자
레디부트
- 크고 효율적인 I/O 읽기를 만들고 RAM에 데이터를 저장함으로 I/O 동작의 최적화를 시도
- 시스템 컴포넌트가 이 데이터를 필요로 할 때 저장된 RAM을 통해 이뤄짐
- 기계적 디스크일 때 특히 효율적, SSD의 경우에도 유용함
- 그러나 SSD의 경우 이득이 미미하므로 기본적으로 꺼져있음
시스템 부팅 혹은 애플리케이션 시작
- 프리패칭을 수행할 기회를 얻음
- 프리패처는 프리패치 디렉터리를 살펴보고 상황에 맞는 추적 파일을 찾음
- 프리패처는 NTFS를 호출해 참조하는 MFT 메타파일을 프리패치
- 참조되는 각 디렉터리 내용을 읽고, 마지막으로 참조된 파일을 염
- 이때 프리패처는 메모리 관리자 함수 MmPrefetchPages를 호출해 추적 파일에 등록되어 있지만 아직 메모리에 없는 데이터와 코드를 읽음
- 메모리 관리자는 모든 읽기 동작을 비동기적으로 시작하고 완료될 때까지 대기하고 애플리케이션을 시작
배치 정책
- 페이지 폴트를 내면 페이지를 물리 메모리 어디에 넣을 것인지 정해야 함
- 이런 규칙을 배치 정책(Placement policy)라고 함
- 페이지 프레임을 선택할 때 캐시의 불필요한 스레싱(thrashing)을 최소화하기 위해 CPU의 메모리 캐시 크기를 고려함
교체 정책(Replacement policy)
- 페이지 폴트 발생 시 물리 메모리가 모두 사용 중일 때 제거할 페이지를 선택하는 정책
- 일반적인 교체 정책
- LRU(least recently used)
- 대부분의 유닉스 버전에서 구현된 방법 - clock 알고리즘이라고도 함
- 메모리 페이지가 언제 사용됐는지 추적
- 가장 오랜시간 사용되지 않은 페이지를 제거
- FIFO(first in, first out)
- 사용빈도와 관계없이 가장 오래된 페이지를 제거
- LRU(least recently used)
교체 정책의 전역 지역 구분
- 전역 교체 정책
- 프로세스에 상관없이 교체 가능
- 가장 오래 메모리에 있었던 페이지를 찾음
- 전체 운영체제에 영향을 줄 수 있음
- 지역 교체 정책
- 현재 프로세스가 소유한 페이지로 한정
윈도우는 두 가지를 조합하여 사용
- 워킹셋이 한계 혹은 정리할 필요가 있을 때
- 충분한 프리(Free) 페이지가 있다고 판단할 때까지 워킹셋에서 페이지를 제거
워킹셋 관리
- 모든 프로세스는 최소 50 페이지 기본 워킹셋과 최대 345 페이지의 최대 워킹셋으로 시작
- SetProcessWorkingSetSize 함수를 이용하여 프로세스 워킹셋 한계를 변경 가능
- 효과는 미미함
- 스케줄링 우선순위 상승 권한(SeIncreaseBasePriorityPrivilege)을 가져야 함
- 하드 워킹셋 한계를 사용하게 프로세스를 구성하지 않았다면 무시됨
- 즉, 프로세스가 과도하게 페이징을 일으키고 충분한 메모리가 존재하면 워킹셋의 한계를 증가시키게 허용함
- 반대의 경우 또한 가능 줄일 수도 있음
워킹셋 상한선
페이지 폴트가 발생하면
- 프로세스 워킹셋 한계와 가용 가능 메모리 양 검사
- 조건을 만족하면 프로세스가 워킹셋 최대값까지 키우게 허용
- 메모리가 부족하면 교체를 수행
윈도우는 변경된 페이지를 디스크에 기록하여 가용 메모리를 유지하려 함
- 물리 메모리가 모자르게 되면
- 밸런스 셋 관리자 시스템 스레드 컨텍스트에서 실행되는 워킹셋 관리자가 자동 워킹셋 정리를 시작
- SetProcessWorkingSetSizeEx 함수를 통해 프로세스 워킹셋 정리를 수행 가능
- 워킹셋 관리자가 사용 가능 메모리 검사, 어느 워킹셋이 정리될지를 결정
- 메모리가 충분 - 얼마나 많은 페이지를 제거할 수 있는지 계산
- 정리가 필요하면 최솟값 이상의 크기를 갖는 워킹셋을 찾음
- 정리할 후보 프로세스 리스트를 최적화된 순서로 구성
- 최솟값 이상을 사용하는 프로세스를 발견할 때 프로세스 워킹셋에서 제거할 페이지를 찾아 다른 용도로 사용하게 만듬
- 여유 메모리가 너무 부족하면 최소한의 프리 페이지가 확보될 때까지 워킹셋에서 페이지를 제거해 나감
어떻게 최근에 엑세스되지 않은 페이지를 제거할까?
- 하드웨어 PTE 내의 Accessed 비트를 검사해 수행
- 이 비트가 꺼져있다면 오래된 것
- 마지막 워킹셋 정리 검사를 한 이후로 페이지가 참조된 적 없음을 의미하는 카운트가 하나 증가함
- 이 카운트(age of page)를 통해 제거될 후보 페이지를 찾는데 이용
- Accessed 비트가 켜져 있다면?
- 이 비트를 끄고 다음 페이지를 검사
- 다음에 검사할 때 비트가 꺼져있음을 체크
- 이런 검사는 원하는 만큼 페이지를 제거 혹은 한 바퀴 돌아 시작점으로 돌아올 때까지 전체 워킹셋을 대상으로 계산
- 검사가 끝난 위치부터 다음번 검사가 시작됨
밸런스 셋 관리자
- 워킹셋의 확장과 정리는 밸런스 셋 관리자라고 불리는 시스템 스레드 컨텍스트에서 일어남
- KeBalanceSetManager 함수
- 시스템 초기화 시 생성됨
- 커널의 일부분이지만 워킹셋의 분석과 조정을 위해 메모리 관리자의 워킹셋 관리자를 호출함
- MmWorkingSetManager
밸런스 셋 관리자는 두 개의 이벤트 객체를 대기함
- 1초마다 주기적으로 시그널되는 이벤트
- 워킹셋 조정 시점에 시그널되는 내부 이벤트
- 페이지 폴트 횟수가 너무 잦거나 프리 리스트가 작을 때
- 메모리가 넉넉하여 폴트된 페이지를 메모리에 넣어 워킹셋 크기를 점차적을 늘리게 함
1초 주기 타이머에 의해 깨어났을 때의 과정
- 시스템이 가상 안전 모드를 지원하면 안전한 커널이 주기적인 정리를 위해 호출됨
- IRP 크래딧을 조정하기 위한 루틴 호출하고 IRP 완료에 사용되는 프로세서별 룩 어사이드 리스트의 사용량을 최적화(IoAdjustIrpCredits)
- 특정 프로세서가 과도한 I/O 부하에 놓이면 더 나은 확장성이 가능해짐
- 룩 어사이드 리스트를 검사하고 이들의 깊이를 조절하여 접근 시간을 개선 시키고 풀 사용량과 단편화를 줄임
- 윈도우 이벤트 트레이싱 버퍼 풀 크기를 조절하기 위한 호출을 하여 ETW 메모리 버퍼를 좀 더 효율적으로 사용
- 메모리 관리자의 워킹셋 관리자를 호출
- 잡에 대한 실행 시간을 강제
- 1초 타이머의 8번째마다 스왑퍼(swapper)라는 시스템 스레드를 깨움
스왑퍼(swapper)
- 한 동안 실행시키지 않았던 커널 스택을 스왑아웃
- 15초 동안 유저 모드에서 대기 상태에 있었던 스레드를 찾음
- 그런 스레드가 있다면 해당 스레드의 커널 스택을 트랜지션 상태로 두어 물리 메모리를 회수
- 그정도 기다린 스레드는 앞으로도 더 오랫동안 대기할 것이라는 원칙에 따름
- 프로세스의 마지막 스레드의 커널 스택이 메모리에서 제거되었다면 이 프로세스는 완전히 스왑아웃 되었다 표시
- 따라서 오랫동안 유휴 상태인 프로세스의 워킹셋은 0이됨
시스템 워킹셋
- 시스템 주소 공간의 페이징 가능한 코드와 데이터는 전역 워킹셋을 통해 관리
시스템 전역 워킹셋
- 시스템 캐시 워킹셋
- 시스템 캐시에 상주하는 페이지 포함
- 페이지드 풀 워킹셋
- 페이지드 풀에 상주하는 페이지 포함
- 시스템 PTE 워킹셋
- 시스템 공간으로 매핑된 섹션 페이지 포함
- 로딩된 드라이버, 커널 이미지의 페이징 가능한 코드와 데이터를 포함
메모리 통지 이벤트
윈도우는 메모리 자원이 모자를 경우 유저 모드 프로세스와 커널 모드 드라이버에게 통지
- 메모리 자원 - 물리 메모리, 페이지드 풀, 넌페이지드 풀, 커밋 양
- 이런 통지 정보는 메모리 사용량 결정을 위해 사용
유저 모드 프로세스가 통지 받을 수 있는 상황
- 낮은 메모리나 높은 메모리 조건인 경우만 통지 받을 수 있음
- 애플리케이션은 이런 상황에 통지를 원한다 명시함
- CreateMemoryResourceNotification 함수를 호출 가능함
- 이 때 얻어진 핸들은 모든 대기 함수에서 사용 가능함
- 메모리가 낮거나 높아지면(조건에 맞음) 대기는 완료되고 스레드에게 통지됨
- 스레드를 블록하지 않고 메모리 조건을 검사하고 싶다면
- QueryMemoryResourceNotification 호출
드라이버의 경우
- 메모리 관리자가 \KernelObjects 객체 관리자 디렉터리에 설정한 특정 이벤트 이름을 사용
- 전역 네임드 이벤트 객체 중 하나를 메모리 관리자가 시그널함으로 통지가 이뤄지게 구현됨
- 해당 메모리 조건이 탐지되면 적절한 이벤트가 시그널되고 대기 스레드가 일어남
반응형다음글이전글이전 글이 없습니다.댓글
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)