Files
ietf-draft-analyzer/workspace/act/bench/bench_act.py
Christian Nennemann 2506b6325a
Some checks failed
CI / test (3.11) (push) Failing after 1m37s
CI / test (3.12) (push) Failing after 57s
feat: add draft data, gap analysis report, and workspace config
2026-04-06 18:47:15 +02:00

175 lines
5.1 KiB
Python

"""ACT performance benchmarks.
Measures Phase 1 creation time (construct + sign + encode) against
the 500µs target from the specification.
"""
import time
import uuid
import statistics
from act import (
ACTMandate,
ACTRecord,
Capability,
TaskClaim,
encode_jws,
decode_jws,
generate_ed25519_keypair,
generate_p256_keypair,
sign,
verify,
transition_to_record,
)
def bench_phase1_ed25519(n: int = 10000) -> None:
"""Benchmark Phase 1 creation with Ed25519."""
priv, pub = generate_ed25519_keypair()
# Warmup
for _ in range(100):
m = ACTMandate(
alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
)
sig = sign(priv, m.signing_input())
encode_jws(m, sig)
times = []
for _ in range(n):
start = time.perf_counter()
m = ACTMandate(
alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
task=TaskClaim(purpose="benchmark"),
cap=[Capability(action="read.data")],
)
sig = sign(priv, m.signing_input())
encode_jws(m, sig)
elapsed = time.perf_counter() - start
times.append(elapsed * 1_000_000) # µs
mean = statistics.mean(times)
median = statistics.median(times)
p99 = sorted(times)[int(n * 0.99)]
print(f"Phase 1 Ed25519 (n={n}):")
print(f" Mean: {mean:.1f} µs")
print(f" Median: {median:.1f} µs")
print(f" P99: {p99:.1f} µs")
print(f" Target: <= 500 µs {'PASS' if mean <= 500 else 'FAIL'}")
print()
def bench_phase1_p256(n: int = 5000) -> None:
"""Benchmark Phase 1 creation with P-256."""
priv, pub = generate_p256_keypair()
for _ in range(50):
m = ACTMandate(
alg="ES256", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
)
sig = sign(priv, m.signing_input())
encode_jws(m, sig)
times = []
for _ in range(n):
start = time.perf_counter()
m = ACTMandate(
alg="ES256", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
task=TaskClaim(purpose="benchmark"),
cap=[Capability(action="read.data")],
)
sig = sign(priv, m.signing_input())
encode_jws(m, sig)
elapsed = time.perf_counter() - start
times.append(elapsed * 1_000_000)
mean = statistics.mean(times)
median = statistics.median(times)
p99 = sorted(times)[int(n * 0.99)]
print(f"Phase 1 ES256 (n={n}):")
print(f" Mean: {mean:.1f} µs")
print(f" Median: {median:.1f} µs")
print(f" P99: {p99:.1f} µs")
print()
def bench_phase2_transition(n: int = 5000) -> None:
"""Benchmark Phase 1 -> Phase 2 transition."""
iss_priv, _ = generate_ed25519_keypair()
sub_priv, _ = generate_ed25519_keypair()
mandate = ACTMandate(
alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
)
# Warmup
for _ in range(50):
transition_to_record(
mandate, sub_kid="sk", sub_private_key=sub_priv,
exec_act="x.y", par=[], status="completed",
)
times = []
for _ in range(n):
start = time.perf_counter()
transition_to_record(
mandate, sub_kid="sk", sub_private_key=sub_priv,
exec_act="x.y", par=[], status="completed",
)
elapsed = time.perf_counter() - start
times.append(elapsed * 1_000_000)
mean = statistics.mean(times)
median = statistics.median(times)
print(f"Phase 2 Transition (n={n}):")
print(f" Mean: {mean:.1f} µs")
print(f" Median: {median:.1f} µs")
print()
def bench_verify(n: int = 5000) -> None:
"""Benchmark JWS decode + verify."""
priv, pub = generate_ed25519_keypair()
m = ACTMandate(
alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
)
sig = sign(priv, m.signing_input())
compact = encode_jws(m, sig)
# Warmup
for _ in range(50):
_, _, s, si = decode_jws(compact)
verify(pub, s, si)
times = []
for _ in range(n):
start = time.perf_counter()
_, _, s, si = decode_jws(compact)
verify(pub, s, si)
elapsed = time.perf_counter() - start
times.append(elapsed * 1_000_000)
mean = statistics.mean(times)
median = statistics.median(times)
print(f"Decode + Verify (n={n}):")
print(f" Mean: {mean:.1f} µs")
print(f" Median: {median:.1f} µs")
print()
if __name__ == "__main__":
bench_phase1_ed25519()
bench_phase1_p256()
bench_phase2_transition()
bench_verify()