1. 성능과 최적화
성능 분석은 경험주의와 인간 심리학이 어울러진 부분입니다.
#
자바 성능 : 잘못된 방법과거 자바 초창기에는 메서드 디스패치 성능은 최악이였습니다. 그래서 메서드를 잘게 나누지 말고, 하나의 덩치 큰 메서드로 작성하는게 좋다라는 의견이 있었습니다.
그러나 시간이 지남에 따라 가상 디스패칭 성능이 엄청 좋아졌고, JVM에서는 자바 인라이닝 덕분에 가상 디스패치 조차 대부분의 호출에서 사라지게 되었습니다. 따라서 모든 코드를 한 메서드에 넣어서 작성하는 코드는 퇴물이 되어서 사라졌습니다.
시대에 따라 이렇게 성능 팁을 나열하는 것이 아니라 여러 가지 단면을 확인할 필요가 있습니다.
- 전체 소프트웨어 수명주기의 성능 방법론
- 성능과 연관된 테스트 이론
- 측정, 통계, 툴링(tooling) : 도구 선정
- (시스템 + 데이터) 분석 스킬
- 하부 기술과 매커니즘 : 장치, 수단
최적화하는 휴리스틱과 각종 코드 수준의 테크닉은 끝부분에서 작성합니다. 다만, 모든 최적화 기법에는 개발자가 사용하기 전에 알아둬야하는 함정과 트레이드 오프가 있기 때문에 신경써야합니다.
일반적인 원칙은 아래와 같습니다.
- JVM을 더 빨리 작동시키는 마법 스위치 같은 것은 없습니다.
- 자바를 더 빨리 실행하게 만드는 팁, 트릭은 없습니다.
- 사람들이 모르는 비밀 알고리즘은 없습니다.
#
자바 성능 개요자바는 실용적인 언어입니다. 그러한 대표적인 특징으로 서브 시스템을 예시로 들 수 있습니다.
- 개발자가 일일이 용량을 세세하게 관리하는 부담을 덜여주고, 주수준으로 제어 가능한 일부 기능을 포기합니다.
- JVM이 가비지 수집 서브시스템 형태로 메모리를 자동 관리하기 덕분에 프로그래머는 수동으로 메모리를 의식해서 개발할 필요가 없습니다.
- 런타임 동작에 복잡도를 유발합니다. (JVM에 의해)
다만, 자바 성능 측정을 위해서 잘못된 판단을 할 수 있으므로 조심해야합니다.
#
성능은 실험과학이다JVM 소프트웨어 스택은 아주 복잡합니다. 다만, 여러 성능 이슈가 발생할 수 있으나 최상의 성능을 제공하기 위해서는 어느 수준 이상의 스킬과 경험이 필요합니다.
JVM 성능 튜닝은 기술, 방법론, 정량적 측정값, 툴을 망라한 개념입니다. 일반적으로 아래와 같은 순서로 진행합니다.
- 원하는 결과를 정의합니다.
- 기존 시스템을 측정합니다.
- 요건을 충족시키려면 무슨 일을 해야 할지 정합니다.
- 개선 활동을 추진합니다.
- 다시 테스트합니다.
- 목표가 달성됐는지 판단합니다.
성능 분석은 통계치에 큰거해 적절히 결과를 처리하는 활동입니다. 이에 대한 자세한 내용은 5장에서 이야기합니다.
#
성능 분류성능 지표는 아래와 같습니다.
- 처리율
- 지연
- 용량
- 사용률
- 확장성
- 저하
다만 이를 수행할 때마다, 좋아야 2~3개 지표가 개선이 되고, 한 지표를 개선했다가 다른 지표들이 악화되는 경우도 있습니다.
#
처리율처리율(throughput)
은 서브 시스템이 수행 가능한 작업 비율을 나타낸 지표입니다. (일정 시간동안 완료한 작업 단위 수)
- 플랫폼에 대한 내용도 기술해야합니다. (HW, OS, SW 스택, 단일 서버인지 혹은 클러스터 환경인지)
#
지연성능 지표를 일종의 수도 패관에 빗대어 설명가능한데, 지연(latency)
은 수도관 자체의 길이를 의미합니다. 하나의 트랜잭션을 처리하고 그 결과를 반대편 수도관 끝에서 바라볼 때까지 소요된 시간입니다.
#
용량용량(capacity)
는 시스템이 보유한 작업 병렬성의 총량, 즉 시스템이 동시 처리 가능한 작업 단위(트랜잭션) 개수를 의미합니다.
시스템에 동시 부하가 증가할수록 처리율도 당연히 영향을 받습니다. 이러한 이유로 보통 용량은 어떤 처리율 또는 지연 값을 전제로 가능한 처리량을 표시합니다.
#
사용률성능 분석 업무 중 가장 흔한 태스크는 시스템 리소스를 효율적으로 활용하는 것입니다. CPU 리소스가 실제 작업 단위를 처리하는데 쓰여야합니다.
사용률(utilization)
은 워크로드에 따라서 리소스별로 들쑥날쑥합니다.
#
효율전체 시스템의 효율(efficiency)
은 처리율을 리소스 사용률로 나눈 값으로 측정합니다.
#
확장성처리율이나 시스템 용량은 처리하는데 끌어 쓸 수 있는 리소스에 달려있습니다. 리소스 추가에 따른 처리율 변화는 시스템/애플리케이션의 확장성(scalability)
을 가늠하는 척도입니다. 시스템 확장성은 리소스를 투입한 만큼 처리율이 변경되는 형태를 지향합니다.
그러나 일반적으로 확장성은 여러 가지 인자들의 영향을 받습니다. 리소스를 어느 정도까지 늘리면 선형적으로 확장되지만, 대부분 부하가 높아지면 한계점에 봉착합니다.
#
저하요청 개수가 증가하거나 접수 속도가 증가하면, 시스템이 더 많은 부하를 받아 지연과 처리율 측정값에 변화가 생깁니다.
변화는 사용률에 따라 다릅니다. 시스템을 덜 사용하고 있으면 측정값이 느슨하게 변하지만, 시스템이 풀 가동된 상태면 처리율이 더 늘어나지 않는 양상을 가집니다. 이러한 현상을 부하 증가에 따른 저하(degradation)
이라고 합니다.
#
측정값 사이의 연관 관계다양한 성능 측정값은 어떤 식으로 연결되어 있습니다.
- 부하에 따라 여러 측정값이 요동칠 수 있습니다.
- 확장성과 저하는 부하가 증가함에 변화됩니다.
#
성능 그래프 읽기부하가 증가하면서 예기치 않은 저하(지연)이 발생하는 그래프를 확인할 수 있으며 이러한 형태를 보통 성능 엘로(performance elbow)
입니다.
이와는 반대로 장비 추가에 따라 거의 선형으로 처리율이 확장되는 운좋은 케이스가 있습니다. 다만 대부분 암달의 법칙과 비슷합니다.
GC 이후 힙 사용량은 아래와 같은 것이 좋습니다.
그러나 문제가 있는 그래프는 아래와 같습니다. (피보나치를 실행한 그래프)