고마웠다, 제니퍼 SFR(Stacktrace Flight Recorder)
이번 아티클은 애플리케이션 성능 모니터링 솔루션 제니퍼(JENNIFER)의 기능인 SFR(스택트레이스 샘플링을 이용한 성능 분석)을 이용해 성능 개선 작업을 진행한 제니퍼 개발자의 경험기입니다. 전체를 아우르는 섬세한(!) 튜닝을 통해 좀 더 만족할 수 있는 성능 개선을 원하는 개발자에게 작은 도움이 될 수 있으면 좋겠습니다.
개요
우리가 스택트레이스 샘플링을 이용한 성능 분석, SFR(Stacktrace Flight Recorder) 을 통해 얻고 싶은 건 성능 개선 작업을 할 때 도움을 얻는 일 입니다.
성능 개선은 장애 처리와 접근하는 방법이 다릅니다.
장애 처리의 경우, 장애라는 문제가 발생하고, 이 문제의 원인이 분명할 때 해당 원인을 제거하거나 조처하면됩니다. 그리고, 원인이 분명하지 않을 때에는 가설을 세우고 이를 재현하는 것을 반복해서 원인을 찾게 됩니다.
반면 성능 개선은 어떤 문제가 발생하기 보다, 인지나 특정 요구사항이 발생한 경우에 이를 해결하는 과정입니다. 예를 들면, 다음과 같은 사항이 성능 개선을 시도하는 이유입니다.
- 성능에 특정 목표치가 존재할 때. ex) 반드시 1초 이내로 요청이 처리되어야 해!
- 프로그램이 느려진 거 같아 확인해 봐. ex) 언젠가부터 반응이 느린 느낌인데?
- 시스템이 수정되거나 사용하는 프로그램(라이브러리) 버전이 변경되었을 경우. ex) 에이전트를 설치했더니 또는 업그레이드했더니 느려졌네?
이런 이유로 성능개선을 하는 과정은 다음과 같습니다.
💡 요구 또는 인지 → 재현 환경 구성 → 측정 → 개선 → 검증을 위한 측정(목표치까지 반복)
성능 개선 과정
요구 또는 인지
어느 날 개발자 A는 다음과 같은 성능개선 요구를 받았습니다.
👨💻 ‘제니퍼 V4 버전에서 V5로 업그레이드했는데, 응답시간도 늦어지고 CPU 0.5 ~ 1% 더 많이 사용하는데요? 좀 봐주세요.!!!’
재현 환경 구성
일단 개선 작업을 하기로 했으니, 요구사항이 정말 그런지 아닌지 어떤 특징이 있는지 확인 작업을 진행해야 합니다. 확인 작업을 위해서는 요구사항과 비슷한 테스트 환경 구성과 프로그램 재현 작업을 먼저 거쳐야 합니다. 그리고 프로그램 재현 작업 시에 여러 번의 시행착오를 하지 않으려면 최대한 애플리케이션의 구성이 어떻게 되어 있는지 파악해야 합니다.
이 부분이 정말 중요한 과정입니다. 정확히 알려주면 재현을 쉽게 할 수 있지만 잘 모르고 있는 경우가 너무 많습니다. 반대로 너무 자세히 알고 있어도 문제가 될 수 있기 때문입니다. 결국 우여곡절 끝에 환경 구성과 프로그램 재현 준비가 완료되고, 어떤식으로 테스트를 진행할지 환경 구성이 되었으면 일단 에이전트를 설치하여 전반적인 상태의 데이터를 수집합니다.
측정
여러 옵션 조절로 응답 시간이 약간 줄어들고 미미하게 CPU 사용량이 줄어든 것을 볼 수 있습니다.
🤓 옵션으로 모든 처리가 가능하면 좋겠지만 이 정도로 만족하지 않습니다. 좀 더 진행해 봐야겠습니다.
연관된 메트릭스를 몇 개 더 추가하여 데이터상으로 응답시간 부분에는 눈에 띄게 차이점을 느낄 수 있지만 만족하지 않습니다.
개선
고객의 만족을 위해 프로그램 성능개선을 하려면 여러 가지 방법이 있을 수 있습니다. 알고리즘 최적화, 코드 최적화, 하드웨어 업그레이드, 병렬 처리, 캐싱, 메모리 관리, 프로파일링을 통한 병목 지점 찾기 등 많은 방법이 있습니다.
이전에는 프로파일링을 통해서 개선 포인트를 찾는 방법이 최선이었습니다.(이 방법은 값의 차이가 잘 보이는 곳에서는 좋은 방법입니다만 그 격차가 미미할 경우에는 큰 도움이 되지 않을 수 있습니다.) 스레드 덤프를 통해서 찾거나 하는 방법도 있지만 정확하지 않았습니다. 이전에는 쉘이나 기타 CLI 도구를 통해서 시간을 정하고 기록 후에 엑셀을 통해서 일일이 수작업하는 게 일반적인 방법이었습니다.
그러나 지금, 이 순간 우리에게는 SFR이 있습니다.
💡 SFR을 통해서 프로세스 CPU 사용률이 높은 시점에 수집된 스택들을 분석하여 튜닝포인트를 찾으려고 합니다. 해당 시점에 스택을 통해 공통적으로 많이 호출되는 메서드의 성능을 개선하는 것이 목표입니다.
다음 과정을 통해 분석을 진행해 보겠습니다.
- 스택트레이스 수집
- Flame Scope 차트 분석
- Method Table 및 Flame 차트 분석
- 코드수정
스택트레이스 수집
개선 포인트를 찾기 위해 자동 스택 트레이스 기능을 설정해서 스택 수집을 통해 SFR을 사용하여 내용을 분석합니다.
Flame Scope 차트 분석
자동 스택 트레이스 설정을 하고 시간이 지나면 스택트레이스 데이터가 수집됩니다. CPU 사용률 개선이 목표이므로 프로세스 CPU 사용률을 선택하고, Flame Scope 차트를 통해 수집된 스택 트레이스 분석을 원하는 시간대를 선택합니다.
Method 테이블 및 Flame 차트를 통한 Method 분석
코드 수정
의심이 가는 부분 코드를 수정하고 옵션을 추가하는 등 개선 작업을 진행합니다.
검증을 위한 측정(목표치 CPU 사용률 평균 1% 개선을 위한)
개선 작업을 하고 나서 다시 수집된 스택 내용이 다음 화면에 있습니다.
짠~ 무언가 개선된 게 보이나요? 처음에 SFR 화면만 보고는 개선이 되었는지 인지가 되지 않았습니다. 다만 수집된 스택의 내용이 다른 것만 인지가 되었죠. 하지만 자세히 수치를 보면 많은 성능 개선이 이루어진 것을 볼 수 있습니다. SFR로 개선된 내용을 인지하기는 쉽지 않습니다. 하지만 우리에겐 성능 브라우저가 있잖아요? 성능 브라우저를 통해 개선 전후를 비교해 봅니다.
정말 아름답지 않습니까? 비록 테스트 결과지만 이 성능 차이가 보이시나요? 밑에 잘 안 보일까 봐 추가한 화면입니다. 이번에 수행한 테스트는 SQL 수행이 많을 때의 상황이지만 응답시간은 약 50배 CPU 사용률은 6배 정도 성능이 개선된 걸 확인 할 수 있습니다.(이 정도 성능 차이라니… 처음에 개발을 잘 못했겠죠 😂)
X-View와 액티브 서비스 화면이 없으면 좀 섭섭할까 봐 한 장 넣었습니다.
SFR 이전에는 이런류의 성능 개선이나 부분이 아니라 전체적인 성능 개선이 필요한 경우에는 주기적인 스레드 스택을 통한 방법이 최선이었습니다. 다양한 도구들이 있었지만, 사용하기 쉽지 않고 지나간 데이터는 유지되지 않아 엑셀 또는 메모장을 통해 일일이 비교하며 수작업해야 했습니다. 또한 이런 작업을 수행할 수 있는 사람도 드물었던 게 사실입니다.
제니퍼의 SFR 기능이 만들어진 이후에 개발이 아니라 운영 쪽에서도 내용 확인을 요청할 수도 있게 되었으며, 무엇 보다 약간의 지식으로도 성능 개선 작업을 수행할 수 있도록 성능 개선 난이도를 내린 부분이 가장 큰 성과가 아닐까 싶습니다.