mirror of
https://github.com/ltcptgeneral/cs239-caching.git
synced 2025-04-01 20:33:26 +00:00
Seive Testing
This commit is contained in:
parent
f475991f50
commit
a276151e0c
17
app/cache/eviction_seive.py
vendored
17
app/cache/eviction_seive.py
vendored
@ -33,20 +33,17 @@ class SeiveCache(Cache):
|
||||
if key in self.cache:
|
||||
node = self.cache[key]
|
||||
node.visited = True
|
||||
print(f"GET {key}: {node.value}")
|
||||
self.print_cache_state()
|
||||
#self.print_cache_state()
|
||||
return node.value
|
||||
print(f"GET {key}: MISS")
|
||||
self.print_cache_state()
|
||||
return None
|
||||
|
||||
def put(self, key: str, val: str) -> bool:
|
||||
print(f"PUT {key}: {val}")
|
||||
if key in self.cache:
|
||||
node = self.cache[key]
|
||||
node.value = val
|
||||
node.visited = True
|
||||
self.print_cache_state()
|
||||
#self.print_cache_state()
|
||||
return False # No eviction needed
|
||||
|
||||
new_node = Node(key, val)
|
||||
@ -66,11 +63,10 @@ class SeiveCache(Cache):
|
||||
self.cache[key] = new_node
|
||||
if not self.hand:
|
||||
self.hand = self.head
|
||||
self.print_cache_state()
|
||||
#self.print_cache_state()
|
||||
return False
|
||||
|
||||
def invalidate(self, key: str) -> bool:
|
||||
print(f"INVALIDATE {key}")
|
||||
if key in self.cache:
|
||||
node = self.cache.pop(key)
|
||||
if node == self.head:
|
||||
@ -81,16 +77,14 @@ class SeiveCache(Cache):
|
||||
node.next.prev = node.prev
|
||||
if node.prev:
|
||||
node.prev.next = node.next
|
||||
self.print_cache_state()
|
||||
#self.print_cache_state()
|
||||
return True
|
||||
print("INVALIDATE FAILED: Key not found")
|
||||
return False
|
||||
|
||||
def next_hand(self):
|
||||
self.hand = self.hand.next if self.hand.next else self.head
|
||||
|
||||
def evict(self):
|
||||
print("EVICTION START")
|
||||
while self.hand.visited:
|
||||
self.hand.visited = False
|
||||
self.next_hand()
|
||||
@ -107,8 +101,7 @@ class SeiveCache(Cache):
|
||||
obj_to_evict.prev.next = obj_to_evict.next
|
||||
|
||||
del self.cache[obj_to_evict.key]
|
||||
print(f"EVICTED {obj_to_evict.key}")
|
||||
self.print_cache_state()
|
||||
#self.print_cache_state()
|
||||
|
||||
# Basic API demo for future testing
|
||||
if __name__ == "__main__":
|
||||
|
76
tests/random_readwrite.py
Normal file
76
tests/random_readwrite.py
Normal file
@ -0,0 +1,76 @@
|
||||
import requests
|
||||
import random
|
||||
import json
|
||||
from tqdm import tqdm
|
||||
import time
|
||||
|
||||
baseurl = "http://localhost:8000"
|
||||
|
||||
endpoints = {
|
||||
"/user/{user_id}": 0.8, # 80% read operations
|
||||
"/update_user/?user_id={user_id}&name=Test&followers=100&bio=Updated&posts=Updated": 0.2 # 20% write operations
|
||||
}
|
||||
|
||||
# Fetch all user IDs
|
||||
user_ids = json.loads(requests.get(baseurl + "/users").content)["ids"]
|
||||
|
||||
random.seed(0)
|
||||
|
||||
def generate_random():
|
||||
"""Randomly generate a read or write request, favoring cache hits."""
|
||||
endpoint = random.choices(list(endpoints.keys()), list(endpoints.values()))[0]
|
||||
if endpoint == "/user/{user_id}":
|
||||
# Favor frequently accessed user IDs to increase hit ratio
|
||||
if len(user_ids) > 0:
|
||||
# Sample from a subset of user IDs to simulate frequent access
|
||||
frequent_users = user_ids[:int(len(user_ids) * 0.2)] # 20% frequent users
|
||||
random_user = str(random.choice(frequent_users)) if random.random() < 0.7 else str(random.choice(user_ids))
|
||||
else:
|
||||
random_user = str(random.choice(user_ids))
|
||||
else:
|
||||
random_user = str(random.choice(user_ids))
|
||||
return baseurl + endpoint.replace("{user_id}", random_user)
|
||||
|
||||
times = []
|
||||
hits = []
|
||||
|
||||
# Warm-up phase
|
||||
# for _ in tqdm(range(1000)):
|
||||
# url = generate_random()
|
||||
# requests.get(url)
|
||||
|
||||
# Main testing phase
|
||||
start = time.time()
|
||||
for i in tqdm(range(10000)):
|
||||
url = generate_random()
|
||||
response = requests.get(url)
|
||||
|
||||
try:
|
||||
content = json.loads(response.content)
|
||||
|
||||
if "time_ms" in content: # Only process if "time_ms" exists
|
||||
times.append(content["time_ms"])
|
||||
hits.append(content["source"] == "cache")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
print(f"Error decoding JSON: {response.content}")
|
||||
exit(1)
|
||||
except KeyError:
|
||||
print(f"Unexpected response format: {content}")
|
||||
exit(1)
|
||||
|
||||
end = time.time()
|
||||
|
||||
hits_count = sum(hits)
|
||||
miss_count = len(hits) - hits_count
|
||||
|
||||
hits_time = sum(times[i] for i in range(len(times)) if hits[i])
|
||||
miss_time = sum(times[i] for i in range(len(times)) if not hits[i])
|
||||
total_time = hits_time + miss_time
|
||||
|
||||
print(f"hits: {hits_count} misses: {miss_count} ratio: {hits_count / (hits_count + miss_count):.2f}")
|
||||
print(f"average response time (ms) : {total_time / len(times):.2f}")
|
||||
print(f"average cache hit response time (ms) : {hits_time / hits_count if hits_count else 0:.2f}")
|
||||
print(f"average cache miss response time (ms): {miss_time / miss_count if miss_count else 0:.2f}")
|
||||
print(f"cache throughput (requests / ms) : {len(times) / total_time:.2f}")
|
||||
print(f"real throughput (requests / ms) : {len(times) / (end - start) / 1000:.2f}")
|
Loading…
x
Reference in New Issue
Block a user