Python/Python

[Python] lru_cache

상쾌한기분 2022. 9. 28. 20:48
반응형

[Python] lru_cache 

0. 개요

LRU(Last Recently Used) 는 운영체제 OS에서 메모리 관리에서 Page 교체에서 사용되는 알고리즘 중 하나로
가장 오랫동안 사용하지 않은 것을 교체하는 방식입니다

Python에서는 @lru_cache 로 데코레이터로 기능을 제공해주고 있습니다.

1. 기대 효과

  • Memorization 으로 추가 계산 감소
  • CPU-Bound 감소

2. Sample Code

  • lru_cache 데코레이터는 실행 함수에 3가지 함수를 추가합니다.
    • 사용 방법은 @lru_cache(maxsize=128, typed=False)
      • maxsize : lru_cache에 입력된 호출 기억하고 있을 크기
      • typed : 고정 타입 사용 유무
    • cache_parameters() : 데코레이터 입력 값
    • cache_info() : 캐시 정보
    • cache_clear() : 캐시 지우기
import random
from decimal import Decimal
from functools import lru_cache
from random import choice

class Message:
    HTTP_SUCCESS = (200, "Success")
    HTTP_CREATED = (201, "Created")
    HTTP_BAD_REQUEST = (400, "Bad request")
    HTTP_NOT_FOUND = (404, "Not found")

    USER_NOT_FOUND = (1000, "User not found")
    USER_EMAIL_EXIST = (1010, "User email already exist")

@lru_cache
def get_message():
    return Message

def rand() -> str:
    return choice([
        "HTTP_SUCCESS", "HTTP_CREATED", "HTTP_BAD_REQUEST", "HTTP_NOT_FOUND",
    ])

@lru_cache(maxsize=5, typed=True)
def calc_something(a: int, b: int) -> int:
    return a * b

class Stock:

    def __init__(self, name: str, price: Decimal, discount: Decimal):
        self.name = name
        self.price = price
        self.discount = discount

@lru_cache(typed=True)
def calc_pay_price(price: Decimal, discount: Decimal) -> Decimal:
    return price - discount

if __name__ == '__main__':
    print("### Config, Message 등 고정 값(?) 같은 것들")
    for _ in range(10):
        print(getattr(get_message(), rand()), '\t\t', get_message.cache_info())

    print("# 이후에도 메모지에이션 되어 있음")
    print(get_message().HTTP_SUCCESS, '\t\t', get_message.cache_info())
    print(get_message().USER_NOT_FOUND, '\t\t', get_message.cache_info())

    print("\n\n### 단순 계산")
    for _ in range(10):
        rand_int = random.randint(0, 10)
        print(calc_something(rand_int, rand_int), '\t\t', calc_something.cache_info())

    print("\n\n### 엔티티 계산")
    stocks = [
        Stock("Product-1", Decimal(100), Decimal(10)),
        Stock("Product-2", Decimal(200), Decimal(10)),
        Stock("Product-3", Decimal(300), Decimal(10)),
        Stock("Product-4", Decimal(100), Decimal(10)),
        Stock("Product-5", Decimal(400), Decimal(10)),
        Stock("Product-6", Decimal(200), Decimal(10)),
    ]

    for stock in stocks:
        print(calc_pay_price(stock.price, stock.discount), "\t\t", calc_pay_price.cache_info())

3. Sample Code Result

### Config, Message 등
(200, 'Success')                CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
(200, 'Success')                CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)
(400, 'Bad request')            CacheInfo(hits=2, misses=1, maxsize=128, currsize=1)
(400, 'Bad request')            CacheInfo(hits=3, misses=1, maxsize=128, currsize=1)
(201, 'Created')                CacheInfo(hits=4, misses=1, maxsize=128, currsize=1)
(404, 'Not found')              CacheInfo(hits=5, misses=1, maxsize=128, currsize=1)
(404, 'Not found')              CacheInfo(hits=6, misses=1, maxsize=128, currsize=1)
(200, 'Success')                CacheInfo(hits=7, misses=1, maxsize=128, currsize=1)
(200, 'Success')                CacheInfo(hits=8, misses=1, maxsize=128, currsize=1)
(404, 'Not found')              CacheInfo(hits=9, misses=1, maxsize=128, currsize=1)

# 이후에도 메모지에이션 되어 있음
(200, 'Success')                CacheInfo(hits=10, misses=1, maxsize=128, currsize=1)
(1000, 'User not found')      CacheInfo(hits=11, misses=1, maxsize=128, currsize=1) 

### 단순 계산
4          CacheInfo(hits=0, misses=1, maxsize=5, currsize=1)
16          CacheInfo(hits=0, misses=2, maxsize=5, currsize=2)
0          CacheInfo(hits=0, misses=3, maxsize=5, currsize=3)
4          CacheInfo(hits=1, misses=3, maxsize=5, currsize=3)
0          CacheInfo(hits=2, misses=3, maxsize=5, currsize=3)
81          CacheInfo(hits=2, misses=4, maxsize=5, currsize=4)
0          CacheInfo(hits=3, misses=4, maxsize=5, currsize=4)
100      CacheInfo(hits=3, misses=5, maxsize=5, currsize=5)
9          CacheInfo(hits=3, misses=6, maxsize=5, currsize=5)
9          CacheInfo(hits=4, misses=6, maxsize=5, currsize=5)

### 엔티티 계산
90              CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
190          CacheInfo(hits=0, misses=2, maxsize=128, currsize=2)
290          CacheInfo(hits=0, misses=3, maxsize=128, currsize=3)
90              CacheInfo(hits=1, misses=3, maxsize=128, currsize=3)
390          CacheInfo(hits=1, misses=4, maxsize=128, currsize=4)
190          CacheInfo(hits=2, misses=4, maxsize=128, currsize=4)

Ref

728x90
반응형