forked from course/hse-2026
1.5 MiB
1.5 MiB
In [1]:
from IPython.display import Image
Image(filename='media/balancers.png') Out [1]:
In [2]:
import json
import matplotlib.pyplot as plt
import numpy as np
import subprocess
from pathlib import Path
# Сначала соберите образ по инструкции в readme.md.
# Для локальной сборки и запуска через Cargo задайте False.
USE_DOCKER = True
DOCKER_IMAGE = 'distsys-load-balancing-lab:local'
def run_experiment(name, n_balancers=1, settings=None, balancers=None,
sync_interval=0.01, seed=123):
settings = list(settings or [])
if balancers is None:
balancers = ['Hash', 'Random', 'RoundRobin', 'LeastLoaded']
config_path = Path('.tmp-config.json')
result_path = Path('.tmp-result.txt')
configs = [{'balancer': balancer, 'n_balancers': n_balancers,
'sync_interval': sync_interval} for balancer in balancers]
config_path.write_text(json.dumps(configs), encoding='utf-8')
args = ['--servers', '100', '--seed', str(seed), '--dump', result_path.name,
'--config', config_path.name, *settings]
try:
if USE_DOCKER:
command = ['docker', 'run', '--rm', '--mount',
f'type=bind,source={Path.cwd()},target=/lab',
DOCKER_IMAGE, *args]
else:
command = ['cargo', 'run', '--locked', '--release', '--', *args]
subprocess.run(command, check=True)
results = result_path.read_text(encoding='utf-8').splitlines()
finally:
config_path.unlink(missing_ok=True)
result_path.unlink(missing_ok=True)
plt.figure(figsize=(12, 5))
plt.title(name)
plt.yscale('log')
plt.ylabel('p99 времени ответа, с (окно 60 с)')
plt.xlabel('Начало окна t, с')
for i in range(0, len(results), 3):
times = np.fromstring(results[i + 1], sep=',')
response_times = np.fromstring(results[i + 2], sep=',')
plt.plot(times, response_times, label=results[i])
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()
In [3]:
run_experiment('balanced workload')In [4]:
run_experiment('balanced workload (10 senders)', settings=['--senders', '10'])In [5]:
run_experiment('skewed workload', settings=['--preset', 'skewed'])In [6]:
run_experiment('balanced workload (different servers)', settings=['--different-servers'])In [7]:
run_experiment('balanced workload (1 balancer, updates every 5 s)', sync_interval=5)In [8]:
run_experiment('balanced workload (5 balancers)', n_balancers=5, sync_interval=5)In [12]:
exp3_balancers = ['Hash', 'Random', 'RoundRobin', 'LeastLoaded', 'PowerOfK[k=2]']In [13]:
run_experiment('power of two choices', n_balancers=5, sync_interval=5, balancers=exp3_balancers)In [14]:
run_experiment('power of K choices', n_balancers=5, sync_interval=5, balancers=['PowerOfK[k=2]', 'PowerOfK[k=3]', 'PowerOfK[k=5]', 'PowerOfK[k=10]'])In [15]:
run_experiment('do updates matter?', n_balancers=5, sync_interval=5, balancers=['PowerOfK[k=2]', 'PowerOfKWithUpdates[k=2]'])In [16]:
run_experiment('power of two choices', n_balancers=5, sync_interval=5, balancers=exp3_balancers, settings=['--different-servers'])In [11]:
run_experiment('correlated selectors (5 balancers)', n_balancers=5, sync_interval=5,
settings=['--correlated-selectors'])