집계 배치가 MemoryError 로 죽었고 최근 변경 때문으로 봤다. 그 변경이 top_n=500 으로 제한하던 것을 제한 없이 전체로 바꾼 것이라 데이터가 늘어나는 것이 당연해 보였다.
Table of contents
Open Table of contents
검증 — 되돌리기 전의 실측
두 가지 방법이 있었는데 바로 git revert 하고 다시 돌려 보는 것과 되돌리기 전에 얼마나 줄어드는지를 재 보는 것이다. 뒤쪽을 골랐다. 이유는 배치가 한 번 도는 데 몇 시간이 걸려 시행착오 비용이 커서다. 대신 실측에 반나절이 드는 것을 감수했다. S3 에 적재된 stats.json 을 열어 버킷별 바이트 수를 직접 셌다.
결과가 뜻밖이었는데 문제의 변경이 영향을 주는 top_items 버킷이 전체의 8퍼센트에 불과했다. 되돌려도 페이로드가 그만큼만 줄어드니 터지는 것은 그대로였고 직접 원인이 아니었다.
원인 — 비중이 가리킨 대상
daily 버킷이 전체의 팔십 퍼센트대를 차지하고 있었다. 경량화를 하려면 그쪽을 겨냥해야 했다.
한 자릿수 퍼센트짜리를 되돌리는 것과 팔십 퍼센트대짜리를 줄이는 것은 완전히 다른 작업이다. 메모리 문제는 큰 것을 줄여야 효과가 있으므로 무엇이 몇 퍼센트인지를 먼저 재고 겨냥할 데를 정해야 한다.
주의 — 되돌리면 안 되는 이유
그 변경을 되돌리면 안 될 수도 있다는 것도 나왔다. 제한을 없앤 데 의도가 있을 수 있는데 상위 몇백 개만 담으면 그 밖의 항목이 추세에서 빠지기 때문이다.
공백을 막으려고 넓혔을 가능성이 있으므로 함부로 되돌리면 안 된다고 REVIEW.md 에 적었다. 원인이 아닌 것을 되돌리면 문제는 그대로이고 원래 고친 것만 망가진다.
배경 — 같이 나온 별개 버그
같은 리뷰에서 다른 것이 나왔는데 build_summary() 의 반환 형태가 바뀌었는데 호출부가 안 바뀐 것이었다. dict 를 기대하는 코드가 tuple 을 받으므로 그대로 TypeError 가 난다.
다만 어디에 영향이 있는지를 먼저 갈랐다. report.py 경로만 그 함수를 호출하고 운영 갱신 경로는 update_stats() 를 쓰며 빌드는 셸만 생성하므로 한 경로만 영향이었다.
조치 — 경로로 한정한 수정
그러면 고칠 것도 한 줄로 한정된다. 그 함수를 쓰는 모든 곳이 아니라 실제로 그 경로를 타는 곳만 보면 수정 범위가 정해진다.
이 리뷰의 결과가 초기 단정 교정과 별개 버그 발견 둘이었고 둘 다 실측과 경로 추적으로 나왔다. 특히 앞의 것이 중요했는데 안 재고 되돌렸으면 메모리는 여전히 터지고 되돌린 변경의 원래 의도가 사라지며 진짜 원인은 계속 안 보였을 것이다.
정리
- 회귀로 의심되는 변경도 얼마나 영향을 주는지 실측한다
- 되돌려도 8퍼센트면 직접 원인이 아니다
- 비율을 재서 겨냥할 데를 정한다
- 큰 것을 줄여야 효과가 있다
- 원인이 아닌 것을 되돌리면 원래 고친 것만 망가진다
- 변경에 다른 의도가 있을 수 있으면 함부로 되돌리지 않는다
- 반환 형태가 바뀌었는데 호출부가 안 바뀌면 크래시가 난다
- 그 함수를 쓰는 모든 곳이 아니라 그 경로를 타는 곳을 본다