[Review] Writing a Performance Budget Document TODO
Concept
A performance budget document spells out, in numbers and conditions, the performance targets a system must meet, serving as the basis for design, review, and deployment decisions. At minimum it needs the target workload (request types and their ratios), the load level (requests per second, concurrency), metrics and targets (tail latency like p95/p99 rather than average, throughput, resource usage), and the measurement method and environment — that's what makes it a reproducible baseline. The budget becomes far more actionable when the overall target is broken down and allocated across segments — for example, splitting an end-to-end latency target across network, queue wait, handler, and DB call lets you immediately see which segment blew its budget. Targets should be set with justification; deriving them from user-perceived thresholds or an upstream system's timeout is more defensible than picking arbitrary numbers. Finally, the document only carries real force once it also states what happens on a budget overrun — blocking deployment, rolling back, an exception-approval process.
Without a documented target, performance turns into a subjective argument over "slow" versus "fast," and regressions only get discovered once they've piled up, by which point tracing the cause is hard.
Code & Formula
# [복습] 성능 예산 문서 쓰기 — 종단 지연 목표를 구간별(네트워크/큐/핸들러/DB)로 쪼개
# 각 구간 상한을 정하고, 실측값과 비교해 어느 구간이 예산을 초과했는지 즉시 드러낸다.
budget_ms = {
"network": 20,
"queue_wait": 30,
"handler": 40,
"db_call": 50,
}
total_budget_ms = sum(budget_ms.values())
# 실측치 두 세트: 정상 배포 vs 회귀가 있는 배포
measured_ok = {"network": 18, "queue_wait": 25, "handler": 35, "db_call": 45}
measured_regressed = {"network": 19, "queue_wait": 28, "handler": 38, "db_call": 95}
def evaluate(name, measured):
print(f"--- {name} (총 예산 {total_budget_ms}ms) ---")
violations = []
for stage, limit in budget_ms.items():
actual = measured[stage]
status = "OK" if actual <= limit else "OVER"
if status == "OVER":
violations.append(stage)
print(f" {stage:10s}: {actual:5.1f}ms / {limit}ms budget -> {status}")
total_actual = sum(measured.values())
print(f" 합계: {total_actual:.1f}ms / {total_budget_ms}ms")
if violations:
print(f" 조치: 배포 차단 (초과 구간: {', '.join(violations)})")
else:
print(" 조치: 배포 승인")
print()
evaluate("정상 배포", measured_ok)
evaluate("회귀가 있는 배포", measured_regressed)
docs/code/algorithms/algorithms-51.py
Exercise
Pick one of the services you currently work on, write a one-page budget covering workload, load, per-segment latency budget, measurement method, and action-on-overrun, then fill in actual measurements next to each line to find current violations.
Practical Connection
Breaking Verex's path from order submission to fill reflected — API, matching, chain submission, confirmation wait — into per-segment budgets lets you immediately tell, when perceived latency worsens, whether it's chain congestion or a regression in your own service.
If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.