대부분의 General Purpose processor들은 page table을 이용해 VM을 지원하며, TLB의 page table에서 VA-PA mapping을 caching한다. TLB coverage는 이 cache된 mapping으로 access 가능한 memory의 양이다. (TLB entry # * page size) 지난 10년 동안 TLB coverage는 main memory size보다 천천히 증가했다. 따라서 오늘날 TLB coverage는 physical memory의 일부분밖에 안 된다. 따라서 working set이 더 큰 application은 성능 저하가 발생한다.
superpage는 한 TLB entry로 base page보다 더 큰 memory page를 차지할 수 있어, 같은 TLB entry 수로 더 큰 TLB coverage가 가능해 TLB miss가 줄어든다.
하지만 너무 큰 superpage를 부적절하게 사용하면
이러한 I/O 비용은 TLB miss 방지보다도 훨씬 크다. 따라서 OS는 page 크기를 혼합해서 사용해야 한다. 하지만 이 경우 external fragmentation이 생긴다. 따라서 external fragmentation이 생기지 않도록 OS가 지원해줄 필요가 있는데 대부분의 OS는 superpage를 이를 별로 지원하지 않는다.
본 논문은 general하고 transparent한(application에 상관없이 사용 가능한) superpage management system을 제안한다.
지난 10년 동안 main memory의 크기가 증가하여 application의 memory requirement도 증가했으나 TLB coverage는 별로 증가하지 않았다. TLB는 일반적으로 fully associative이며 memory access의 critical path에 있기 때문에 access time이 작게 유지되어야 해서 TLB entry를 막 늘릴 수가 없으며 따라서 일반적으로 128개 이하의 entry를 사용한다. 이에 따라 최신 application은 TLB coverage보다 큰 working set을 가진다. 심지어 요새는 physical address cache가 TLB coverage보다 커져서 TLB miss가 cache에 있는 data에 대해서도 memory access를 해야 할 수도 있다.
TLB size ( = TLB entry # ) 를 키우지 않고 coverage를 증가시키는 방법인 더 큰 크기의 base page를 사용하는 방법을 채택할 수 있다. 근데 이 방법은 internal fragmentation이 증가하여 memory pressure가 더 빨리 발생하고, paging granularity가 증가하여 IO demand가 커진다.
따라서 base page는 그대로 두되 더 큰 size의 page를 같이 사용하여 internal fragmentation과 disk traffic을 줄이면서 TLB coverage를 늘릴 수 있다. 여러 size의 page를 사용하기 위해서 OS의 지원이 필요하다.
TLB hardware 설계에 의한 superpage 제약
virtual address space는 code, data, stack, heap 등의 memory object로 이루어졌다고 가정한다. 또 physical memory는 처음 access될 때 할당한다고 가정한다.
[Allocation]
[Fragmentation control]
multiple page size를 쓰거나 wired-page (paging이 불가능한 page)가 있으면 external fragmentation이 발생한다.
따라서 OS는 연속성 복구 technique을 적용해야 한다. 이 때 예약을 선점해서 다른 용도로 사용할 것인지 큰 예약으로 냅둘 것인지의 tradeoff가 있다.
[Promotion]
예약해놓은 곳이나, base page들이 크기, 연속성, 정렬, 보호제약을 만족하면 superpage로 승격할 수 있다.
promotion 정책은 TLB miss 감소라는 이점과 memory 소비 증가라는 손해에 대해 tradeoff가 있다.
[Demotion]
page attribute가 바뀌거나, 일부만 수정할 때 demotion이 필요하다. process가 superpage의 모든 부분을 사용하지 않고 메모리 부족이 있을 때 강등시킬 수 있다. 그런데 reference bit가 superpage에 대해 하나만 있기 때문에 어느 부분을 안 쓰는지 확인하기가 어렵다는 issue가 있다.
[Eviction]
memory pressure 시 physical memory로부터 inactive superpage를 evict해야 한다. 이 때 superpage는 dirty bit가 하나만 있어서 일부는 clean하더라도 superpage 전체를 flush해야 할 수도 있다는 문제가 있다.
reservation-based superpage 관리 정책을 채택하여
로 확장
각 memory object의 allocation을 track할 때 사용한다. population map은 모든 page fault에 대해 query되기 때문에 효율적으로 찾을 수 있어야 하는데, 따라서 각 page size에 대응되는 level에 대해 radix tree를 만든다.
leaf가 아닌 node에는 다음 level의 superpage 크기 만큼의 영역을 유지하며, somepop (하위 level node 중 하나 이상 찬 것 개수), fullpop (하위 level node 중 꽉 찬 것 개수) counter를 가진다.
[Population map의 목적]
reservation list가 완전히 populate되지 않은 page frame extent를 linked list로 가지고 있음
ex) 64KB 범위가 필요한 경우
page fault handler가 page frame을 할당할 때 한 번에 한 frame을 할당하지 않고 fault가 난 base page를 포함하는 영역에 대해 preferred superpage size만큼의 연속된 page frame set를 할당한다. 이 때 fault가 일어난 base page 외의 다른 page는 예약 상태로 예약된 page에서 fault가 발생하는 경우에는 base page의 page table의 mapping을 그대로 사용할 수 있다.
page size를 크게 잡으면 demotion이 필요하지만, 너무 작게 잡으면 relocation이 필요하다. 일반적으로 demotion overhead가 relocation보다 작기도 하고, 크게 잡은 경우 예약을 선점할 수 있기 때문에 큰 size를 사용한다.
사용 가능한 메모리가 부족하거나, fragmentation이 과도하게 일어난 경우 reservation된 애들 중 사용하지 않는 frame을 선점할 수 있다.
할당이 요청되었으나 원하는 크기의 extent가 없는 경우
하여 원하는 크기의 extent를 만든다. 가능한 한 할당을 거부하기보다는 기존 예약을 선점한다고 한다. 선점하는 victim은 LRU policy로 선택한다.
여러 page size를 사용하다보면 external fragmentation이 생겨 큰 superpage의 개수가 부족해진다. 따라서 buddy allocator가 가능할 떄마다 coalescing을 수행한다.
또한 page replacement daemon이 contiguity-aware page replacement를 background에서 수행한다. 이 daemon의 기능은 implementation에서 설명한다.
예약이 모두 populate되지 않더라도 다음 크기로 승격할 수 있지만, 이 경우 memory footprint가 증가하기 때문에 그냥 모두 populate될 때 승격시킨다. 따라서 promotion은 점진적으로 일어난다.
populate : 예약 내의 base page가 mapping됨
footprint : 실제로 메모리에서 써야 하는 data의 크기. superpage를 사용하는 경우 base page만큼을 access하더라도 superpage의 size만큼 읽고 써야 한다.
demotion이 발생한다. demotion도 바로 base page 크기로 할 필요는 없기 때문에 incremental하게 수행한다.
superpage의 모든 부분이 활발하게 사용되는지 확인하기 위해 주기적으로 demotion을 하기도 한다. reference bit를 재설정할 때 해당 superpage를 demotion하고, 모든 base page가 참조되면 다시 promote한다.
dirty bit가 superpage에 대해 1개 뿐이어서 superpage 중 일부만 수정되었더라도 superpage 전체를 evict해야 한다. 이렇게 부분적으로 dirty한 superpage에 의한 I/O 성능 저하가 superpage의 이점을 초과할 수 있다. 따라서 write를 하면 superpage를 강등하고 모든 base page가 dirty되면 다시 promote한다.
[Inferring dirty page using hash digest]
대안으로 hash를 사용할 수도 있다. clean memory를 읽으면 해당 내용의 cryptrographic hash digest가 계산되어 기록된다. page을 flush할 때 hash를 다시 계산하여 실제로 disk에 기록할 base page를 확인한다. 근데 암호화하는 구현 자체가 overhead가 커서 본 논문에서는 사용하지 않았다고 한다.
실제로 실험을 위해 위 내용들을 구현하기 위한 수정사항들을 설명한다.
FreeBSD의 page daemon은 근사 LRU 순서로 active, inactive, cache page의 3개 list를 가진다.
memory pressure일 때 daemon은
[본 논문에서 contiguity-aware하게 만들기 위해 수정 사항]
wired-page는 위치를 바꿀 수 없어서 paging이 불가능한 page들을 말한다. 일반적으로 부팅 시 physical memory에 클러스터링되지만, 다른 프로세스가 실행되는 동안 kernel이 메모리를 할당하면 점점 scatter된다. 따라서 wired-page를 미리 식별하여 인접한 physical memory pool에 clustering한다.
두 프로세스가 file을 서로 다른 VA에 mapping할 수 있다. VA가 base page보다 더 크게 차이나는 경우 superpage를 만들 수 없다. application이 file을 mapping할 때 주소를 지정하지 않는 경우가 많으므로 kernel이 VA를 할당할 수 있다. 따라서 superpage와 호환되도록 VA를 선택하여 해결한다.