시스템을 최적화하라, 구성 요소가 아닌
해밍의 시스템 공학 제1원칙
해밍의 Ch. 28 핵심 원칙: 구성 요소를 최적화하면 시스템 성능이 망가질 가능성이 높다.
그는 미분해석기(differential analyzer) 사례로 이를 설명했다. 두 장치를 연결해야 했다. 제작자들은 두 번째 장치의 증폭기를 개선했다. 검수 당일, 해밍은 표준 테스트를 실행했다 — y'' + y = 0을 풀고 y vs y' 그래프를 그려 원이 나와야 한다. 그러나 실패했다. 원인: 개선된 증폭기가 접지 회로를 통해 더 많은 전류를 끌어들였다. 접지는 원래 설계에는 적합했지만, 새로운 전류 수준에는 맞지 않았다. 고장난 것은 인터페이스였지, 구성 요소가 아니었다.
그의 일반화: 대부분의 시스템 실패는 구성 요소가 아니라 인터페이스에서 발생한다. 구성 요소는 설계되고, 테스트되며, 인증된다. 인터페이스는 사후에 설계되고, 거의 테스트되지 않으며, 독립적으로 인증되는 경우가 없다. 구성 요소가 변경되면 해당 인터페이스의 동작도 변경된다. 하위 시스템은 그 새로운 인터페이스를 고려해 설계되지 않았다.
핵심 비대칭: 구성 요소가 10배 개선되더라도, 그 구성 요소가 제약된 인터페이스에 연결되어 있다면 시스템 전체는 10배 악화될 수 있다. 개선은 더해지지 않고, 오히려 빼게 된다.
실패한 시스템 공학으로서의 교육 시스템
해밍의 교육 사례
해밍은 이 원리를 교육에 적용했다. 개별 과목 점수를 최적화하는 것 — 각 과목에서 시험 성적을 극대화하도록 학생들을 훈련하는 것 — 은 개별 시험에서는 잘 보이지만, 학문 간 지식을 통합하지 못하는 학생을 만들어낸다.
각 구성 요소(과목 점수)는 향상됩니다. 시스템(교육, 통합된 이해로 정의됨)은 저하됩니다. 과목 간의 인터페이스 — 학생이 여러 영역에 걸쳐 지식을 적용하는 능력 — 은 최적화된 적이 없었습니다. 그것은 퇴화했습니다.
이것은 구현상의 우연이 아닙니다. 구조적입니다. 구성 요소 성과를 측정하고 보상하면 구성 요소 최적화가 이루어집니다. 인터페이스는 구성 요소 지표에 보이지 않습니다.
그의 처방: 시스템에서 병목을 찾은 다음, 그것을 제거했을 때 하류에서 어떤 일이 일어나는지 물어보십시오. 병목 제거는 다음 대기열을 넘치게 합니다. 제약 없는 최적화는 새로운 제약이 됩니다.
인터페이스 저하 추적
해밍은 구성 요소를 개선하면 그 인터페이스 동작이 바뀌며, 시스템의 나머지 부분은 이전 인터페이스를 기준으로 설계되어 있었다고 보여주었습니다.
Nodes, Queues, Surge Scores
A MOAD Factory Model
모든 소프트웨어 의존성 그래프는 공장을 형성합니다. 각 노드는 워크스테이션입니다. 각 엣지는 큐입니다. 작업이 노드의 큐로 들어가 처리되고, 다운스트림 큐로 흘러갑니다.
두 개의 점수가 모든 노드를 특징짓습니다:
Surge score = speedup × in-degree
이 병목 지점이 해소될 때 하류로 얼마나 많은 작업이 쏟아지는지를 나타냅니다. in-degree가 5(5개의 상류 의존성이 모두 이 노드로 유입)이고 100× speedup이 발생하면, 하류로 500× surge가 생성됩니다.
Betweenness = in-degree + out-degree
이 워크스테이션이 전체 흐름에서 얼마나 중심적인지. 높은 betweenness는 많은 경로가 이 노드를 통과한다는 의미입니다.
두 가지 원형:
Workaholic node: 높은 betweenness, 높은 surge score. 이것이 병목입니다. 상류의 모든 큐가 이 때문에 막힙니다. 하류 용량을 준비하지 않고 이 병목을 제거하면, 하류의 모든 것이 동시에 무너집니다.
Glutton node: 높은 out-degree, 낮은 surge score. 공급되는 모든 것을 소모합니다. 병목이 처리량이 아니라 내부에 있기 때문에 고통을 느끼지 않습니다. 멈추는 것을 잊어버린 기계 — 작업이 들어가고, 아무것도 나오지 않으며, 노드는 영원히 'busy'라고 보고합니다.
MOAD-0001 & MOAD-0005: 결합 사례
GHC 사례
GHC의 의존성 해결기에서 MOAD-0001 패치 적용 전: N=50,000개의 의존성을 빌드하는 데 17분이 걸렸다. 적용 후: 10초. 속도 향상: 100×.
하류에는 어떤 일이 일어날까? 17분 배치 도착 속도에 맞춰 동작하던 모든 빌드 캐시, 아티팩트 저장소, CI 러너는 이제 시간당 100배 더 많은 완료된 빌드를 받게 된다. 시간당 60개의 빌드 아티팩트를 처리하도록 설계된 캐시는 이제 6,000개를 받는다.
이것이 MOAD-0005: 캐시 스탬피드 결함이다. 모든 캐시 키가 동시에 미스되는데, 이는 새로운 도착 속도에 맞춰 미리 워밍된 캐시가 없기 때문이다. MOAD-0001의 수정이 MOAD-0005를 만들어낸다.
이 결합은 우연이 아니다. 구조적이다. in-degree > 1인 O(N²) → O(N) 속도 향상은 1을 초과하는 서지 점수를 생성한다. 100을 초과하는 서지 점수는 MOAD-0005 후보가 된다.
공개 전 스테이징
빌드 시스템은 시간당 1,000개의 패키지 의존성 그래프를 처리합니다. 그래프 탐색에서 MOAD-0001을 패치하여 빌드 시간을 60분에서 30초로 단축했습니다 — 120배의 속도 향상입니다. 이제 시스템은 시간당 120,000개의 그래프를 처리합니다.
언제 중단할 것인가: 중단 조건
정지 조건
패치가 정지 조건을 충족한다는 것은 — 즉, 공개하지 말라는 의미 — 다음 네 가지 조건이 동시에 성립할 때입니다:
1. 패치가 라이브 시스템에 존재함 (병합됨, 배포됨)
2. 다운스트림 영향에 대한 책임자가 지정되지 않음
3. 다운스트림 결함 (MOAD-0005) 미해결
4. 속도 향상 >= 100×
네 개가 모두 합쳐지면 = 아기가 울어요. 병합 후가 아니라 병합 전에 팀을 배정하세요.
관리자가 없는 노드는 일꾼 없는 워크스테이션처럼 작동합니다. 작업이 쌓입니다. 누군가 무너집니다. 퍼마컴퓨터 원칙: 드라이버를 스테이징하지 않고는 디스패치 알고리즘을 수정하지 마세요. 드라이버 3대, 인구 300만 명: 알고리즘을 풀면 더 빠른 배송이 아니라 처리되지 않은 요청의 엄청난 물결이 생깁니다.
WALL-E: 대식가와 일중독자
WALL-E 모델
픽사의 WALL-E는 공장 모델의 실패를 가장 명확하게 보여줍니다. 호버체어에 앉은 대식가들은 마찰 없이 먹여지고, 일중독자들 — WALL-E, EVE — 은 공급을 유지하기 위해 작업장에서 죽어갑니다.
대식가 노드(호버체어에 앉은 인간)는 최대 출력 차수를 가집니다. 공급되는 모든 것을 소비하고 아무것도 생산하지 않습니다. 서지 점수는 0입니다 — 싱크입니다. 출력에 아무것도 쌓이지 않기 때문에 고통을 느끼지 않습니다. 그저 소비할 뿐입니다.
워크홀릭 노드(WALL-E)는 최대 사이즈를 가집니다: 모든 것이 이 노드를 통과합니다. 모든 입력을 흡수합니다. 유일한 출력을 생성합니다. 만약 더 빠른 모델로 대체된다면, 그 서지 점수는 모든 하위 큐를 동시에 범람시킬 것입니다.
WALL-E 시스템의 결함은 탐식자들이 아닙니다. 그것은 부재한 관리자입니다: 워크스테이션의 균형을 맞출 담당자가 없습니다. 알고리즘을 실행하기 전에 용량을 준비한 사람도 없습니다.
pip 사례: 공개 전 체크리스트
Python의 pip 의존성 해결기에서 MOAD-0001을 발견했습니다. 측정된 속도 향상: 200×. pip는 하루에 약 4억 건의 설치에서 실행됩니다. PyPI는 패키지를 제공합니다.