LabHub
배우기 러닝패스 코스

부하 테스트 · 회귀 판정 · 실습

성능 회귀라고 되돌린 변경이 사실은 잡음이었다

LabHub 에서 이어서 보기

목표

같은 대상을 다섯 번 반복해 잡음의 크기를 먼저 재고, 지연을 조금 늘린 판과 많이 늘린 판을 각각 다섯 번씩 재서 어느 쪽이 잡음을 넘는지 규칙으로 판정합니다. 그 규칙을 기준선 디렉터리와 새 측정 디렉터리를 받아 종료 코드를 내는 CI 게이트 스크립트로 만들고, 한 번짜리 비교가 같은 코드도 회귀로 만든다는 것을 숫자로 확인합니다.

왜 중요한가

성능 회귀 판정은 통계 문제가 아니라 운영 문제다. 문턱을 잘못 잡으면 둘 중 하나가 일어난다 — 거짓 경보가 잦아 사람들이 게이트를 끄거나, 문턱이 느슨해 진짜 회귀가 지나간다. 두 경우 다 게이트가 없는 것과 같아진다. 그래서 문턱은 회의실에서 정한 백분율이 아니라 그때 그 기계에서 실제로 잰 잡음이어야 한다. 잡음을 재려면 아무것도 바꾸지 않은 채로 같은 시험을 여러 번 돌려 봐야 하고, 그러면 자연스럽게 '몇 번 돌릴 것인가' 가 시간과 민감도의 맞바꿈이라는 것이 드러난다. 한 번만 돌리면 문턱이 0 이 되어 무엇이든 회귀가 되고, 많이 돌릴수록 더 작은 회귀를 자신 있게 잡을 수 있다. 이 판단을 사람의 눈에 맡기지 않고 스크립트의 종료 코드로 남기는 것이 이 실습의 마지막 단계다.

단계

