# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # How does the system perform?
#
# This notebook will look the following:
#
# * How long do users wait to answer questions?
# * How long do users wait for the network to respond?
# * How many simultaneous users do we have?
# * How many simultaneous requests are served?
#

# %matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
plt.style.use('seaborn')

import caption_contest_data as ccd
responses = ccd.responses(577)
print("Number of responses:", len(responses))
responses.columns

responses.iloc[0]

# ## Response time 
# How long does the average user wait before providing a respose? That data is recorded in the responses and we can plot a histogram. 
#
# We know that waiting for something to happen is characterized by an [exponential random variable]. Can we fit the PDF of an exponential random variable to the reponse time we see? 
#
# [exponential random variable]:https://en.wikipedia.org/wiki/Exponential_distribution

most_responses = (responses['response_time'] >= 0) & (responses['response_time'] <= 15) 
df = responses[most_responses].copy()

df['response_time'].plot.hist(bins=50, normed=True)
plt.xlabel('Respond time (seconds)')
plt.show()

users = df.participant_uid.unique()
num_users = len(users)
print(num_users, "total users")

# ## Network delay
# How long does our system take to respond?

most_delays = (responses['network_delay'] >= 0) & (responses['network_delay'] <= 2)
df = responses[most_delays]

plt.style.use('seaborn-talk')
df['network_delay'].plot.hist(bins=100)
plt.title('Network delay')
plt.show()

# ## Concurrent users
# How many users hit our system in a one second period?

import datetime
df = responses.copy()
contest_start = df['timestamp_query_generated'].min()
contest_end = df['timestamp_query_generated'].max()
df = df.sort_values(by='timestamp_query_generated')
delta = datetime.timedelta(seconds=1)
df['seconds_elapsed'] = df['timestamp_query_generated'] - contest_start
df['seconds_elapsed'] = df.apply(lambda row: row['seconds_elapsed'].total_seconds(), axis=1)

total_seconds = (contest_end - contest_start).total_seconds()


def find_users_in_range(start, k, total, resolution=None, times=None, participants=None):
    if k % 1000 == 0:
        print(k / total, "fraction")
    end = start + resolution
    n_questions = (times >= start) & (times < end)
    n_users = participants[n_questions].nunique()
    
    return {'questions served': n_questions.sum(), 'n_users': n_users, 'start': start, 'end': end}


# +
from joblib import Parallel, delayed

times = df['seconds_elapsed'].values.astype("float32")
participants = df["participant_uid"].apply(hash)

measure = np.linspace(times.min(), times.max(), num=20_000)
print(np.diff(measure).min())
resolution = 5  # seconds
print(f"Launching {len(measure)//1000}k jobs...")
print(f"Resolution: {resolution} seconds")
# -

kwargs = {"resolution": resolution, "times": times, "participants": participants}
stats = []
for k, m in enumerate(measure):
    stat = find_users_in_range(m, k, len(measure), **kwargs)
    stats.append(stat)

print(stats[:3])

stats = pd.DataFrame(stats)
stats["minutes"] = stats["start"] / 60
stats["hours"] = stats["minutes"] / 60
stats["days"] = stats["hours"] / 24

stats.sample(n=5)

max_rate = stats['questions served'].max()
print(f'Questions served per {resolution} seconds: {max_rate}')

# +
import matplotlib.pyplot as plt

w = 4.5
fig, axs = plt.subplots(ncols=2, figsize=(2 * w, 1*w))
ax = stats.plot(x="days", y="questions served", ax=axs[0])
ax.set_title(f"Questions served in {resolution} seconds")
ax.legend_.remove()

ax = stats.plot(x="days", y="n_users", ax=axs[1])
ax.set_title("Concurrent users")
ax.legend_.remove()

# +
idx = (97.5<= stats.hours) & (stats.hours <= 104)


w = 4.5
fig, axs = plt.subplots(ncols=2, figsize=(2 * w, 1*w))
ax = stats[idx].plot(x="days", y="questions served", ax=axs[0])
ax.set_title(f"Questions served in {resolution} seconds")
ax.legend_.remove()

ax = stats[idx].plot(x="days", y="n_users", ax=axs[1])
ax.set_title("Concurrent users")
ax.legend_.remove()
# -



StarcoderdataJupyterScriptsDedupFiltered