Both reviewers passed and each left one documentation item.
Grok: the benchmark's fork table still named the shell path `-m
lib_py.delegation.cli`, which is what R1 replaced. It now names the actual
bootstrap, and says why the module-execution form was abandoned. The fork count
is unchanged either way.
Claude (O-4): inside a freeze tree, _delegate_py_bin walks up from its own
location for a .venv and finds none, so it falls back to a system python that
has no paho. Harmless in phase 1, because nothing in production calls the frozen
lib.sh helpers; it becomes real in phase 3 when the loop process starts doing
exactly that. Recorded on P3-02 rather than fixed here, since the fix belongs
with the code that will depend on it. Verified the premise: the current freeze
root has no .venv.
No code changed. The unanimous PASS was issued on 95f3e9a.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd
4.6 KiB
📊 Issue #5 Phase 1 — 장수 MQTT 연결 벤치마크 실측
- 문서 버전: Rev.1
- 측정 일시: 2026-09-06
- 기준 커밋: Phase 1 커밋 4 (
feat(issue-5): persistent MQTT publisher prototype and benchmark harness) - 하니스:
python -m lib_py.delegation.bench --n <N> --transport {fake|broker} - 근거 대상:
implementation_plan.md§5 "MQTT 연결 재사용 p50 단축" 항목
1. 측정 환경
| 항목 | 값 |
|---|---|
| Python | 3.9.6 (.venv) |
| paho-mqtt | 2.1.0 |
| 플랫폼 | darwin-arm64 |
| 로컬 브로커 | 없음 (mosquitto, nats-server, docker 모두 미설치) |
| 실브로커 | broker.hivemq.com:1883 (PoC 기본 공용 브로커, TLS 없음) |
⚠️ 로컬 브로커가 없으므로 실브로커 수치는 공용 인터넷 브로커에 대한 1회 측정치이며, 네트워크 상태에 좌우된다. 게이트 조건이 아니다. 게이트가 걸린 것은 아래 §2의 결정적 지표뿐이다.
2. 결정적 지표 — 가짜 전송 (CI 단정 대상)
합성 연결 지연 50 ms, N = 50.
| 지표 | OneShot | Persistent |
|---|---|---|
| 발행 수 | 50 | 50 |
| 연결 수립 횟수 | 50 | 1 |
| 실패 | 0 | 0 |
| 발행당 지연 p50 | 54.813 ms | 0.002 ms |
| 발행당 지연 p95 | 55.049 ms | 0.003 ms |
| 발행당 지연 max | 55.075 ms | 51.110 ms (최초 연결) |
tests/test_issue5_phase1_delegation.py::test_bench_fake_transport_schema_and_counts가 "OneShot = N, Persistent = 1" 및 p50 감소를 단정한다. 네트워크 접촉 0.
3. 정보성 지표 — 실브로커 (게이트 아님)
broker.hivemq.com:1883, N = 5.
| 지표 | OneShot | Persistent |
|---|---|---|
| 연결 수립 횟수 | 5 | 1 |
| 실패 | 0 | 0 |
| 발행당 지연 p50 | 1892.728 ms | 275.992 ms |
| 발행당 지연 p95 | 1942.762 ms | 875.412 ms |
| 발행당 지연 max | 1942.762 ms | 875.412 ms (최초 연결) |
p50 기준 약 85% 단축. 연결 수립이 발행 지연의 지배적 요소임을 보여준다.
3-1. 이 프로토타입의 실측 동기
Rev.1 계획 job의 started 이벤트는 payload timestamp 05:58:49Z에서 모니터 수신 05:59:01.487Z까지 약 12.5초가 걸렸고, 원인은 CONNECT_ACK_TIMEOUT=10 1회 실패 후 재연결이었다. 본 job(ddcaf930)의 started 발행에서도 같은 CONNACK 경고가 재현됐다. 1회성 연결은 이 비용을 매 이벤트마다 다시 지불한다.
4. 프로세스 포크 수 (셸 경로, 분석값)
delegate_publish_event 1회당:
| 구현 | fork |
|---|---|
레거시 (_delegate_publish_event_legacy) |
3 ($(_delegate_py_bin), $(_delegate_script), python) |
신규 (_delegation_py → python -c + sys.path.insert(0, SKILL_DIR)) |
3 ($(_delegate_py_bin), $(_delegate_script), python) |
신규 경로는
-m이 아니라_delegation_py의 명시 부트스트랩이다(교차 리뷰 R1 대응:-m은 cwd가PYTHONPATH보다 우선하므로 freeze 보장이 성립하지 않았다). fork 수는 그와 무관하게 동일하다.계획서 D8은 신규 경로가 2 fork일 것으로 예상했으나, 실제 구현은 3 fork로 동일하다.
_delegate_script publish_event.py조회를 유지했기 때문이다.이 조회가 실제로 보장하는 것 (교차 리뷰
cc3468cb정정): 초기 서술은 이 조회가 "비치명 계약(C-02)을 만드는 유일한 지점"이라고 했으나 부정확하다. rc 0 자체는delegate_publish_event의|| true만으로도 보장되고, C-02도 rc만 단정한다. 조회가 보장하는 것은 위임 스크립트 트리가 없을 때 인터프리터를 아예 띄우지 않아 stderr에 트레이스백을 남기지 않는다는 정숙성과, 레거시 본체와의 동작 동일성이다(인터프리터 미호출 단정은 C-01에 있다). 유지 결정 자체는 세 리뷰어 전원이 지지했으며, fork 절감은 Phase 4에서 이 계약과 함께 재검토한다.
5. 프로덕션 적용 범위
Phase 1에서 장수 연결은 프로덕션 경로에 쓰이지 않는다. CLI와 셸 헬퍼는 발행 1회 후 프로세스가 종료되므로 재사용 이득이 없고, 두 경로 모두 OneShotPublisher를 계속 쓴다. 첫 소비자는 Phase 2a의 장수 엔진이다.
6. 재현 명령
export PYTHONPATH="$PWD/.agents/skills"
.venv/bin/python -m lib_py.delegation.bench --n 50 --transport fake --connect-latency-ms 50
# 실브로커(임시 레지스트리 필요)
.venv/bin/python -m lib_py.delegation.cli submit --prompt bench --registry-dir .mam/jobs
.venv/bin/python -m lib_py.delegation.bench --n 5 --transport broker --job <id> --registry-dir .mam/jobs