1. /opt/lab/lt/lt-regression/svc.pyVERSION=base DELAY_MS=20 JITTER_MS=20 SEED=1234 로 127.0.0.1:8080 에 띄우세요. hey -n 200 -c 5 -o csv http://127.0.0.1:8080/work 를 다섯 번 돌려 출력을 /root/lt-regression/base/run1.csv 부터 run5.csv 까지 저장합니다. 실행마다 p50 을 구해 /root/lt-regression/01-noise.tsv 에 다섯 줄로 적으세요 — 각 줄은 탭으로 나눈 두 칸 run<번호> <p50 밀리초> 이고 밀리초는 소수 셋째 자리까지입니다. p50 은 csv 첫 칸(response-time, 초 단위)을 밀리초로 바꿔 오름차순 정렬한 뒤 int(n/2)+1 번째(1부터 세어) 값으로 정합니다. 그리고 /root/lt-regression/01-spread.txt 에 네 줄 min= · max= · spread_ms=<max - min> · spread_pct=<(max - min) ÷ min × 100, 소수 첫째 자리> 를 적습니다.
2. 1단계의 다섯 실행 중 p50 이 가장 작은 실행과 가장 큰 실행을 고르세요. /root/lt-regression/02-illusion.txt 에 여섯 줄을 적습니다 — fastest_run=<번호> · slowest_run=<번호> · fastest_p50=<밀리초> · slowest_p50=<밀리초> · apparent_change_pct=<(느린 값 - 빠른 값) ÷ 빠른 값 × 100, 소수 첫째 자리> · same_code=yes 입니다. 밀리초는 소수 셋째 자리까지 적습니다. 이 둘은 같은 판을 같은 조건으로 잰 것입니다.
3. 같은 /opt/lab/lt/lt-regression/svc.pyVERSION=small DELAY_MS=21 JITTER_MS=20 SEED=1234 로 127.0.0.1:8081 에 추가로 띄우세요(8080 은 그대로 둡니다). 1단계와 똑같은 부하를 다섯 번 걸어 /root/lt-regression/small/run1.csv 부터 run5.csv 까지 저장하고, /root/lt-regression/03-small.tsv 에 1단계와 같은 모양으로 다섯 줄을 적으세요. 그리고 /root/lt-regression/03-median.txtmedian_of_medians=<다섯 p50 의 중앙값, 소수 셋째 자리> 한 줄을 적습니다. 중앙값의 정의는 1단계와 같습니다.
4. /opt/lab/lt/lt-regression/svc.pyVERSION=big DELAY_MS=30 JITTER_MS=20 SEED=1234 로 127.0.0.1:8082 에 추가로 띄우고, 같은 부하를 다섯 번 걸어 /root/lt-regression/big/run1.csv 부터 run5.csv 까지 저장하세요. /root/lt-regression/04-big.tsv 에 다섯 줄, /root/lt-regression/04-median.txtmedian_of_medians= 한 줄을 3단계와 같은 모양으로 적습니다.
5. /root/lt-regression/05-rule.txt 에 네 줄을 적으세요 — metric=p50 · stat=median_of_5 · noise_ms=<1단계 다섯 실행의 최대 - 최소, 소수 셋째 자리> · rule=<이 규칙을 한 문장으로, 40자 이상> 입니다. 그리고 /root/lt-regression/05-verdict.tsv 에 세 줄을 적습니다. 각 줄은 탭으로 나눈 세 칸 <이름> <delta_ms> <judgment> 이고 이름은 base · small · big 순서입니다. delta 는 그 판의 다섯 실행 중앙값에서 base 의 다섯 실행 중앙값을 뺀 값(소수 셋째 자리)이고, judgment 는 delta 가 noise_ms 보다 클 때 regression, 아니면 noise 입니다.
6. /root/lt-regression/gate.sh 를 만드세요. bash gate.sh <기준선 디렉터리> <새 측정 디렉터리> 로 부르면 두 디렉터리의 *.csv 를 각각 읽어 실행마다 p50 을 구하고, 각 묶음의 중앙값을 냅니다. 출력은 한 줄이고 delta=<밀리초> noise=<밀리초> REGRESSION 또는 delta=<밀리초> noise=<밀리초> OK 입니다. delta 는 새 측정의 중앙값에서 기준선의 중앙값을 뺀 값, noise 는 기준선 실행들의 p50 최대에서 최소를 뺀 값이고 둘 다 소수 셋째 자리까지입니다. delta 가 noise 보다 크면 종료 코드 1, 아니면 0 으로 끝납니다. 채점기는 자기가 만든 세 벌의 입력으로 이 스크립트를 돌려 통과와 실패를 모두 확인합니다.
7. 1단계의 다섯 실행 중 p50 이 가장 작은 것을 /root/lt-regression/one-base/run.csv 로, 가장 큰 것을 /root/lt-regression/one-new/run.csv 로 복사하세요(두 파일 다 base 판의 측정입니다). 그 두 디렉터리로 게이트를 돌려 출력을 /root/lt-regression/07-gate-out.txt 에 저장하고, /root/lt-regression/07-onerun.txt 에 다섯 줄을 적습니다 — noise_ms=<게이트가 낸 값> · delta_ms=<게이트가 낸 값> · gate_exit=<종료 코드> · false_positive=<yes 또는 no> · min_runs=<기준선을 최소 몇 번 돌려야 한다고 볼 것인가, 2 이상의 정수> 입니다.
8. 게이트를 두 번 더 돌리세요. bash gate.sh base big 의 출력은 /root/lt-regression/08-gate-big.txt 에, bash gate.sh base base 의 출력은 /root/lt-regression/08-gate-same.txt 에 저장합니다. 그리고 /root/lt-regression/08-decision.txt 에 여섯 줄을 적으세요 — big_exit= · same_exit= · rollback=<yes 또는 no, big 판을 되돌릴 것인가> · min_runs=<5 이상의 정수> · threshold_rule=<문턱을 어떻게 정할 것인가, 40자 이상> · why=<60자 이상> 입니다.

참고

단계 8개

  1. 아무것도 바꾸지 않고 다섯 번 재서 잡음을 구한다
  2. 같은 코드끼리도 이만큼 벌어진다
  3. 5% 느려진 판을 다섯 번 잰다
  4. 50% 느려진 판도 다섯 번 잰다
  5. 판정 규칙을 글로 적고 세 판에 적용한다
  6. 규칙을 CI 게이트로 못박는다
  7. 한 번짜리 비교는 같은 코드도 회귀로 만든다
  8. 되돌릴 것인가 — 게이트의 답과 사람의 답