성능 튜닝을 어떻게 접근해야 하는지 살펴보자.
성능 튜닝을 위해서는 아주 기초적인 법칙을 하나를 알아야 한다. 바로 '암달(Amdahl)의 법칙'이라는 것이다.
Gene Amdahl이 1967년에 시스템의 성능 향상에 대한 법칙을 만들었다. 이 법칙을 간단하게 설명하자면, 1 Core에서 20시간 소요되는 작업 중 1시간은 절대 개선할 수 없다면, 20배 이상의 성능 향상은 불가능하다는 법칙이다. 암달의 법칙을 수식으로 표현하면 다음과 같다.
여기서 P는 개선 가능한 부분의 비율이며, S는 개선된 정도를 말한다.
만약 개선 가능한 부분이 100%이면, P는 1이 된다. 그리고, 2배의 성능 향상이 이루어졌다면, S=2가 된다.
따라서 이 공식을 적용하면,
가 되며 성능 개선율은 2가 된다.
만약 개선 가능한 부분이 90%라면 P는 0.9가 되고, 그 부분에서 2배의 성능 향상이 되었다면,
이 되기 때문에 성능 개선율은 1.8이 된다.
암달의 법칙을 그래프로 나타내면 다음과 같다.
어떤 프로그램이라도 할지라도 위와 같은 패턴을 보일 수 밖에 없으며, 성능 개선에는 한계가 생길 수 밖에 없다.
1) 원인 파악
2) 목표 설정
3) 튜닝 실시
4) 개선율 확인
5) 결과 정리 및 반영
각 사항에 대해서 간단히 살펴보자.
성능 저하가 발생하는 원인을 파악하는 단계이다.
이 단계에서 원인 파악을 잘못하면 매우 많은 시간 낭비가 발생할 것이다. 따라서, 어디가 병목인지 확실히 파악하여 원인을 찾아야 한다. 그냥 단순하게 보면 별 것 아닌 단계일 수 있으나, 실제로 제대로 원인을 파악하면 오랜 시간이 소요될 수 있다. 그러므로, 주변의 전문가가 있다면 그들에게 부탁하는 것도 좋은 방법이다. 일주일 동안 걸리는 일을 그들은 한 시간만에 처리할 수도 있기 때문이다. 그리고, 원인이 아닌 곳을 원인으로 판단하여 진행하며, 첫 단추를 잘못 맨 것이기 때문에 아무리 결과 정리까지 끝냈다고 하더라도 처음부터 다시 튜닝 작업을 해야하는 상황도 발생한다.
성능 튜닝의 목표를 설정하는 단계이다.
반드시 목표를 설정할 필요는 없다. 하지만, 모든 일은 목표가 있어야만 제대로 된 결과가 나올 수 있다. 성능 개선뿐만 아니라, 향후 유지보수까지 모두 고려해서 목표를 정하는 것이 좋다.
코드를 최적화하며 튜닝하는 단계이다.
튜닝을 실시하는 가장 좋은 방법은 프로파일링 툴이나 APM과 같은 툴을 사용하는 것이고, 개선이 얼마나 되었는지를 확인하려면 JMH나 캘리퍼와 같은 성능 비교 도구를 사용하는 것도 큰 도움이 될 수 있다.
튜닝을 실시한 후 얼마나 개선되었는지를 확인하는 단계이다.
개선을 확인한 다음에, 결과가 만족스럽지 않은 경우에는 '튜닝 실시' 단계로 다시 넘어가서 진행을 해야 한다. 간혹, 원인을 잘못 판단했을 경우 개선율이 아주 낮게 나올 수 밖에 없다. 엉뚱한 곳에서 작업을 할 수도 있으니, 때에 따라서는 '원익 파악'부터 다시 해야 한다.
튜닝한 결과들을 정리하고, 실제 운영되는 시스템에 반영하는 단계이다.
만약 정리가 반드시 필요 없다고 하더라도, 아주 간단하게 어딘가에 정리하는 습관을 가져가는 것이 좋다. 가장 좋은 것은 파워 포인트나 워드와 같은 문서지만, 이 작업을 수행할 때는 꽤 많은 시간이 소요된다. 따라서, 관련인들에게 전달할 메일로 정리하거나. 회사에 위키가 있다면 위키로 정리하는 것도 좋다.
또한 무의미한 데이터를 다 넣기보다는 되도록이면 꼭 필요한 사항들만 정리해야 한다. 만약 무의미한 데이터를 어쩔 수 없이 넣어야 한다면, 보고용 요약본도 따로 만들어야만 한다.
간단하게 각 사항에 대해서 살펴보았으니, 튜닝을 실시할 때 어떤 점을 유의해야 하는지 알아보자.
성능 튜닝의 비법은 다음과 같다.
병목이 될 수 있는 대상 목록은 다음과 같다.
대상 | 세부 대상 |
서버 장비 | CPU, Network, Disk, Memory 등 |
서버 OS | OS 커널, OS 설정, 수행중인 프로세스 등 |
자바 애플리케이션 | 스레드 풀 설정, DB Connection Pool 설정, Cache 설정, GC 설정, Heap 크기 설정, 검증되지 않은 프레임워크의 버그, 개발된 애플리케이션 등 |
웹 서버 | 프로세스 개수 설정, Connector 설정, 개발된 모듈의 버그 등 |
네트워크 | 사용자의 네트워크의 종류, 사용자의 위치, L4 및 Switch 등 네트워크 장비, 방화벽 등 |
클라이언트 | 클라이언트 장비의 CPU, Network, Disk, Memory, OS 등의 성능, 클라이언트 애플리케이션, 클라이언트 장비에서 수행 중인 프로세스 등 |
애플리케이션의 가장 큰 성능 저하가 발생하는 부분을 찾아서 튜닝해야만 한다.
어떤 애플리케이션은 1명의 요청을 할 때는 응답이 0.1초로 매우 빠르다. 하지만, 운영 상황에서 그 속도가 나온다고 보장할 수는 없다. 즉, 부하 테스트 툴이나 간단히 스레드를 만들어서 부하를 주어 성능 측정을 해 봐야만 한다. 모든 애플리케이션ㅇ르 그렇게 측정할 필요는 없지만, 해당 애플리케이션 요청의 상위 80%에 해당하는 프로그램들은 반드시 그렇게 측정하고 문제를 잡아야만 한다. 예를 들어 일반적인 경우 전체 300개의 화면이 있을 때 10개 내의 화면이 전체 요청의 80%를 차지한다. 심한 경우에는 5개도 안되는 화면이 전체의 95%를 차지하는 경우도 존재한다.
그리고, 성능 튜닝을 하다 보면 중심이 되는 라이브러리에 문제를 발생하는 경우도 적지 않다. 이 경우 선택은 두 가지다. 하나는 해당 라이브러리를 튜닝하는 것이고, 다른 하나는 다른 것으로 교체하는 것이다. 라이브러리를 튜닝하는 것이 비용상으로 많은 절감을 가져올 수 있겠지만, 그렇게 할 수 없는 경우에는 다른 것으로 교체할 수 밖에 없다. 만약 개발이 거의 막바지에 다다랐을 때는 라이브러리를 교체하는 기능이 만만치 않게 될 수도 있다. 이런 경우가 발생하는 것을 방지하는 가장 좋은 방법은 시스템의 코어 부분이 개발 완료되었을 때 성능 테스트를 통해 사용중인 라이브러리의 성능을 검증하는 것이다. 대부분의 프로젝트는 개발을 시작할 때 코어가 되는 부분을 먼저 개발하고, 그 다음에 관련된 기능을 개발한다. 따라서 이 절차를 따르는 것을 권장한다.
자바의 성능도 큰 영향을 미치지만, 해당 애플리케이션을 사용하는 사용자들에게 클라이언트의 성능도 무시할 수 없다. 웹 페이지를 만들었다면, 적어도 브라우저에서 제공하는 개발자 도구를 통해서 해당 애플리케이션의 로딩이 어떻게 되는지 확인해 보기 바란다. 구글의 Chrome, 애플의 Safari와 같은 브라우저들은 훌륭한 웹 프로파일링 도구를 제공한다.
개발 언어, OS, DB, N/W, 서버 등 대충 알면 대충 튜닝할 수밖에 없다. 하지만, 이 모든 것의 전문가가 되기는 어렵다. 그러니 하나라도 전문가가 되어야 한다.
결과를 잘 정리하는 것은 매우 중요하다. 잘못하면 오랜 기간 동안 힘들게 작업한 것이 인정받지 못할 수도 있다. 결과 정리를 할 때 꼭 포함되어야 하는 내용은 다음과 같다.
이렇게 튜닝 결과를 정리할 때 몇 가지 유의사항이 있다.
결과 보고서를 작성할 때 그래프를 그릴 수도 있는데, 그래프는 신중하게 생각하면서 그리는 게 좋다. 대충 의미 없이 그래프 30개를 나열하는 것보다는, 그래프 하나로 모든 상황을 볼 수 있도록 그리는 것만큼 예술적인 것은 없다. 그래프를 액셀로 그릴 때 유의하는 사항은 다음과 같다.
전반적으로,
- 그래프의 타이틀은 반드시 추가하자. 그렇지 않으면 비슷한 다른 그래프와 혼동될 수도 있다.
- 그래프의 라벨(Label)은 가능하면 X축 하단에 넣자. 그래야 그래프의 내용을 보다 크게 보여줄 수 있다.
- 산포도(Scatter chart)를 보여줄 때, 데이터를 나타내는 각 점은 되도록이면 작게 표현하자. 그래야 데이터가 어떻게 분포되어 있는지를 쉽게 볼 수 있다.
Y축을 그릴 때,
- 정수 값일 경우 1,000단위에 콤마를 추가해 주자.
- 소수까지 내려가는 값일 경우 적어도 3자리를 보여 주자. 하지만 이 경우는 그때그때 다르다.
- 주 단위를 표시하는 경우에는 그래프 내에 주 단위가 4개 이상 표시되지 않는 것이 좋다. 그렇지 않으면, 그래프 데이터가 잘 보이지 않는다.
X축을 그릴 때,
- X축의 주 단위는 10개 내외로 보여 주는 것이 좋다.
- 주 단위로 선으로 보여 줄지, 눈금으로만 보여줄지는 상황에 맞게 결정하자.
참고