Skip to content

Instantly share code, notes, and snippets.

@juandspy
Last active May 23, 2023 07:01
Show Gist options
  • Save juandspy/2b109646f81d5c8a3c3727d73415da17 to your computer and use it in GitHub Desktop.
Save juandspy/2b109646f81d5c8a3c3727d73415da17 to your computer and use it in GitHub Desktop.
CCXDEV-11016

CCXDEV-11016

A benchmark of LRU cache for storing upgrade risks responses.

I'm caching a response per cluster with N alerts and M focs, being N and M a random value between 0 and 10.

Below you can see a plot of the memory usage given the number of clusters in cache.

It's also possible to use mprof and run:

N_CLUSTERS=35000 mprof run python test.py
mprof plot
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv("results.csv")
plt.plot(df.n_clusters, df.max_mem/1e6, 'o-')
plt.xlabel("N clusters")
plt.ylabel("max memory used (MB)")
plt.savefig("test.png")
n_clusters current_mem max_mem
0 0 96
100 630598 630662
200 1167555 1167619
300 1714210 1714274
400 2364305 2364369
500 3013997 3014061
600 3552418 3552482
700 4298535 4298599
800 4720230 4720294
900 5422576 5422640
1000 6003063 6003127
2000 11979691 11979755
3000 18094088 18094152
4000 24018522 24018586
5000 30004447 30004511
6000 36343983 36344047
7000 41910551 41910615
8000 47959719 47959783
9000 53960104 53960168
10000 60483101 60483165
12000 72579351 72579415
14000 84010147 84010211
16000 97033424 97033488
18000 108304061 108304125
20000 120799091 120799155
22000 132924810 132924874
24000 145309354 145309418
26000 158006858 158006922
28000 169157906 169157970
30000 181647030 181647094
32000 193527703 193527767
34000 205718352 205718416
36000 217097529 217097593
38000 229259677 229259741
40000 241537831 241537895
42000 253296182 253296246
44000 265653054 265653118
46000 279009385 279009449
48000 290873554 290873618
50000 302612987 302613051
from functools import lru_cache, wraps
from datetime import datetime, timedelta
import random
import string
import tracemalloc
import os
TTL_SECONDS = 300
LRU_MAXENTRIES = None
MIN_ALERTS, MIN_FOCS = 0, 0
MAX_ALERTS, MAX_FOCS = 10, 10
def timed_lru_cache(seconds: int, maxsize: int = 128):
def wrapper_cache(func):
func = lru_cache(maxsize=maxsize)(func)
func.lifetime = timedelta(seconds=seconds)
func.expiration = datetime.utcnow() + func.lifetime
@wraps(func)
def wrapped_func(*args, **kwargs):
if datetime.utcnow() >= func.expiration:
func.cache_clear()
func.expiration = datetime.utcnow() + func.lifetime
return func(*args, **kwargs)
return wrapped_func
return wrapper_cache
@timed_lru_cache(seconds=TTL_SECONDS, maxsize=LRU_MAXENTRIES)
def get_result(cluster_id):
return generate_random_result()
def generate_random_result():
n_alerts = random.randint(MIN_ALERTS, MAX_ALERTS)
n_focs = random.randint(MIN_FOCS, MAX_FOCS)
alerts = []
for _ in range(n_alerts):
alert_name = get_random_string(20)
namespace = get_random_string(10)
alerts.append(
{
"name": alert_name,
"namespace": namespace,
"severity": "info",
"url": f"https://my-cluster.com/monitoring/alerts?orderBy=asc&sortBy=Severity&alert-name={alert_name}"
}
)
focs = []
for _ in range(n_focs):
foc_name = get_random_string(20)
alerts.append(
{
"condition": "Failing",
"name": foc_name,
"reason": "AsExpected",
"url": f"https://my-cluster.com/k8s/cluster/config.openshift.io~v1~ClusterOperator/{foc_name}"
}
)
return {
"meta": {
"last_checked_at": "2023-05-22T13:03:41.299Z"
},
"status": "ok",
"upgrade_recommendation": {
"upgrade_recommended": random.randint(0,1),
"upgrade_risks_predictors": {
"alerts": alerts,
"operator_conditions": focs
}
}
}
letters = string.ascii_lowercase
def get_random_string(length):
return ''.join(random.choice(letters) for _ in range(length))
if __name__ == "__main__":
import uuid
N_CLUSTERS = int(os.environ["N_CLUSTERS"])
clusters = [uuid.uuid4() for _ in range(N_CLUSTERS)]
# starting the monitoring
tracemalloc.start()
for cluster in range(N_CLUSTERS):
get_result(cluster_id=cluster)
# displaying the memory
current_mem, max_mem = tracemalloc.get_traced_memory()
print(f"{N_CLUSTERS},{current_mem},{max_mem}")
# stopping the library
tracemalloc.stop()
N_CLUSTERS=10
echo "n_clusters,current_mem,max_mem" > results.csv
for N_CLUSTERS in {0..1000..100}
do
N_CLUSTERS="$N_CLUSTERS" python test.py >> results.csv
done
for N_CLUSTERS in {2000..10000..1000}
do
N_CLUSTERS="$N_CLUSTERS" python test.py >> results.csv
done
for N_CLUSTERS in {12000..50000..2000}
do
N_CLUSTERS="$N_CLUSTERS" python test.py >> results.csv
done
python plot.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment