Back to Gitpod

Global CPU limiter design

components/ws-daemon/pkg/cpulimit/design.ipynb

2022.11.33.9 KB
Original Source

Global CPU limiter design

This notebook takes the data produced by the tests and displays it, aiming to provide insight into the behaviour of the algorithm. For one, we can gain confidence that the algorithm works as expected. We might also use this analysis to inform the parameter choice in production.

Setup

Prior to running any of the analysis, we need to do some setup work.

python
!pip install pandas matplotlib
python
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from IPython.display import display, HTML

matplotlib.rcParams['figure.figsize'] = (20, 10)
python
%%javascript
IPython.OutputArea.auto_scroll_threshold = 9999
python
def details(title, objs):
    display(HTML("<details><summary><h1>%s</h1></summary>%s</details>" % (title, [ o._repr_html_() for o in objs ])))

Analysis

The function below is our primary driver: it loads a CSV file produced by the tests and generates plots which aim to provide insight into the behaviour.

python
def analyse(fn):
    display(HTML("<h1>"+fn+"</h1>"))
    df = pd.read_csv(fn)
    df["t"] = df["t"] / (1000.0*1000.0*1000.0)
    df["dt"] = df['t'] - df.groupby("id")["t"].shift(1)
    df['usage_lag'] = df.groupby("id")["usage"].shift(1)
    df['usage_dt'] = df['usage'] - df['usage_lag']
    df['usage_fair'] = (df['bwavail'] * df["t"]) / len(df.groupby("id"))
    df['usage_avail'] = (df['bwavail'] * df["t"])
    df['usage_total'] = [ df['usage'][df['t'] == t].sum() for t in df['t'] ]
    df['desiredrate_diff'] = df['actualrate']-df['desiredrate']
    
    display(HTML("<h3>Per Client</h3>"))
    cs = pd.DataFrame()
    cs["desiredrate_diff"] = df.groupby("id")['desiredrate_diff'].mean()
    cs["total_usage"] = df.groupby("id")['usage'].sum()
    cs["limit_lo"] = df.groupby("id")['limit'].min()
    cs["limit_hi"] = df.groupby("id")['limit'].max()
    cs.columns = ['Desired Date Diff', 'Total Usage', 'Min Limit', 'Max Limit']
    display(cs)

    display(HTML("<h3>Bandwidth</h3>"))
    df["bwreq"].plot();
    df["bwused"].plot();
    df["bwavail"].plot();
    df["bwbreak"].plot();
    plt.legend();
    plt.title(fn+": bandwidth use");
    plt.show();
    
    display(HTML("<h3>Usage</h3>"))
    plt.figure();
    df.groupby("id")['usage'].plot();
    df['usage_fair'].plot();
    plt.legend();
    plt.title(fn+": usage");    
    plt.show();
    
    plt.figure();
    df['usage_avail'].plot();
    df['usage_total'].plot();
    plt.legend();
    plt.title(fn+": total usage");
    plt.show();
    
    pd.pivot_table(df.reset_index(),
               index='t', columns='id', values='usage_dt'
              ).plot(subplots=True, title=fn+": cycle usage", figsize=(20, 5*len(df.groupby("id"))));
    plt.show();

    pd.pivot_table(df.reset_index(),
               index='t', columns='id', values='usage'
              ).plot(subplots=True, title=fn+": total usage", figsize=(20, 5*len(df.groupby("id"))));
    plt.show();

    display(HTML("<h3>Rates / Consumption</h3>"))
    pd.pivot_table(df.reset_index(),
               index='t', columns='id', values='desiredrate'
              ).plot(subplots=True, title=fn+": desired rate", figsize=(20, 5*len(df.groupby("id"))));
    plt.show();

    pd.pivot_table(df.reset_index(),
               index='t', columns='id', values='desiredrate_diff'
              ).plot(subplots=True, title=fn+": desired rate diff", figsize=(20, 5*len(df.groupby("id"))));
    plt.show();
    
    pd.pivot_table(df.reset_index(),
               index='t', columns='id', values='limit'
              ).plot(subplots=True, title=fn+": limit", figsize=(20, 5*len(df.groupby("id"))));
    plt.show();

Test Cases

The cell below will run all tests and run the analyse function on their result.

python
!go test -v .
python
from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(".") if isfile(join(".", f)) and f.startswith("sim_") and f.endswith(".csv")]

for f in onlyfiles:
    analyse(f)