3.4. Cache - 3.4.2 LFU Cache

2024. 1. 26. 19:15ใ†CS - Roadmap.sh/3. Common Algorithms

CS - 3. Common Algorithms - 3.4. Cache - 3.4.2 LFU Cache

 

๐Ÿ’กLFU Cache is a data structure that stores key-value pairs. It has a fixed size and when it is full, it removes the least frequently used key-value pair. It is a variation of the LRU Cache and is used in many applications such as caching web pages, caching database queries, and caching images.

LFU ์บ์‹œ๋Š” ํ‚ค-๊ฐ’ ์Œ์„ ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ์œผ๋ฉฐ, ํฌ๊ธฐ๊ฐ€ ๊ฐ€๋“ ์ฐจ๋ฉด ์‚ฌ์šฉ ๋นˆ๋„๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ์€ ํ‚ค-๊ฐ’ ์Œ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. LRU ์บ์‹œ์˜ ๋ณ€ํ˜•์œผ๋กœ ์›น ํŽ˜์ด์ง€ ์บ์‹ฑ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์บ์‹ฑ, ์ด๋ฏธ์ง€ ์บ์‹ฑ ๋“ฑ ๋งŽ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

LFU(Least Frequently Used) ์บ์‹œ๋Š” ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ๊ฐ€์žฅ ์ ๊ฒŒ ์‚ฌ์šฉ๋œ ํ•ญ๋ชฉ์„ ์บ์‹œ์—์„œ ์ œ๊ฑฐํ•˜๋Š” ์ „๋žต์„ ์‚ฌ์šฉํ•˜๋Š” ์บ์‹œ์ž…๋‹ˆ๋‹ค. 

์ด๋Š” ์บ์‹œ์˜ ํฌ๊ธฐ๊ฐ€ ์ œํ•œ๋˜์–ด ์žˆ๊ณ , ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•  ๋•Œ ๊ณต๊ฐ„์ด ๋ถ€์กฑ

์ด ๊ฒฝ์šฐ, LFU ์บ์‹œ๋Š” ๊ฐ€์žฅ ์ ๊ฒŒ ์•ก์„ธ์Šค๋œ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐํ•˜์—ฌ ๊ณต๊ฐ„์„ ํ™•๋ณดํ•ฉ๋‹ˆ๋‹ค.

 

In Python

LFU ์บ์‹œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•ฉ๋‹ˆ๋‹ค๋งŒ, ์ด ๊ธ€์—์„œ๋Š” ํ•ด์‹œ๋งต๊ณผ ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

import collections
import heapq

class LFUCache:

    def __init__(self, capacity):
        self.capacity = capacity
        self.val_map = collections.defaultdict(int) # ๊ฐ’๊ณผ ๋นˆ๋„
        self.freq_map = collections.defaultdict(list) # ๊ฐ’๊ณผ ๋นˆ๋„ ๋ฆฌ์ŠคํŠธ
        self.min_freq = 0
        self.size = 0

    def get(self, key):
        if key in self.val_map:
            self.update(key)
            return self.val_map[key][0]
        else:
            return -1

    def put(self, key, value):
        if self.capacity == 0:
            return
        if key in self.val_map:
            self.update(key, value)
        else:
            if self.size == self.capacity:
                to_remove = self.freq_map[self.min_freq].pop(0)
                del self.val_map[to_remove]
                self.size -= 1
            self.val_map[key] = [value, 1]
            self.freq_map[1].append(key)
            self.min_freq = 1
            self.size += 1

    def update(self, key, new_val=None):
        value, freq = self.val_map[key]
        if new_val != None:
            value = new_val
        self.freq_map[freq].remove(key)
        if not self.freq_map[freq]:
            del self.freq_map[freq]
            if self.min_freq == freq:
                self.min_freq += 1
        self.val_map[key] = [value, freq+1]
        self.freq_map[freq+1].append(key)

์ด๋Ÿฐ์‹์œผ๋กœ LFU ์บ์‰ฌ๋ฅผ ๊ตฌ์„ฑํ•ด๋ณผ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ •๋ง ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ 1

LFU ์บ์‰ฌ์˜ ์šฉ๋Ÿ‰์„ 2๋กœ ์„ค์ •ํ•˜์˜€๊ธฐ์—

1='A', 2='B', 3='C', 4='D'๋ฅผ ์ฐจ๋ก€๋Œ€๋กœ ๋„ฃ์œผ๋ฉด 

๋‚˜์ค‘์— key 1๋กœ ๋ถ€๋ฅด๋ฉด -1 ๋กœ ์—†์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๊ทผ๋ฐ ์ด ์˜ˆ์‹œ์—๋Š” ์ตœ์‹ ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์™€์„œ ์˜ค๋ž˜๋œ ๊ฒƒ๋“ค์„ ์ œ๊ฑฐํ•˜๊ณ  ๊ทธ์ž๋ฆฌ์— ์ตœ์‹ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ ๊ฒƒ์ธ์ง€, ์ฆ‰ LRU ์ธ์ง€ LFU ์ธ์ง€ ํŒ๋‹จํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

 

