예제 #1
0
class Indicator(object):
    def __init__(self):
        self.cms = CMS(5000)
        self.hinter_sum = 0
        self.hinter_count = 0
        self.freqs = Counter()  # Alternatively use SpaceSaving

    def record(self, key):
        hint = self.cms.frequancy(key)
        self.hinter_sum += hint
        self.hinter_count += 1
        self.cms.increment(key)
        self.freqs[key] += 1

    def get_hint(self):
        return self.hinter_sum / self.hinter_count

    def est_skew(self):
        top_k = [(i, log(k[1]))
                 for i, k in zip(range(1, 71), self.freqs.most_common(70))]
        return -stats.linregress(top_k)[0]

    def get_indicator(self):
        skew = self.est_skew()
        return (self.get_hint() * ((1 - skew**3) if skew < 1 else 0)) / 15.0

    def reset(self):
        self.hinter_sum = 0
        self.hinter_count = 0
        self.freqs.clear()
예제 #2
0
class WTinyLFU(Policy):
    def __init__(self, maximum_size, window_percentage=1):
        super().__init__(maximum_size)

        self.data = {}

        self.cms = CMS(maximum_size)

        self.sentinel_window = Node()  # LRU
        self.sentinel_probation = Node()  # SLRU
        self.sentinel_protected = Node()  # SLRU

        self.max_window_size = (self.maximum_size * window_percentage) // 100
        max_main = self.maximum_size - self.max_window_size
        self.max_protected = max_main * 4 // 5

        self.size_window = 0
        self.size_protected = 0

    def record(self, key, size=1):
        self.cms.increment(key)
        node = self.data.get(key)
        if not node:
            self.misses += 1
            new_node = Node(key, Node.Status.Window)
            new_node.append_to_tail(self.sentinel_window)
            self.data[key] = new_node
            self.size_window += 1
            if self.size_window > self.max_window_size:
                self.evict()
            return False
        else:
            self.hits += 1
            node.remove()
            if node.status == Node.Status.Window:
                node.append_to_tail(self.sentinel_window)
            elif node.status == Node.Status.Probation:
                node.status = Node.Status.Protected
                node.append_to_tail(self.sentinel_protected)
                self.size_protected += 1
                self.demote_protected()
            elif node.status == Node.Status.Protected:
                node.append_to_tail(self.sentinel_protected)
            return True

    def demote_protected(self):
        if self.size_protected > self.max_protected:
            demote = self.sentinel_protected.next_node
            demote.remove()
            demote.status = Node.Status.Probation
            demote.append_to_tail(self.sentinel_probation)
            self.size_protected -= 1

    def evict(self):
        candidate = self.sentinel_window.next_node
        candidate.remove()
        self.size_window -= 1
        candidate.status = Node.Status.Probation
        candidate.append_to_tail(self.sentinel_probation)
        if len(self.data) > self.maximum_size:
            victim = self.sentinel_probation.next_node
            evicted = victim if self.cms.frequancy(
                candidate.data) > self.cms.frequancy(
                    victim.data) else candidate
            del self.data[evicted.data]
            evicted.remove()