Загрузка данных
import random
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
class Request:
def __init__(self, req_id, arrival_time, req_type, service_time):
self.id = req_id
self.arrival_time = arrival_time
self.req_type = req_type
self.service_time = service_time
self.start_service = 0.0
self.end_service = 0.0
def simulate_storage(lam, mu_up, mu_down, n_servers, upload_prob, sim_time, warmup, seed=42):
random.seed(seed)
req_id = 0
queue = []
servers = [None] * n_servers
completed = []
events = []
next_arrival = random.expovariate(lam)
events.append((next_arrival, 'arrival', None))
while events:
events.sort(key=lambda x: x[0])
current_time, ev_type, ev_data = events.pop(0)
if current_time > sim_time:
break
if ev_type == 'arrival':
if random.random() < upload_prob:
req_type = 'upload'
svc = random.expovariate(mu_up)
else:
req_type = 'download'
svc = random.expovariate(mu_down)
req = Request(req_id, current_time, req_type, svc)
req_id += 1
free_server = None
for i, s in enumerate(servers):
if s is None or s[0] <= current_time:
free_server = i
break
if free_server is not None:
req.start_service = current_time
req.end_service = current_time + svc
servers[free_server] = (req.end_service, req)
events.append((req.end_service, 'departure', (free_server, req)))
else:
queue.append(req)
next_arr = current_time + random.expovariate(lam)
if next_arr < sim_time:
events.append((next_arr, 'arrival', None))
elif ev_type == 'departure':
server_idx, req = ev_data
if current_time > warmup:
completed.append(req)
if queue:
next_req = queue.pop(0)
next_req.start_service = current_time
next_req.end_service = current_time + next_req.service_time
servers[server_idx] = (next_req.end_service, next_req)
events.append((next_req.end_service, 'departure', (server_idx, next_req)))
else:
servers[server_idx] = None
if not completed:
return None
wait_times = [r.start_service - r.arrival_time for r in completed]
service_times = [r.service_time for r in completed]
resp_times = [r.end_service - r.arrival_time for r in completed]
rho = lam / (n_servers * (upload_prob * mu_up + (1 - upload_prob) * mu_down))
return {
'lam': lam,
'mean_wait': np.mean(wait_times),
'mean_service': np.mean(service_times),
'mean_response': np.mean(resp_times),
'mean_queue': np.mean(wait_times) * lam,
'rho': min(rho, 0.999)
}
MU_UPLOAD = 0.5
MU_DOWNLOAD = 2.0
UPLOAD_PROB = 0.35
SIM_TIME = 5000
WARMUP = 500
N_RUNS = 5
LAMBDAS = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4]
SERVER_COUNTS = [1, 2, 3, 4]
results = {}
ci = {}
for c in SERVER_COUNTS:
results[c] = []
ci[c] = []
for lam in LAMBDAS:
runs = []
for run in range(N_RUNS):
res = simulate_storage(lam, MU_UPLOAD, MU_DOWNLOAD, c, UPLOAD_PROB, SIM_TIME, WARMUP, seed=run*100)
if res:
runs.append(res)
if runs:
resp_vals = [r['mean_response'] for r in runs]
wait_vals = [r['mean_wait'] for r in runs]
mean_resp = np.mean(resp_vals)
mean_wait = np.mean(wait_vals)
if len(runs) > 1:
interval_resp = stats.t.interval(0.95, df=len(runs)-1, loc=mean_resp, scale=stats.sem(resp_vals))
interval_wait = stats.t.interval(0.95, df=len(runs)-1, loc=mean_wait, scale=stats.sem(wait_vals))
else:
interval_resp = (mean_resp, mean_resp)
interval_wait = (mean_wait, mean_wait)
avg = {
'lam': lam,
'mean_wait': mean_wait,
'mean_service': np.mean([r['mean_service'] for r in runs]),
'mean_response': mean_resp,
'mean_queue': np.mean([r['mean_queue'] for r in runs]),
'rho': np.mean([r['rho'] for r in runs]),
'ci_resp_lo': interval_resp[0],
'ci_resp_hi': interval_resp[1],
'ci_wait_lo': interval_wait[0],
'ci_wait_hi': interval_wait[1]
}
results[c].append(avg)
print("-" * 75)
print(" СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ (2 сервера)")
print("-" * 75)
print(f"{'лямбда':<8} {'Ожидание':<10} {'Обслуж.':<10} {'Ответ':<10} {'Очередь':<9} {'Загрузка':<8} {'95% ДИ ответа'}")
print("-" * 75)
for r in results[2]:
print(f"{r['lam']:<8.1f} {r['mean_wait']:<10.3f} {r['mean_service']:<10.3f} "
f"{r['mean_response']:<10.3f} {r['mean_queue']:<9.2f} {r['rho']:<8.1%} "
f"[{r['ci_resp_lo']:.3f}, {r['ci_resp_hi']:.3f}]")
print("-" * 75)
print("\n" + "-" * 55)
print(" СРАВНЕНИЕ ЧИСЛА СЕРВЕРОВ при λ = 1.0")
print("-" * 55)
print(f"{'Серверов':<10} {'Ожидание':<12} {'Ответ':<12} {'Очередь':<10} {'Загрузка'}")
print("-" * 55)
for c in SERVER_COUNTS:
for r in results[c]:
if abs(r['lam'] - 1.0) < 0.01:
print(f"{c:<10} {r['mean_wait']:<12.3f} {r['mean_response']:<12.3f} {r['mean_queue']:<10.2f} {r['rho']:.1%}")
print("-" * 55)
print("\n[Анализ точек деградации (>80% нагрузки)]")
for c in SERVER_COUNTS:
degraded = False
for r in results[c]:
if r['rho'] > 0.8:
print(f" Серверов: {c} -> деградация при лямбда = {r['lam']:.1f} (Загрузка: {r['rho']:.1%})")
degraded = True
break
if not degraded:
print(f" Серверов: {c} -> система стабильна на всех протестированных частотах")
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle("Имитационная модель облачного хранилища", fontsize=14)
colors = ['blue', 'green', 'orange', 'red']
labels = ['1 сервер', '2 сервера', '3 сервера', '4 сервера']
ax1 = axes[0, 0]
ax1.set_title("Время ответа vs Интенсивность")
for i, c in enumerate(SERVER_COUNTS):
x = [r['lam'] for r in results[c]]
y = [r['mean_response'] for r in results[c]]
ax1.plot(x, y, marker='o', color=colors[i], label=labels[i])
ax1.set_xlabel("Интенсивность запросов λ (зап/сек)")
ax1.set_ylabel("Среднее время ответа (сек)")
ax1.legend()
ax1.grid(True)
ax2 = axes[0, 1]
ax2.set_title("Время ожидания в очереди")
for i, c in enumerate(SERVER_COUNTS):
x = [r['lam'] for r in results[c]]
y = [r['mean_wait'] for r in results[c]]
ax2.plot(x, y, marker='o', color=colors[i], label=labels[i])
ax2.set_xlabel("Интенсивность запросов λ (зап/сек)")
ax2.set_ylabel("Среднее время ожидания (сек)")
ax2.legend()
ax2.grid(True)
ax3 = axes[1, 0]
ax3.set_title("Длина очереди")
for i, c in enumerate(SERVER_COUNTS):
x = [r['lam'] for r in results[c]]
y = [r['mean_queue'] for r in results[c]]
ax3.plot(x, y, marker='o', color=colors[i], label=labels[i])
ax3.set_xlabel("Интенсивность запросов λ (зап/сек)")
ax3.set_ylabel("Средняя длина очереди (запросов)")
ax3.legend()
ax3.grid(True)
ax4 = axes[1, 1]
ax4.set_title("Загрузка серверов")
for i, c in enumerate(SERVER_COUNTS):
x = [r['lam'] for r in results[c]]
y = [r['rho'] * 100 for r in results[c]]
ax4.plot(x, y, marker='o', color=colors[i], label=labels[i])
ax4.axhline(y=80, color='red', linestyle='--', label='Порог деградации (80%)')
ax4.set_xlabel("Интенсивность запросов λ (зап/сек)")
ax4.set_ylabel("Загрузка серверов (%)")
ax4.legend()
ax4.grid(True)
plt.tight_layout()
plt.savefig("graphs.png", dpi=150)
plt.show()
print("\nГрафики сохранены в graphs.png")