Skip to content

Commit cf41d90

Browse files
committed
docs: update changelog
1 parent d7fe651 commit cf41d90

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed

Changelog.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
### [0.0.37] - unreleased
1+
### [0.0.37] - 2025/7/15
22

33
**breaking changes**:
44

5-
- Add event gist table, need migration
5+
- Add event gist table, need DB migration
66

77
**Added**
88

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env python3
2+
"""
3+
P95 Search Time Latency Demo Program
4+
5+
This program simulates search operations and computes the 95th percentile (p95) latency.
6+
It includes timing measurements, data generation, and statistical analysis.
7+
"""
8+
9+
import time
10+
import random
11+
import numpy as np
12+
import statistics
13+
from typing import List, Dict, Any
14+
from dataclasses import dataclass
15+
from concurrent.futures import ThreadPoolExecutor
16+
import json
17+
18+
19+
class LatencyAnalyzer:
20+
"""Analyzes search latencies and computes statistics."""
21+
22+
def __init__(self, results: list[float]):
23+
self.results: List[float] = results
24+
25+
def get_latencies(self) -> List[float]:
26+
"""Extract latency values from all results."""
27+
return self.results
28+
29+
def compute_statistics(self) -> Dict[str, float]:
30+
"""Compute comprehensive latency statistics."""
31+
if not self.results:
32+
return {}
33+
34+
latencies = self.get_latencies()
35+
36+
return {
37+
"count": len(latencies),
38+
"min_ms": min(latencies),
39+
"max_ms": max(latencies),
40+
"mean_ms": statistics.mean(latencies),
41+
"median_ms": statistics.median(latencies),
42+
"p50_ms": np.percentile(latencies, 50),
43+
"p90_ms": np.percentile(latencies, 90),
44+
"p95_ms": np.percentile(latencies, 95), # The main metric
45+
"p99_ms": np.percentile(latencies, 99),
46+
"std_dev_ms": statistics.stdev(latencies) if len(latencies) > 1 else 0,
47+
}
48+
49+
def print_statistics(self):
50+
"""Print formatted statistics to console."""
51+
stats = self.compute_statistics()
52+
if not stats:
53+
print("No results to analyze.")
54+
return
55+
56+
print("\n" + "=" * 50)
57+
print("SEARCH LATENCY ANALYSIS")
58+
print("=" * 50)
59+
print(f"Total searches: {stats['count']}")
60+
print(f"Min latency: {stats['min_ms']:.2f} ms")
61+
print(f"Max latency: {stats['max_ms']:.2f} ms")
62+
print(f"Mean latency: {stats['mean_ms']:.2f} ms")
63+
print(f"Median latency: {stats['median_ms']:.2f} ms")
64+
print("-" * 30)
65+
print("PERCENTILES:")
66+
print(f"P50 (median): {stats['p50_ms']:.2f} ms")
67+
print(f"P90: {stats['p90_ms']:.2f} ms")
68+
print(f"P95: {stats['p95_ms']:.2f} ms ⭐") # Highlighted
69+
print(f"P99: {stats['p99_ms']:.2f} ms")
70+
print("-" * 30)
71+
print(f"Standard deviation: {stats['std_dev_ms']:.2f} ms")
72+
print("=" * 50)
73+
74+
75+
with open("./fixture/memobase/results_0710_3000.json", "r") as f:
76+
data = json.load(f)
77+
latencies = []
78+
79+
80+
for k in data.keys():
81+
for d in data[k]:
82+
latencies.append(d["speaker_1_memory_time"] * 1000)
83+
latencies.append(d["speaker_2_memory_time"] * 1000)
84+
85+
86+
analyzer = LatencyAnalyzer(latencies)
87+
analyzer.print_statistics()

0 commit comments

Comments
 (0)