Latency percentile bands
Azure Functions 2021 invocation trace (real data, no fallback)
Example from the compendium of canonical charts
Python Code
"""Latency percentile bands — Azure Functions 2021 invocation trace (real data, no fallback)."""
import pandas as pd
import plotly.graph_objects as go
import requests, warnings, subprocess, tempfile, os
# Azure Functions "two weeks of January 2021" per-invocation trace.
# Columns: app, func, end_timestamp (s), duration (s). ~2M rows, RAR5-compressed.
RAR_URL = "https://raw.githubusercontent.com/Azure/AzurePublicDataset/master/data/AzureFunctionsInvocationTraceForTwoWeeksJan2021.rar"
def load_trace():
"""Download + extract the RAR5 trace with `unar`, return the invocation DataFrame."""
warnings.filterwarnings("ignore")
requests.packages.urllib3.disable_warnings()
if not subprocess.run(["which", "unar"], capture_output=True).stdout.strip():
raise RuntimeError("`unar` not found — install it (brew install unar) to extract the RAR5 trace")
with tempfile.TemporaryDirectory() as tmpdir:
rar_path = os.path.join(tmpdir, "trace.rar")
print(" downloading Azure Functions 2021 trace …")
r = requests.get(RAR_URL, verify=False, timeout=180, stream=True)
r.raise_for_status()
with open(rar_path, "wb") as f:
for chunk in r.iter_content(1 << 20):
f.write(chunk)
print(f" downloaded {os.path.getsize(rar_path)/1e6:.1f}MB, extracting …")
result = subprocess.run(["unar", "-o", tmpdir, rar_path], capture_output=True, timeout=180)
if result.returncode != 0:
raise RuntimeError(f"unar failed: {result.stderr.decode()[:200]}")
# The archive holds a single comma-delimited .txt (not .csv).
data_files = [f for f in os.listdir(tmpdir) if f.endswith((".txt", ".csv"))]
if not data_files:
raise RuntimeError(f"no data file in archive: {os.listdir(tmpdir)}")
return pd.read_csv(os.path.join(tmpdir, data_files[0]))
def generate():
print("building latency percentile bands …")
df = load_trace()
# Bucket invocations into hours of the two-week trace, take per-hour percentiles.
df["hour"] = (df["end_timestamp"] // 3600).astype(int)
bands = df.groupby("hour")["duration"].quantile([0.5, 0.9, 0.99]).unstack()
bands.columns = ["p50", "p90", "p99"]
bands = bands.reset_index()
x = bands["hour"]
fig = go.Figure()
fig.add_trace(go.Scatter(
x=x, y=bands["p99"], mode="lines", name="p99",
line=dict(color=PINK, width=1.5),
hovertemplate="Hour %{x}<br>p99 = %{y:.3f}s<extra></extra>",
))
fig.add_trace(go.Scatter(
x=x, y=bands["p90"], mode="lines", name="p90",
line=dict(color=TEAL, width=1.5),
fill="tonexty", fillcolor="rgba(82,179,208,0.15)",
hovertemplate="Hour %{x}<br>p90 = %{y:.3f}s<extra></extra>",
))
fig.add_trace(go.Scatter(
x=x, y=bands["p50"], mode="lines", name="p50",
line=dict(color=VIOLET, width=2),
fill="tonexty", fillcolor="rgba(132,94,238,0.15)",
hovertemplate="Hour %{x}<br>p50 = %{y:.3f}s<extra></extra>",
))
fig.update_layout(
title=dict(text="Serverless Latency Percentile Bands — Azure Functions 2021", x=0.5),
xaxis=dict(title="Hour of trace"),
yaxis=dict(title="Duration (s)", type="log"),
legend=dict(orientation="h", y=1.08),
margin=dict(t=60, b=50, l=70, r=40),
height=460,
)
return fig
if __name__ == "__main__":
generate()
Made with Plotly