์˜ˆ์‹œ 2

๊ทธ๋ž˜์„œ 1='A' ๋ฅผ ๊ฐ€์žฅ ์ฒ˜์Œ ๋งŽ์ด ๋„ฃ์€๋’ค์— 2='B', 3, 4 ๋ฅผ ํ•œ๋ฒˆ์”ฉ ๋„ฃ๊ณ  1์ด ์‚ญ์ œ ๋˜๋Š”์ง€ ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ๊ฐ’์€ ๊ฐ€์žฅ ๋‹ค์ˆ˜์ธ 1='A'๋Š” ๋‚จ์•„์žˆ๊ณ  2='B'๋Š” ์ œ๊ฑฐ, 3,4 ๊ฐ€ ์ €์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

ํ™œ์šฉ

LFU ์บ์‹œ๋Š” ํŠน์ • ํ•ญ๋ชฉ์˜ ์‚ฌ์šฉ ๋นˆ๋„๊ฐ€ ๋†’์€ ๊ฒฝ์šฐ์— ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ์ผ๋ถ€ ํ•ญ๋ชฉ์ด ์ž์ฃผ ์•ก์„ธ์Šค๋˜๊ณ , ๊ทธ ํ•ญ๋ชฉ๋“ค์ด ์บ์‹œ์—์„œ ์ œ๊ฑฐ๋˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ LFU ์บ์‹œ๋Š” ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

 

1. ์›น ํŽ˜์ด์ง€ ์บ์‹œ

- ํŠน์ • ์›น ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์š”์ฒญ์ด ๋นˆ๋ฒˆํ•  ๊ฒฝ์šฐ,

LFU ์บ์‹œ ๋ฅผ ์‚ฌ์šฉํ•ด ์›น ํŽ˜์ด์ง€๋ฅผ ์บ์‹œ์— ์œ ์ง€, ๋นˆ๋„๊ฐ€ ๋‚ฎ์€ ๋‹ค๋ฅธ ์›นํŽ˜์ด์ง€๋ฅผ ์บ์‹œ์—์„œ ์ œ๊ฑฐ.

์ด๋Ÿฐ์‹์œผ๋กœ ์ž์ฃผ ์•ก์„ธ์Šคํ•˜๋Š” ์›น ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ๊ฐ„์„ ์ค„์ž…๋‹ˆ๋‹ค.

 

2. DB ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ์บ์‹ฑ

- ์ผ๋ถ€ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์ž์ฃผ ์š”์ฒญ๋˜๋Š” ๊ฒฝ์šฐ,

์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•จ์œผ๋กœ์จ ๋น ๋ฅด๊ฒŒ ์ œ๊ณต.

 

3.ML ๋ชจ๋ธ ์˜ˆ์ธก ๊ฒฐ๊ณผ ์บ์‹ฑ

- ML ๋ชจ๋ธ์—์„œ ๋™์ผํ•œ ์ž…๋ ฅ์— ๋Œ€ํ•œ ์˜ˆ์ธก์„ ์ž์ฃผ ์ˆ˜ํ–‰ํ•  ๊ฒฝ์šฐ,

์˜ˆ์ธก ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•˜์—ฌ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•จ.

 

 

๋ฌธ์ œ์ ์€

"Recently" ์ตœ๊ทผ์„ฑ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

3.4.1์—์„œ LRU ์— ๋Œ€ํ•ด์„œ ๋‹ค๋ค˜์Šต๋‹ˆ๋‹ค. LRU ์บ์‹œ๋Š” ๊ฐ€์žฅ ์ตœ๊ทผ์— ์‚ฌ์šฉ๋œ ์บ์‹œ๋ฅผ ์ €์žฅํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. 

์ด์—๋ฐ˜ํ•ด 3.4.2 LFU ๋Š” ์˜ˆ์ „์— ์ž์ฃผ ์‚ฌ์šฉ๋˜์—ˆ์ง€๋งŒ ํ˜„์žฌ๋Š” ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•ญ๋ชฉ์ด LFU ์บ์‹œ์— ๊ณ„์† ์œ ์ง€๋  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฅผ ๋ณด์™„ํ•˜๊ธฐ์œ„ํ•ด LRU๊ณผ LFU๋ฅผ ๊ฒฐํ•ฉํ•œ LRU-LFU ์บ์‹œ ์ „๋žต์„ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

(  LRU-LFU ์บ์‹œ ์ „๋žต์€ ์ถ”ํ›„์— ๋‹ค๋ฃจ๊ธฐ)

728x90

'CS - Roadmap.sh > 3. Common Algorithms' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

3.5 Graph & 3.6 Tree  (0) 2024.01.27
3.4. Cache - 3.4.3 MFU Cache  (0) 2024.01.27
3.4. Cache - 3.4.1 LRU Cache  (2) 2024.01.25
3.3. Search - 3.3.2 Linear Search  (1) 2024.01.24
3.3. Search - 3.3.1 Binary Search  (0) 2024.01.23