TT Lab
블로그 시작하기
배우기 러닝패스 코스

프로파일링: 느린 요청 하나를 함수까지

고친 뒤, 같은 조건으로 두 프로파일을 견준다

TT Lab 에서 이어서 보기

목표

지금까지 쫓아온 원인(요청마다 정규식을 컴파일하는 couponPattern)을 고치고, 고치기 전과 같은 조건으로 다시 재서 두 프로파일의 차이(diff)로 고쳐졌음을 확인합니다. 조건이 다른 비교가 왜 믿을 수 없는지도 직접 만들어 봅니다.

왜 중요한가

「고쳤더니 빨라졌다」는 말은 두 측정이 같은 조건이었을 때만 뜻이 있습니다. 동시성이 다르면 대기 시간이 달라지고, 쿠폰 비율이 다르면 하는 일 자체가 다르고, 프로파일 길이가 다르면 표본 수가 다릅니다. 그 차이를 고친 효과로 읽으면 다음 사람이 같은 실험을 되풀이할 수 없습니다.

go tool pprof -diff_base 는 같은 조건의 두 프로파일을 빼서 줄어든 곳을 음수로 보여 줍니다. 그리고 처리량이 늘면 같은 시간에 더 많은 일을 하므로 CPU 합계만 보면 오히려 그대로일 수 있습니다. 그래서 「요청 하나당 CPU」처럼 일의 양으로 나눈 값을 함께 봅니다.

단계

  1. 소스를 처음 상태로 되돌려 pricing 을 띄우고 -c 4 -d 20s -seed 7 부하(/root/prof/runs/before.json)를 주는 동안 15초 프로파일을 /root/prof/profiles/before.pb.gz 에 받으세요.
  2. /root/prof/src/pricing/main.go 에서 정규식을 한 번만 컴파일하도록 고치고 다시 빌드하세요.
  3. 고친 pricing 으로 1단계와 같은 조건의 부하(/root/prof/runs/after.json)와 프로파일(/root/prof/profiles/after.pb.gz)을 받으세요.
  4. -diff_base 로 두 프로파일을 뺀 표를 /root/prof/answers/diff-top.txt 에 저장하세요.
  5. 두 측정의 처리량과 요청 하나당 CPU(ms)를 /root/prof/answers/compare.json 에 적으세요.
  6. 두 측정의 p99 와 그 비율을 /root/prof/answers/result.json 에 적으세요.
  7. 조건을 바꾼 측정(/root/prof/runs/after-wrong.json)을 하나 만들고, before 와 다른 조건 필드를 /root/prof/answers/why-wrong.txt 에 적으세요.

참고

고치기 전을 잰다

prof-workspace --reset pricing 으로 처음 소스로 되돌려 빌드하고, prof-svc up pricing 뒤 loadgen -c 4 -d 20s -seed 7 -out /root/prof/runs/before.json 을 돌리는 동안 ?seconds=15 프로파일을 /root/prof/profiles/before.pb.gz 에 받으세요.

비교의 기준선입니다. 나중에 같은 명령을 그대로 다시 쓸 수 있게 명령을 적어 두세요.

원인을 고친다

/root/prof/src/pricing/main.go 의 couponPattern 이 정규식을 매번 컴파일하지 않도록 고치고(패키지 변수로 한 번만 컴파일) prof-workspace 로 다시 빌드하세요.

패턴은 요청마다 같습니다. 패키지 수준 var 로 한 번 컴파일해 두고 함수는 그것을 돌려주면 됩니다. 정말 고쳐졌는지는 이 단계가 아니라 다음 단계의 프로파일이 판정합니다.

같은 조건으로 다시 잰다

prof-svc up pricing 으로 새 바이너리를 띄우고 1단계와 같은 loadgen 명령을 -out /root/prof/runs/after.json 으로 돌리는 동안 같은 길이의 프로파일을 /root/prof/profiles/after.pb.gz 에 받으세요.

채점기는 두 결과 파일의 조건 필드와 두 프로파일의 길이를 견줍니다. 하나라도 다르면 이 비교는 받지 않습니다.

두 프로파일을 뺀다

go tool pprof -top -cum -nodecount=40 -diff_base /root/prof/profiles/before.pb.gz /root/prof/profiles/after.pb.gz 의 출력을 /root/prof/answers/diff-top.txt 에 저장하세요. main.couponPattern 줄이 음수여야 합니다.

-diff_base 는 뒤의 프로파일에서 기준을 뺍니다. 줄어든 곳이 음수, 늘어난 곳이 양수입니다. couponPattern 은 자기 시간(flat)이 거의 없으니 -cum 으로 정렬해야 위에 보입니다. 고친 곳 말고 늘어난 곳도 보세요. 처리량이 늘면 다른 함수가 더 바빠집니다.

일의 양으로 나눈다

before_rps·after_rps(loadgen 결과의 rps)와 before_cpu_ms_per_req·after_cpu_ms_per_req(프로파일의 CPU 합(ms) ÷ (rps × 프로파일 길이(초)))를 /root/prof/answers/compare.json 에 적으세요.

CPU 합만 보면 두 코어를 다 쓰는 것은 고친 뒤에도 같을 수 있습니다. 같은 CPU 로 일을 몇 배 했는지가 고친 효과입니다.

사용자가 느끼는 차이

runs/before.json·runs/after.json 의 p99 를 p99_before·p99_after 로, 그 비율(before ÷ after)을 speedup 으로 /root/prof/answers/result.json 에 적으세요.

프로파일은 서버가 어디에 시간을 썼는지, p99 는 사용자가 얼마나 기다렸는지를 말합니다. 둘 다 좋아져야 「고쳤다」고 말할 수 있습니다.

믿을 수 없는 비교를 알아본다

조건을 바꿔(loadgen -c 1 -d 5s -out /root/prof/runs/after-wrong.json) 한 번 더 재고, runs/before.json 과 값이 다른 조건 필드 이름을 한 줄에 하나씩 /root/prof/answers/why-wrong.txt 에 적으세요.

조건 필드는 concurrency·duration_s·coupon_ratio·big_ratio·seed 입니다. 명령에 적지 않은 옵션은 기본값으로 돌아간다는 점을 잊지 마세요.