Rework benchmark: cold-cache 50/50 speed, ua-parser native backends, SVG throughput plot
This commit is contained in:
+7
-6
@@ -34,6 +34,7 @@ from user_agent_parser import parse as uap_parse
|
||||
from user_agents import parse as uas_parse
|
||||
|
||||
from uarite import uaparse
|
||||
from uarite.core import _parse_client
|
||||
|
||||
ALL_DOMAINS = (
|
||||
ua_parser.Domain.USER_AGENT | ua_parser.Domain.OS | ua_parser.Domain.DEVICE
|
||||
@@ -244,7 +245,7 @@ def bench_realistic():
|
||||
f" with 2000 mostly-unique bots)"
|
||||
)
|
||||
for name, fn in (
|
||||
("ua-parser (pure)", uap_pure),
|
||||
("ua-parser", uap_pure),
|
||||
("ua-parser (re2)", uap_re2),
|
||||
("ua-parser (rust)", uap_rust),
|
||||
("user-agents", uas_parse),
|
||||
@@ -257,7 +258,7 @@ def bench_realistic():
|
||||
print(f"{name:20} {t / len(mix) * 1e6:7.1f} µs/UA cache: {info}")
|
||||
print(f"\n## pure bot storm ({len(storm)} unique UAs, zero cache value)")
|
||||
for name, fn in (
|
||||
("ua-parser (pure)", uap_pure),
|
||||
("ua-parser", uap_pure),
|
||||
("ua-parser (re2)", uap_re2),
|
||||
("ua-parser (rust)", uap_rust),
|
||||
("user-agents", uas_parse),
|
||||
@@ -283,8 +284,8 @@ def safe(fn):
|
||||
|
||||
def cache_info(name):
|
||||
if name == "uarite":
|
||||
i = uaparse.cache_info()
|
||||
return f"{i.hits} hits / {i.misses} misses (cap 1024)"
|
||||
i = _parse_client.cache_info()
|
||||
return f"{i.hits} hits / {i.misses} misses (cap 1024, browsers only)"
|
||||
if name == "user-agent-parser":
|
||||
from user_agent_parser.parser import _cached_parse_user_agent
|
||||
|
||||
@@ -314,7 +315,7 @@ def bench():
|
||||
rng.shuffle(work)
|
||||
res = {}
|
||||
for name, fn in (
|
||||
("ua-parser (pure)", uap_pure),
|
||||
("ua-parser", uap_pure),
|
||||
("ua-parser (re2)", uap_re2),
|
||||
("ua-parser (rust)", uap_rust),
|
||||
("user-agents", uas_parse),
|
||||
@@ -323,7 +324,7 @@ def bench():
|
||||
):
|
||||
fn = safe(fn)
|
||||
fn("Warmup/1.0 (+https://example.com/warmup)")
|
||||
uaparse.cache_clear()
|
||||
_parse_client.cache_clear()
|
||||
t = timeit.timeit(lambda: [fn(u) for u in work], number=1)
|
||||
res[name] = t / len(work) * 1e6
|
||||
return res, len(work)
|
||||
|
||||
@@ -20,7 +20,7 @@ import matplotlib
|
||||
|
||||
matplotlib.use("Agg")
|
||||
matplotlib.rcParams["svg.fonttype"] = "path" # text as paths: renders anywhere
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# µs per cold parse, from scripts/bench.py.
|
||||
US = {
|
||||
@@ -28,7 +28,7 @@ US = {
|
||||
"uarite": 17.7,
|
||||
"ua-parser (Rust)": 46.6,
|
||||
"ua-parser (RE2)": 77.1,
|
||||
"ua-parser (pure)": 321.5,
|
||||
"ua-parser": 321.5,
|
||||
"user-agents": 334.4,
|
||||
}
|
||||
|
||||
@@ -42,15 +42,17 @@ colors = ["#6e6e6e"] * len(data)
|
||||
colors[names.index("uarite")] = "#2b6cb0"
|
||||
|
||||
fig, ax = plt.subplots(figsize=(12, 1.7), dpi=100)
|
||||
bars = ax.barh(names, values, color=colors, height=0.62)
|
||||
bars = ax.barh(names, values, color=colors, height=0.82)
|
||||
ax.set_xlim(0, max(values))
|
||||
ax.axis("off")
|
||||
|
||||
for bar, name, v in zip(bars, names, values):
|
||||
# Round to three significant digits: 121951 -> "122 000".
|
||||
rounded = round(v, 2 - int(f"{v:.0e}".split("e")[1]))
|
||||
# Round to two significant digits: 121951 -> "120 000".
|
||||
rounded = round(v, 1 - int(f"{v:.0e}".split("e")[1]))
|
||||
label = f"{name} {rounded:,.0f}".replace(",", " ")
|
||||
y = bar.get_y() + bar.get_height() / 2
|
||||
# va="center" centers the font bbox incl. descender space, which leaves
|
||||
# the glyphs slightly high; nudge down to optically center on the bar.
|
||||
y = bar.get_y() + bar.get_height() / 2 - 0.09
|
||||
if bar.get_width() > max(values) * 0.28:
|
||||
# Long bar: white text inside, right-aligned at the bar end.
|
||||
ax.text(bar.get_width() - max(values) * 0.012, y, label,
|
||||
|
||||
Reference in New Issue
Block a user