from typing import (
Iterator,
)
from abc import (
ABC,
abstractmethod,
)
from random import (
Random,
)
from collections import (
OrderedDict,
)
__all__ = (
'PfCachePolicy',
'PfRandomPolicy',
'PfFifoPolicy',
'PfClockPolicy',
'PfCustomPolicy',
)
[문서]
class PfCachePolicy[Key](ABC):
"""
buffer에서 page frame을 관리하는 cache policy의 기반 추상 클래스입니다.
"""
[문서]
@abstractmethod
def access(self, key: Key) -> None: # pragma: no cover
"""
key에 해당하는 page frame를 가장 최근에 접근한 것으로 표시합니다.
Args:
key (Key):
대상 page frame의 key.
"""
pass
[문서]
@abstractmethod
def insert(self, key: Key) -> None: # pragma: no cover
"""
key에 해당하는 page frame를 cache에 추가합니다.
Args:
key (Key):
대상 page frame의 key.
"""
pass
[문서]
@abstractmethod
def remove(self, key: Key) -> None: # pragma: no cover
"""
key에 해당하는 page frame를 cache에서 제거합니다.
Args:
key (Key):
대상 page frame의 key.
"""
pass
[문서]
@abstractmethod
def victims(self) -> Iterator[Key]: # pragma: no cover
"""
cache에서 evict 후보인 page frame들을 yield 합니다.
Yields:
Key:
evict 후보 page frame들의 key.
"""
pass
[문서]
class PfRandomPolicy[Key](PfCachePolicy[Key]):
"""
evict 후보 page frame을 무작위로 선택하는 cache policy 클래스입니다.
Attributes:
_seed (int):
랜덤 시드.
_rng (Random):
랜덤 생성기.
_set (set[Key]):
cache에 있는 page frame들의 key를 관리하는 컨테이너.
"""
[문서]
def __init__(self, seed: int = 0) -> None:
"""
cache policy를 초기화합니다.
Args:
seed (int):
랜덤 시드 (기본값: `0`).
"""
self._seed = seed
self._rng = Random(seed)
self._set: set[Key] = set()
[문서]
def access(self, key: Key) -> None:
pass
[문서]
def insert(self, key: Key) -> None:
self._set.add(key)
[문서]
def remove(self, key: Key) -> None:
self._set.discard(key)
[문서]
def victims(self) -> Iterator[Key]:
keys = list(self._set)
self._rng.shuffle(keys)
for key in keys:
yield key
[문서]
class PfFifoPolicy[Key](PfCachePolicy[Key]):
"""
evict 후보 page frame을 FIFO 순서로 선택하는 cache policy 클래스입니다.
Attributes:
_table (OrderedDict[Key, None]):
cache에 있는 page frame들의 key를 관리하는 컨테이너.
"""
[문서]
def __init__(self) -> None:
"""
cache policy를 초기화합니다.
"""
self._table: OrderedDict[Key, None] = OrderedDict()
[문서]
def access(self, key: Key) -> None:
pass
[문서]
def insert(self, key: Key) -> None:
self._table[key] = None
[문서]
def remove(self, key: Key) -> None:
self._table.pop(key)
[문서]
def victims(self) -> Iterator[Key]:
for key in self._table:
yield key
[문서]
class PfClockPolicy[Key](PfCachePolicy[Key]):
"""
evict 후보 page frame을 Clock 알고리즘으로 선택하는 cache policy 클래스입니다.
Attributes:
_chance (int):
Clock 알고리즘에서 잔여 유예 횟수.
_slots (list[Key | None]):
cache에 있는 page frame들의 key를 관리하는 컨테이너.
_counter (list[int]):
slot에 해당하는 잔여 유예 횟수를 관리하는 컨테이너.
_find (dict[Key, int]):
key에 해당하는 slot의 인덱스를 관리하는 컨테이너.
_frees (list[int]):
free slot의 인덱스를 관리하는 컨테이너.
_hand (int):
Clock 알고리즘에서 현재 가리키고 있는 인덱스.
"""
[문서]
def __init__(self, chance: int = 2) -> None:
"""
cache policy를 초기화합니다.
Args:
chance (int):
Clock 알고리즘에서 잔여 유예 횟수 (기본값: `2`).
"""
self._chance = chance
self._slots: list[Key | None] = []
self._counter: list[int] = []
self._find: dict[Key, int] = {}
self._frees: list[int] = []
self._hand = 0
[문서]
def access(self, key: Key) -> None:
index = self._find[key]
self._counter[index] = min(self._counter[index] + 1, self._chance - 1)
[문서]
def insert(self, key: Key) -> None:
if self._frees:
index = self._frees.pop()
self._slots[index] = key
self._counter[index] = 0
else:
index = len(self._slots)
self._slots.append(key)
self._counter.append(0)
self._find[key] = index
[문서]
def remove(self, key: Key) -> None:
index = self._find.pop(key)
self._slots[index] = None
self._counter[index] = 0
self._frees.append(index)
[문서]
def victims(self) -> Iterator[Key]:
size = len(self._slots)
for _ in range(size * self._chance):
key = self._slots[self._hand]
assert key is not None
if not self._counter[self._hand]:
yield key
else:
self._counter[self._hand] -= 1
self._hand = (self._hand + 1) % size
[문서]
class PfCustomPolicy[Key](PfCachePolicy[Key]):
"""
evict 후보 page frame을 사용자가 구현한 방식으로 선택하는 cache policy 클래스입니다.
이 클래스의 attribute는 자유롭게 정의할 수 있습니다.
"""
[문서]
def __init__(self) -> None:
"""
cache policy를 초기화합니다.
이 클래스의 초기화 argument는 자유롭게 정의할 수 있습니다.
다만, 기본값을 정의해야 테스트에서 사용할 수 있습니다.
"""
raise NotImplementedError
[문서]
def access(self, key: Key) -> None:
raise NotImplementedError
[문서]
def insert(self, key: Key) -> None:
raise NotImplementedError
[문서]
def remove(self, key: Key) -> None:
raise NotImplementedError
[문서]
def victims(self) -> Iterator[Key]:
raise NotImplementedError