| 표지 설명 | 표지 동물은 마코르 염소markhor goat다. 야생 염소인 이 종은 턱수염과 우뚝 솟은 나선형 뿔로 유명 하며, 주로 서부 및 중앙아시아의 산악 지대 높은 고도의 산림에 서식한다. 마코르는 풀, 잎, 허브, 과일, 꽃 등 다양한 초목을 주로 먹는 초식 동물이다. 다른 야생 염소처 럼 나무에서 과일이나 꽃, 풀 등을 먹고 배설물을 통해 씨앗을 뿌리므로 생태계 내에서 중요한 역할을 한다. 짝짓기 시즌은 겨울이며, 이후의 출생은 4월말에서 6월 초순으로 1~2마리의 새끼를 낳는다. 성숙 한 수컷은 대체로 숲속에서 홀로 지내며 암컷과 새끼들은 경사가 높은 암벽으로 이루어진 숲에서 무 리 지어 산다. 오라일리 책 표지에 등장하는 동물 대다수는 멸종 위기종이며, 이들 모두 세상에서 중요한 존재다. 이들을 돕는 방법을 알 고 싶다면 animals.oreilly.com을 방문해보자. 표지 이미지는 『Riverside Natural History』에서 가져왔다.
자바 최적화 가장 빠른 성능을 구현하는 검증된 10가지 기법 초판 1쇄 발행 2019년 4월 29일 지은이 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드 / 옮긴이 이일웅 / 펴낸이 김태헌 펴낸곳 한빛미디어 (주) / 주소 서울시 서대문구 연희로2길 62 한빛미디어(주) IT출판사업부 전화 02 – 325 – 5544 / 팩스 02 – 336 – 7124 등록 1999년 6월 24일 제25100 – 2017 – 000058호 / ISBN 979 – 11 – 6224 – 177-6 93000 총괄 전태호 / 책임편집 이상복 / 기획 이상복 / 편집 서현 디자인 표지 신종식 내지 김연정 조판 김민정 영업 김형진, 김진불, 조유미 / 마케팅 송경석, 김나예, 이행은 / 제작 박성우, 김정우 이 책에 대한 의견이나 오탈자 및 잘못된 내용에 대한 수정 정보는 한빛미디어(주)의 홈페이지나 아래 이메일로 알려주십시오. 잘못된 책은 구입하신 서점에서 교환해드립니다. 책값은 뒤표지에 표시되어 있습니다. 한빛미디어 홈페이지 www.hanbit.co.kr / 이메일 ask@hanbit.co.kr © 2019 Hanbit Media Inc.
Authorized Korean translation of the English edition of Optimizing Java, ISBN 9781492025795 © 2018 Chris Newland, James Gough, and Benjamin J Evans This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same. 이 책의 저작권은 오라일리와 한빛미디어 (주)에 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 무단 복제를 금합니다.
지금 하지 않으면 할 수 없는 일이 있습니다. 책으로 펴내고 싶은 아이디어나 원고를 메일 ( writer@hanbit.co.kr ) 로 보내주세요. 한빛미디어(주)는 여러분의 소중한 경험과 지식을 기다리고 있습니다.
지은이 소개
지은이
벤저민 J. 에번스 Benjamin J. Evans
데브옵스 팀을 위한 성능 툴 개발사인 jClarity의 공동 창업자이자 기술 위원입니다. 자바 커 뮤니티 프로세스 집행 위원회에서 런던 자바 커뮤니티 대표로 활동하며 자바 생태계의 표준을 제정하는 일을 했습니다. 자바 챔피언, 자바원 록스타인 그는 『The Well-Grounded Java
Developer』(매닝, 2012년)를 공동 집필했고 자바 플랫폼, 동시성, 기타 관련된 주제로 강연 을 계속해오고 있습니다.
지은이
제임스 고프 James Gough
자바 개발자 및 저자입니다. 워릭 대학교에 다니던 중 처음 자바에 매료되어, 졸업 후 런던 자 바 커뮤니티에 가입했고 그때부터 이 커뮤니티를 중심으로 수년간 JSR-310 설계/테스트를 담 당하며 JCP 집행 위원회에서 활동했습니다. 콘퍼런스 상임 연사이기도 한 그는 현재 모건 스탠 리에서 고객 응대 기술 구축에 매진하고 있습니다. 세계 각지를 돌며 다양한 나라에서 오랫동 안 자바, C++를 가르쳐왔습니다.
지은이
크리스 뉴랜드 Chris Newland
자바 기술을 응용해 실시간 주식 데이터를 처리하는 ADVFN 사이트의 선임 자바 개발자입니 다. 핫스팟 JVM 내부에서 이루어지는 JIT (적시) 컴파일 결정을 시각화하는 오픈 소스 로그 분석기, JITWatch 프로젝트의 저작자입니다. 자바 챔피언인 그는 여러 콘퍼런스에서 JIT 컴 파일 기술 강연을 해오고 있습니다.
4
옮긴이 소개
옮긴이
이일웅 leeilwoong@gmail.com
13여 년 동안 자바/스칼라 개발자, 애플리케이션 아키텍트로 활동하며 엔터프라이즈 프로젝트 현장을 누벼온 야전형 정보 기술자이자, 한 여인과 두 딸의 사랑을 한 몸에 받고 사는 행복한 딸바보입니다. 2014년 이후로 십 수 권의 IT 전문서를 번역하며 동료, 후배 개발자들과 지식, 경험을 나누는 일에도 힘쓰고 있습니다. 시간이 나면 피아노를 연주합니다.
5
옮긴이의 말
자바 언어로 작성된 애플리케이션 성능이 문제일 때 자바 내부의 메커니즘과 작동 원리를 제대 로 모르는 엔지니어는 할 수 있는 일이 별로 없습니다. 성능 툴에 표시된 각종 수치와 그래프는 눈에 보이지 않는 저수준에서 수십, 수백 가지 사건들이 서로 조합돼 나타난 스냅샷일 뿐이니 까요. 그렇다고 20년이 넘는 세월 동안 수많은 대가의 손을 거쳐 진화해온 자바/JVM을 일반 엔지니 어가 처음부터 속속들이 다 이해하기란 거의 불가능합니다. 또 성능 엔지니어가 아닌, 일반 응 용 프로그래머가 자바/JVM 소스 코드(C++)를 낱낱이 분석하며 작동 원리를 섭렵할 필요는 없겠죠. 사실, 빠듯한 개발 프로젝트 현장에서 그럴 만한 시간을 내기도 어렵습니다. 그런 점에서 이 책은 주로 애플리케이션 성능을 높이는 ‘자바 최적화Optimizing Java’ 기법을 설명 하지만, 지금까지 언어 구문상의 자바 사용법만 익혀 온 많은 자바 개발자가 ‘자바 해부학Java ’에 입문해 미시적인 세계에 관심을 가지게 할 흥미로운 내용으로 가득합니다. 특히, 바
anatomy
이트코드, JMM, 가비지 수집기 등의 고급 주제는 시중에 출간된 대부분의 자바 도서에서 거의 다루지 않는 내용이므로 자바 기본기를 익힌 중/고급자 개발자분들께는 희소성의 가치가 높은 책입니다. 원래 성능이란 주제 자체가 워낙 광범위한 까닭에 너무 많은 요소가 심하게 응축된 느낌도 없 잖지만, 이 책에서 소개된 주요 개념과 각종 용어를 출발점 삼아 다음 학습을 진행하면 자바를 ‘좀 아는’ 분들이 ‘진짜 많이, 깊이 아는’ 경지로 발전할 수 있을 거라고 확신합니다. 절대 평범하지 않은 주제인지라, 기술 용어부터 번역하기가 쉽지 않았고 군데군데 의미를 온전 히 전달하지 못한 곳도 있겠지만, 이제 우리나라 출판계에도 이런 고급 전문서가 더 많이 소개 되었으면 하는 바람으로 열심히 옮겼습니다. 역자의 부족함으로 인한 오역이나 불분명한 표현 이 있더라도 여러분의 넓은 양해 부탁드리며, 한빛미디어 홈페이지를 통해 알려주시면 적극적 으로 보완하여 더 완성도 높은 역서로 가꾸겠습니다.
6
2018년 내내 『스프링 5 레시피』(한빛미디어, 2018 )와 이 책 원고를 작업하느라 많은 시간을 함께 보내지 못한 아내와 제이, 솔이 두 딸아이에게 미안한 마음, 고마운 마음 가득 담아 이 책 을 바칩니다. 2018년 끝무렵, 몹시 추운 어느 날에
이일웅
7
감사의 말
제 아내 애나에게 이 책을 바칩니다. 멋진 그림도 그려주고 군데군데 첨삭도 해주고, 그녀는 제 가 가장 먼저 아이디어를 함께 나눈 사람이었습니다. - 벤저민 J. 에번스
이 책을 제가 너무나도 사랑하는 가족, 메건, 에밀리, 애나에게 바칩니다. 가족의 배려와 뒷받 침이 없었다면 이 책을 쓸 엄두는 감히 내지 못했을 겁니다. 늘 제가 새로운 걸 배우게 북돋워 주시고 변함없는 지원을 아끼지 않으신 부모님 폴 고프 옹, 헤더 고프 여사께도 감사의 말씀 올 립니다. 또 공동 집필하면서 올바른 방향으로 이끌어준 벤저민 에번스 씨, 고맙습니다. 당신과 다시 함께 일하게 돼서 정말 유쾌했습니다. - 제임스 고프
제가 책을 쓸 수 있게 격려와 성원을 아끼지 않은 아내 리나와 앞으로 호기심이 가득한 아이들 로 성장할 두 아들, 조슈아, 휴고에게 이 책을 바칩니다. - 크리스 뉴랜드
8
들어가며
당신은 성능performance이 무엇이라고 생각하십니까? 개발자들에게 애플리케이션의 성능에 대해 물어보면 제일 먼저 속도 측정을 떠올립니다. 초 당 트랜잭션 처리 수나 몇 기가바이트의 데이터를 처리했는지 등 ‘짧은 시간에 얼마나 많은 일 을 했느냐?’를 나타내는 지표로 판단하죠. 하지만 여러분이 애플리케이션 아키텍트application architect
(AA )라면 이보다 훨씬 넓은 의미의 지표를 측정해야 합니다. 그냥 순차적으로 실행되는
프로그램 흐름보다 리소스(자원) 사용률을 더 주의 깊게 봐야 할 때도 있고, 서비스 자체보다 여러 서비스 간의 연결 성능이 더 중요한 관심사인 경우도 있습니다. 사내 비즈니스 요건이 정 해지면 애플리케이션 성능은 더 이상 초 단위가 아닌, 금액으로 환산해서 생각해야 합니다. 그 과정에서 데브옵스팀 운영 비용과 업무 소요 시간을 저울질하며 개발자, 아키텍트들과 언쟁을 벌이기도 하지요. 여러분이 어떤 역할을 맡은 사람이건 이 모든 지표는 중요합니다. 필자는 1996년에 자바 애플리케이션 개발을 시작했습니다. 처음엔 미네소타 대학교 경영대학 원에서 애플스크립트AppleScript CGI를 구축해 웹 개발팀이 쓰는 서버 사이드 펄 애플리케이션을 관리했죠. 당시 자바는 이제 막 최초 안정 버전인 1.0.2가 출시되었고 필자는 뭔가 쓸 만한 개 발 도구는 없는지 찾아보고 있었습니다. 그 시절, 자바 애플리케이션의 성능을 끌어올리는 최고의 방법은 다른 언어로 코딩하는 것이었 습니다. JIT 컴파일러나 병렬/동시성 GC도 없던 원시 시대였고, 지금처럼 자바가 서버 분야를 점령하기 훨씬 전이었으니 그럴 만도 했죠. 하지만 많은 개발자가 자바를 제대로 써보고 싶어 했고 우리는 어떻게든 코드가 매끄럽게 잘 돌아가게 갖은 꼼수를 동원했습니다. 가비지 수집은 느리고 종종 끊어지기도 해서 객체를 풀링, 재사용하는 식으로 해결했고 엄청나게 많은 전역 상태와 정적 메서드로 도배를 했습니다. 진짜 끔찍한 자바 코드를 짰지만, 여하튼 한동안은 잘 작동했습니다.
9
그러던 중 1999년부터 변화가 찾아왔습니다. 속도를 따라잡기 위해 고군분투했던 수년간의 자바 개발 시절을 뒤로하고 드디어 JIT 기술이 등장하게 됐죠. 메서드 인라이닝inlining (인라인화) 기능이 컴파일러에 추가돼서 이제 메서드 호 출 횟수보다 거대한 코드 덩이를 잘게 나누는 일이 더 중요해졌습니다. 우리는 흔쾌히 객체 지 향 설계를 수용해 기존 메서드를 아주 잘게 쪼개고 모든 코드를 인터페이스로 감쌌습니다. JIT 컴파일러가 선호하는 좋은 자바 코드를 작성했기 때문에 매번 자바 새 버전이 나올 때마다 조 금씩 작동 결과가 좋아지는 모습을 지켜보며 환호성을 질러댔죠. 이윽고 자바는 서버 분야에서 도 두각을 드러내며 더 크고 복잡한 애플리케이션을 더 풍성한 추상화 기술로 제작할 수 있는 여건이 조성됐습니다. 가비지 수집기garbage collector (GC ) 역시 빠른 속도로 성능이 향상됐습니다. 이제는 풀링 오버헤 드로 인한 할당 비용은 미미한 수준이고 멀티스레드 연산을 지원하는 가비지 수집기도 여럿 있 습니다. 애플리케이션과 독립적으로 움직이며 중단 시간이 짧은, 거의 동시에 작동하는 가비지 수집기도 차츰 등장하기 시작했죠. 개발자가 마음껏 객체를 만들고 쓰다가 버리면 뒷일은 똑똑 한 가비지 수집기가 알아서 잘 처리하게끔 맡겨두는 것이 표준 관례로 자리 잡혔습니다. 음, 이 또한 얼마간은 별문제가 없었죠. 늘 그렇듯, 기술은 스스로를 무효화하는 것이 문제입니다. JIT와 GC 기술이 점점 발전하면서 애플리케이션 성능을 어떻게 개선해야 할지 방향을 정하기 어려워졌고, JVM이 코드를 최적화 하고 객체를 거의 자유롭게 풀어주었음에도 애플리케이션 요건은 점점 늘었습니다. 대부분은, 작은 메서드를 적절히 인라이닝하고 인터페이스 및 타입 체크는 저렴하게 처리하면 서 JIT 컴파일러가 만든 네이티브 코드는 간결하고 효율적으로 유지하는, ‘좋은’ 코딩 패턴을 따르는 게 맞습니다. 그러나 경우에 따라 사람이 직접 코드를 작성하고 컴파일러 및 CPU 한계 를 감안해 추상화와 아키텍처를 재조정해야 할 때도 있습니다. 물론 객체는 정말 자유로운 데 다 그들이 메모리 대역폭bandwidth과 GC 사이클을 소비한다는 사실조차 무시해도 좋을 때도 있 습니다. 하지만, 최상품 GC나 메모리 서브시스템에도 부하를 일으키는 테라바이트급(또는 그
10
이상) 데이터셋dataset을 처리해야 할 경우도 생기기 마련입니다. 오늘날 성능 문제를 해결하려면 툴 사용법을 익혀야 합니다. 자바 언어의 작동 원리는 말할 것 도 없고 애플리케이션이 상호작용하는 JVM 라이브러리, 메모리, 컴파일러, GC, 심지어 하드 웨어 지식까지 총동원해야 합니다. 필자는 제이루비JRuby 프로젝트를 하는 동안 JVM에 관한 불 변의 진리 한 가지를 깨달았습니다. 모든 성능 문제는 한 가지 정답이 있는 게 아니라 여러 개 정답이 있다는 사실이죠. 가능한 해결책을 찾고 그중 요건에 가장 알맞은 해결책을 조합하는 게 바로 기술입니다. 지금 여러분의 손에는 한바탕 성능 전투에 임하기 전에 필요한 비밀 병기, 즉 이 책이 들려 있습니다. 자, 동료 여러분! 지금부터 책장을 넘기며 풍성한 툴과 재미난 기법들을 하나씩 섭렵하세요. 가 용 리소스를 바탕으로 균형 있게 애플리케이션을 설계하는 방법을 배우세요. JVM을 모니터링 하고 튜닝하는 기술을 습득하기 바랍니다. 한물간 라이브러리, 패턴보다 훨씬 효율적인, 최신 자바 기술의 활용법을 터득하세요. 자바로 무궁무진한 가능성을 파헤쳐보시길! 지금이 자바 개발자에게 가장 흥분되는 시기 아닐까요? 지금처럼 자바 플랫폼으로 다재다능 하고 응답성 좋은 애플리케이션을 구축할 기회가 많았던 적은 한번도 없었습니다. 건투를 빕 니다! 찰리 누터 레드햇 미들웨어 수석 소프트웨어 엔지니어
11
CONTENTS
지은이 소개 ������������������������������������������������������������������������������������������������������������������������� 4 옮긴이 소개 ������������������������������������������������������������������������������������������������������������������������� 5 옮긴이의 말 ������������������������������������������������������������������������������������������������������������������������� 6 감사의 말 ����������������������������������������������������������������������������������������������������������������������������� 8 들어가며 ������������������������������������������������������������������������������������������������������������������������������ 9
CHAPTER
1 성능과 최적화 1.1 자바 성능: 잘못된 방법................................................................................................... 26 1.2 자바 성능 개요............................................................................................................... 28 1.3 성능은 실험과학이다....................................................................................................... 29 1.4 성능 분류....................................................................................................................... 30 1.4.1 처리율................................................................................................................... 31 1.4.2 지연...................................................................................................................... 31 1.4.3 용량...................................................................................................................... 32 1.4.4 사용률................................................................................................................... 32 1.4.5 효율...................................................................................................................... 32 1.4.6 확장성................................................................................................................... 33 1.4.7 저하...................................................................................................................... 33 1.4.8 측정값 사이의 연관 관계............................................................................................ 33
1.5 성능 그래프 읽기............................................................................................................ 35 1.6 마치며........................................................................................................................... 39
CHAPTER
2 JVM 이야기 2.1 인터프리팅과 클래스로딩................................................................................................ 41 2.2 바이트코드 실행............................................................................................................. 43 2.3 핫스팟 입문................................................................................................................... 48
12
2.3.1 JIT 컴파일이란?...................................................................................................... 50
2.4 JVM 메모리 관리........................................................................................................... 52 2.5 스레딩과 자바 메모리 모델(JMM).................................................................................... 53 2.6 JVM 구현체 종류........................................................................................................... 55 2.6.1 JVM 라이선스......................................................................................................... 57
2.7 JVM 모니터링과 툴링..................................................................................................... 58 2.7.1 VisualVM.............................................................................................................. 59
2.8 마치며........................................................................................................................... 62
CHAPTER
3 하드웨어와 운영체제 3.1 최신 하드웨어 소개......................................................................................................... 64 3.2 메모리........................................................................................................................... 65 3.2.1 메모리 캐시............................................................................................................ 66
3.3 최신 프로세서의 특성..................................................................................................... 72 3.3.1 변환 색인 버퍼(TLB)................................................................................................. 72 3.3.2 분기 예측과 추측 실행............................................................................................... 73 3.3.3 하드웨어 메모리 모델................................................................................................ 73
3.4 운영체제........................................................................................................................ 75 3.4.1 스케줄러................................................................................................................ 76 3.4.2 시간 문제............................................................................................................... 78 3.4.3 컨텍스트 교환......................................................................................................... 79
3.5 단순 시스템 모델............................................................................................................ 81 3.6 기본 감지 전략............................................................................................................... 82 3.6.1 CPU 사용률........................................................................................................... 82 3.6.2 가비지 수집............................................................................................................ 84 3.6.3 입출력................................................................................................................... 85 3.6.4 기계 공감............................................................................................................... 87
13
CONTENTS
3.7 가상화........................................................................................................................... 88 3.8 JVM과 운영체제............................................................................................................. 90 3.9 마치며........................................................................................................................... 92
CHAPTER
4 성능 테스트 패턴 및 안티패턴 4.1 성능 테스트 유형............................................................................................................ 93 4.1.1 지연 테스트............................................................................................................ 95 4.1.2 처리율 테스트......................................................................................................... 95 4.1.3 부하 테스트............................................................................................................ 96 4.1.4 스트레스 테스트. ..................................................................................................... 96 4.1.5 내구 테스트............................................................................................................ 96 4.1.6 용량 계획 테스트...................................................................................................... 97 4.1.7 저하 테스트............................................................................................................ 97
4.2 기본 베스트 프랙티스..................................................................................................... 98 4.2.2 테스트 환경 구축...................................................................................................... 99 4.2.3 성능 요건 식별. .................................................................................................... 100 4.2.4 자바에 특정한 이슈................................................................................................ 101 4.2.5 SDLC 일부로 성능 테스트 수행하기........................................................................ 102
4.3 성능 안티패턴 개요...................................................................................................... 102 4.3.1 지루함................................................................................................................ 103 4.3.2 이력서 부풀리기. .................................................................................................. 104 4.3.3 또래 압박............................................................................................................ 104 4.3.4 이해 부족............................................................................................................ 104 4.3.5 오해와 있지도 않은 문제......................................................................................... 105
4.4 성능 안티패턴 카탈로그............................................................................................... 106 4.4.1 화려함에 사로잡히다.............................................................................................. 106 4.4.2 단순함에 사로잡히다.............................................................................................. 107
14
4.4.3 성능 튜닝 도사. .................................................................................................... 108 4.4.4 민간 튜닝............................................................................................................ 109 4.4.5 안되면 조상 탓. .................................................................................................... 111 4.4.6 숲을 못 보고 나무만 보다........................................................................................ 112 4.4.7 내 데스크톱이 UAT............................................................................................... 114 4.4.8 운영 데이터처럼 만들기는 어려워............................................................................. 116
4.5 인지 편향과 성능 테스트.............................................................................................. 118 4.5.1 환원주의............................................................................................................. 119 4.5.2 확증 편향............................................................................................................ 119 4.5.3 전운의 그림자(행동 편향)........................................................................................ 120 4.5.4 위험 편향............................................................................................................ 121 4.5.5 엘스버그 역설...................................................................................................... 122
4.6 마치며........................................................................................................................ 123
CHAPTER
5 마이크로벤치마킹과 통계 5.1 자바 성능 측정 기초.................................................................................................... 126 5.2 JMH 소개................................................................................................................... 131 5.2.1 될 수 있으면 마이크로벤치마크하지 말지어다(실화)..................................................... 131 5.2.2 휴리스틱: 마이크로벤치마킹은 언제 하나?................................................................. 132 5.2.3 JMH 프레임워크.................................................................................................. 134 5.2.4 벤치마크 실행...................................................................................................... 135
5.3 JVM 성능 통계............................................................................................................ 142 5.3.1 오차 유형............................................................................................................ 143 5.3.2 비정규 통계학...................................................................................................... 148
5.4 통계치 해석................................................................................................................ 152 5.5 마치며........................................................................................................................ 157
15
CONTENTS
CHAPTER
6 가비지 수집 기초 6.1 마크 앤 스위프............................................................................................................ 160 6.1.1 가비지 수집 용어................................................................................................... 162
6.2 핫스팟 런타임 개요...................................................................................................... 164 6.2.1 객체를 런타임에 표현하는 방법................................................................................ 165 6.2.2 GC 루트 및 아레나............................................................................................... 169
6.3 할당과 수명................................................................................................................ 170 6.3.1 약한 세대별 가설................................................................................................... 170
6.4 핫스팟의 가비지 수집.................................................................................................. 173 6.4.1 스레드 로컬 할당................................................................................................... 173 6.4.2 반구형 수집......................................................................................................... 174
6.5 병렬 수집기................................................................................................................ 176 6.5.1 영 세대 병렬 수집.................................................................................................. 176 6.5.2 올드 세대 병렬 수집............................................................................................... 178 6.5.3 병렬 수집기의 한계................................................................................................ 179
6.6 할당의 역할................................................................................................................ 181 6.7 마치며........................................................................................................................ 187
CHAPTER
7 가비지 수집 고급 7.1 트레이드오프와 탈착형 수집기..................................................................................... 190 7.2 동시 GC 이론............................................................................................................. 191 7.2.1 JVM 세이프포인트................................................................................................ 192 7.2.2 삼색 마킹............................................................................................................ 194
7.3 CMS.......................................................................................................................... 197 7.3.1 CMS 작동 원리.................................................................................................... 198 7.3.2 CMS 기본 JVM 플래그......................................................................................... 201
16
7.4 G1............................................................................................................................. 201 7.4.1 G1 힙 레이아웃 및 영역......................................................................................... 202 7.4.2 G1 알고리즘 설계................................................................................................. 204 7.4.3 G1 단계.............................................................................................................. 205 7.4.4 G1 기본 JVM 플래그............................................................................................ 206
7.5 셰난도아..................................................................................................................... 207 7.5.1 동시 압착............................................................................................................ 209 7.5.2 셰난도아 얻기...................................................................................................... 209
7.6 C4(아줄 징)................................................................................................................ 210 7.6.1 로드값 배리어...................................................................................................... 212
7.7 밸런스드(IBM J9)........................................................................................................ 214 7.7.1 J9 객체 헤더........................................................................................................ 215 7.7.2 밸런스드에서 큰 배열 처리하기................................................................................ 217 7.7.3 NUMA와 밸런스드............................................................................................... 218
7.8 레거시 핫스팟 수집기.................................................................................................. 219 7.8.1 Serial 및 Serial Old............................................................................................. 219 7.8.2 증분 CMS(iCMS)................................................................................................. 219 7.8.3 디프리케이트되어 사라진 GC 조합.......................................................................... 220 7.8.4 엡실론................................................................................................................ 221
7.9 마치며........................................................................................................................ 222
CHAPTER
8 GC 로깅, 모니터링, 튜닝, 툴 8.1 GC 로깅 개요............................................................................................................. 223 8.1.1 GC 로깅 켜기...................................................................................................... 224 8.1.2 GC 로그 vs JMX................................................................................................. 225 8.1.3 JMX의 단점......................................................................................................... 226 8.1.4 GC 로그 데이터의 장점......................................................................................... 227
17
CONTENTS
8.2 로그 파싱 툴............................................................................................................... 228 8.2.1 센섬................................................................................................................... 228 8.2.2 GCViewer.......................................................................................................... 231 8.2.3 같은 데이터를 여러 가지 형태로 시각화하기............................................................... 232
8.3 GC 기본 튜닝............................................................................................................. 233 8.3.1 할당이란?............................................................................................................ 235 8.3.2 중단 시간이란?..................................................................................................... 238 8.3.3 수집기 스레드와 GC 루트...................................................................................... 239
8.4 Parallel GC 튜닝......................................................................................................... 242 8.5 CMS 튜닝.................................................................................................................. 243 8.5.1 단편화로 인한 CMF.............................................................................................. 246
8.6 G1 튜닝...................................................................................................................... 247 8.7 jHiccup...................................................................................................................... 249 8.8 마치며........................................................................................................................ 252
CHAPTER
9 JVM의 코드 실행 9.1 바이트코드 해석.......................................................................................................... 254 9.1.1 JVM 바이트코드 개요............................................................................................ 257 9.1.2 단순 인터프리터. .................................................................................................. 264 9.1.3 핫스팟에 특정한 내용............................................................................................. 266
9.2 AOT와 JIT 컴파일....................................................................................................... 268 9.2.1 AOT 컴파일. ....................................................................................................... 268 9.2.2 JIT 컴파일........................................................................................................... 269 9.2.3 AOT 컴파일 vs JIT 컴파일..................................................................................... 270
9.3 핫스팟 JIT 기초........................................................................................................... 272 9.3.1 klass 워드, vtable, 포인터 스위즐링........................................................................ 272 9.3.2 JIT 컴파일 로깅.................................................................................................... 273
18
9.3.3 핫스팟 내부의 컴파일러.......................................................................................... 275 9.3.4 핫스팟의 단계별 컴파일.......................................................................................... 276
9.4 코드 캐시.................................................................................................................... 277 9.4.1 단편화................................................................................................................ 278
9.5 간단한 JIT 튜닝법....................................................................................................... 279 9.6 마치며........................................................................................................................ 280
CHAPTER
10 JIT 컴파일의 세계로 10.1 JITWatch란?............................................................................................................ 281 10.1.1 기본적인 JITWatch 뷰........................................................................................ 283 10.1.2 디버그 JVM과 hsdis.......................................................................................... 288
10.2 JIT 컴파일 개요........................................................................................................ 289 10.3 인라이닝................................................................................................................... 290 10.3.1 인라이닝 제한.................................................................................................... 291 10.3.2 인라이닝 서브시스템 튜닝..................................................................................... 293
10.4 루프 펼치기.............................................................................................................. 294 10.4.1 루프 펼치기 정리................................................................................................. 297
10.5 탈출 분석................................................................................................................. 297 10.5.1 힙 할당 제거...................................................................................................... 298 10.5.2 락과 탈출 분석. .................................................................................................. 300 10.5.3 탈출 분석의 한계................................................................................................. 302
10.6 단형성 디스패치........................................................................................................ 305 10.7 인트린직................................................................................................................... 310 10.8 온-스택 치환............................................................................................................ 312 10.9 세이프포인트 복습.................................................................................................... 315 10.10 코어 라이브러리 메서드.......................................................................................... 316 10.10.1 인라이닝하기 적합한 메서드 크기 상한.................................................................. 316
19
CONTENTS
10.10.2 컴파일하기 적합한 메서드 크기 상한..................................................................... 321
10.11 마치며................................................................................................................... 323
CHAPTER
11 자바 언어의 성능 향상 기법 11.1 컬렉션 최적화........................................................................................................... 326 11.2 List 최적화............................................................................................................... 328 11.2.1 ArrayList.......................................................................................................... 329 11.2.2 LinkedList........................................................................................................ 330 11.2.3 ArrayList vs LinkedList..................................................................................... 330
11.3 Map 최적화.............................................................................................................. 332 11.3.1 HashMap........................................................................................................ 332 11.3.2 TreeMap.......................................................................................................... 335 11.3.3 MultiMap은 없어요............................................................................................ 336
11.4 Set 최적화............................................................................................................... 336 11.5 도메인 객체.............................................................................................................. 337 11.6 종료화 안 하기.......................................................................................................... 341 11.6.1 무용담: 정리하는 걸 깜빡하다................................................................................ 343 11.6.2 왜 종료화로 문제를 해결하지 않을까?..................................................................... 343 11.6.3 try-with-resources.......................................................................................... 347
11.7 메서드 핸들.............................................................................................................. 352 11.8 마치며...................................................................................................................... 356
CHAPTER
12 동시 성능 기법 12.1 병렬성이란?............................................................................................................. 359 12.1.1 자바 동시성 기초................................................................................................. 361
20
12.2 JMM의 이해............................................................................................................. 364 12.3 동시성 라이브러리 구축............................................................................................. 370 12.3.1 Unsafe............................................................................................................. 372 12.3.2 아토믹스와 CAS................................................................................................ 373 12.3.3 락과 스핀락....................................................................................................... 375
12.4 동시 라이브러리 정리................................................................................................ 376 12.4.1 java.util.concurrent 락....................................................................................... 376 12.4.2 읽기/쓰기 락...................................................................................................... 378 12.4.3 세마포어........................................................................................................... 380 12.4.4 동시 컬렉션....................................................................................................... 381 12.4.5 래치와 배리어.................................................................................................... 382
12.5 실행자와 태스크 추상화............................................................................................. 384 12.5.1 비동기 실행이란?................................................................................................ 384 12.5.2 ExecutorService 선택하기................................................................................. 386 12.5.3 포크/조인.......................................................................................................... 387
12.6 최신 자바 동시성...................................................................................................... 389 12.6.1 스트림과 병렬 스트림........................................................................................... 390 12.6.2 락-프리 기법...................................................................................................... 391 12.6.3 액터 기반 기법. .................................................................................................. 392
12.7 마치며...................................................................................................................... 394
CHAPTER
13 프로파일링 13.1 프로파일링 개요........................................................................................................ 398 13.2 샘플링과 세이프포인팅 편향...................................................................................... 399 13.3 개발자용 프로파일링 툴............................................................................................. 402 13.3.1 VisualVM 프로파일러......................................................................................... 402 13.3.2 JProfiler........................................................................................................... 403
21
CONTENTS
13.3.3 YourKit............................................................................................................ 409 13.3.4 JFR/JMC......................................................................................................... 410 13.3.5 운영 툴............................................................................................................. 413
13.4 최신 프로파일러........................................................................................................ 417 13.5 할당 프로파일링........................................................................................................ 422 13.6 힙 덤프 분석............................................................................................................. 429 13.6.1 hprof............................................................................................................... 431
13.7 마치며...................................................................................................................... 432
CHAPTER
14 고성능 로깅 및 메시징 14.1 로깅......................................................................................................................... 434 14.1.1 로깅 벤치마크.................................................................................................... 435
14.2 성능에 영향이 적은 로거 설계하기............................................................................. 439 14.3 리얼 로직 라이브러리를 이용해 지연 줄이기............................................................... 442 14.3.1 아그로나........................................................................................................... 443 14.3.2 단순 바이너리 인코딩........................................................................................... 450 14.3.3 에어론.............................................................................................................. 454 14.3.4 에어론의 설계 개념.............................................................................................. 457
14.4 마치며...................................................................................................................... 463
CHAPTER
15 자바 9와 미래 15.1 자바 9에서 소소하게 개선된 성능............................................................................... 466 15.1.1 코드 캐시 세그먼트화........................................................................................... 466 15.1.2 콤팩트 스트링.................................................................................................... 467 15.1.3 새로운 스트링 연결.............................................................................................. 468
22
15.1.4 C2 컴파일러 개선............................................................................................... 470 15.1.5 G1 새 버전........................................................................................................ 472
15.2 자바 10과 그 이후 버전............................................................................................. 472 15.2.1 새로운 릴리즈 절차.............................................................................................. 472 15.2.2 자바 10............................................................................................................ 473
15.3 자바 9 Unsafe 그 너머.............................................................................................. 475 15.3.1 자바 9의 VarHandle........................................................................................... 477
15.4 발할라 프로젝트와 값 타입........................................................................................ 478 15.5 그랄과 트러플........................................................................................................... 483 15.6 바이트코드의 향후 발전 방향..................................................................................... 485 15.7 동시성의 향후 발전 방향............................................................................................ 488 15.8 마치며...................................................................................................................... 490
23
CHAPTER
1
성능과 최적화
자바 성능을 최적화하는 일(또는 그런 부류의 코드)은 마치 어둠의 마법처럼 느껴집니다. 흔 히들 성능 분석이라고 하면 ‘홀로 고뇌하며 깊은 생각에 빠져 살아가는 고독한 해커(할리우드 영화에서 컴퓨터를 다루는 사람들을 보통 이렇게 묘사하죠)’ 나 할 수 있는 고도의 숙련된 기술 처럼 바라봅니다. 시스템을 손금보듯 깊숙이 들여다보며 더 빨리 작동시킬 마법 같은 솔루션을 번뜩이며 찾아내는 과정처럼요. 안타깝게도 이런 이미지는 성능이 소프트웨어 팀의 부차적인 관심사인(그런 일이 너무 흔하 죠) 상황과 맞물려 있습니다. 그래서 시스템이 결딴나는 지경에 이르러서야 부랴부랴 분석 작 업을 해보고 성능 ‘해결사’에게 구원의 손길을 뻗는 시나리오를 당연하게 생각하는데요. 이는 현실과 조금 다릅니다. 실제로 성능 분석은 경험주의empiricism와 질퍽한 인간 심리학human psychology이 교묘히 어우러진 분 야입니다. 그리고 정작 중요한 건, 관측 지표observable metrics의 절대 수치, 그리고 엔드 유저(최종 사용자, 실제로 시스템을 사용하는 사람)와 기타 이해관계자들이 그 수치를 어떻게 받아들이 는가 하는 점입니다. 이 책의 주제는 이 뻔한 패러독스(역설)를 해결하는 것입니다.
1장 성능과 최적화
25
1.1 자바 성능: 잘못된 방법 한동안 구글에서 ‘Java Performance Tuning (자바 성능 튜닝)’이라고 검색하면 1997~1998 년에 작성된 글 3개가 상위권을 차지했습니다. 구글 서비스가 처음 시작된, 오래전에 인덱싱된 글들이죠. 초기 검색 랭킹(순위)별로 트래픽이 많이 유입됐고 그만큼 피드백도 활발했기 때문 에 계속 상위권을 지킬 수 있었을 겁니다. 그런데 이들 페이지는 지금은 더 이상 안 맞는, 완전 구닥다리 조언들과 심지어는 애플리케이 션에 악영향을 끼칠 만한 내용으로 가득 차 있었습니다. 하지만 검색 엔진 결과 상위권을 점유 한 탓에 많은 개발자가 끔찍한 조언에 고스란히 노출될 수밖에 없었죠. 예를 들면, 자바 초창기에 메서드 디스패치 성능은 정말 최악이었습니다. 그래서 메서드를 잘 게 나누지 말고 하나의 덩치 큰 메서드로 작성하는 게 좋다고 권고하는 개발자가 있었죠. 물론 시간이 지나면서 가상 디스패치 성능은 엄청나게 좋아졌고, 특히 최신 자바 가상 머신Java Virtual Machine
(JVM )에서는 자동 인라이닝automatic managed inlining 덕분에 가상 디스패치조차 대부분의 호
출부call site (콜 사이트)에서 사라지게 됐습니다. ‘모든 코드를 한 메서드에 욱여넣어라’는 말대로 짠 코드는 바야흐로 현대 JIT (적시) 컴파일러와는 어울리지 않는 퇴물이 됐습니다. 그릇된 조언이 애플리케이션 성능을 얼마나 나쁜 길로 빠져들게 했을지 가늠할 순 없지만, 정 량적, 검증 가능한 방식으로 성능을 다루지 않으면 얼마나 안 좋지 영향을 끼칠 수 있는지 사람 들이 깨달은 계기가 됐습니다. 또 인터넷에서 찾은 글을 무턱대고 믿어선 안 된다는 교훈을 주 었죠. NOTE_ 자바 코드가 실행되는 속도는 매우 변화무쌍하며 전적으로 코드를 실행하는 하부(겉으로 드러나지 않는 내부 구현에 관한) JVM에 따라 다릅니다. 따라서 오래전 작성한 자바 코드도 재컴파일 없이 최신 JVM 에서 실행하면 더 빨리 작동될 수 있습니다.
이런 이유로 필자는 코드에 바로 써먹을 수 있는 성능 팁을 나열할 목적으로 이 책을 쓰지 않았 습니다. 대신, 우수한 성능 목표를 달성하기 위해 필요한 여러 가지 단면을 종합적으로 집중 조 명하고자 합니다.
26
자바 최적화
• 전체 소프트웨어 수명주기의 성능 방법론 • 성능과 연관된 테스트 이론 • 측정, 통계, 툴링tooling1 (도구 선정) • (시스템 + 데이터) 분석 스킬 • 하부 기술과 메커니즘mechanism (장치, 수단)
최적화하는 휴리스틱heuristics2과 각종 코드 수준의 테크닉은 끝부분에서 소개합니다. 모든 최적 화 기법에는 개발자가 사용하기 전에 알아두어야 할 함정과 트레이드오프trade-off3 (상충 관계)가 도사리고 있으니 조심해야 합니다. TIP_ 어떤 맥락에서 씌여진 조언인지 제대로 알지 못한 채 섣불리 뒷장부터 펼쳐보며 세부 기법을 적용하 지 마세요. 적용 원리를 잘 모르고는 어떤 기법도 득보다는 실이 더 많을 겁니다.
일반적인 원칙은 이렇습니다. • JVM을 더 빨리 작동시키는 ‘마법의 스위치’ 같은 건 없습니다. • 자바를 더 빨리 실행하게 만드는 ‘팁, 트릭’은 없습니다. • 여러분이 못 보게 꼭꼭 숨겨둔 ‘비밀 알고리즘’ 같은 것도 없습니다.
앞으로 자바 성능 분석 및 그와 연관된 이슈를 다루면서 개발자들이 저지르기 쉬운 실수와 갖 가지 오해를 점점 구체적으로 살펴보겠습니다. 설마 벌써 책을 덮은 건 아니겠죠? 자, 성능 이 야기를 시작해봅시다.
1 역자주_ 사용 목적과 의도에 의도에 맞게 소프트웨어 소프트웨어 툴를 선정하고 조합하는 조합하는 등의 활동 2 역자주_ 불충분한 시간이나 정보로 인하여 합리적인 판단을 할 수 없거나, 체계적이면서 합리적인 판단이 굳이 필요하지 않은 상황에서 사람들이 빠르게 사용할 수 있는 어림짐작의 방법 (출처: 위키백과) 3 역자주_ 소프트웨어의 어느 한 부분의 품질을 높이거나 낮추면 다른 부분의 품질을 높이거나 낮추는 데 영향받는 것. 대개 어느 하나를 개선하면 다른 부분이 악화되는 식입니다.
1장 성능과 최적화
27
1.2 자바 성능 개요 자바 성능의 본질을 이해하려면 자바 창시자인 제임스 고슬링의 한마디를 거슬러 인용하지 않 을 수 없습니다. 자바는 블루 칼라(주로 생산직에 종사하는 육체 노동자) 언어입니다. 박사 학위 논문 주제가 아니라 일을 하려고 만든 언어죠.4
곧, 자바는 처음부터 지극히 실용적인 언어였습니다. 개발 환경이 ‘충분히 빠르다면’ 개발자 생 산성이 높아지는 대가로 어느 정도의 성능 희생은 감수할 만하다는 입장이었죠. 그러나 자바 환경이 고성능 컴퓨팅 애플리케이션에 적합한 수준에 이른 건 비교적 최근에 핫스팟 같은 정교 한 JVM이 성숙했기 때문입니다. 실용성을 추구하는 자바 플랫폼의 성격은 여러 방면에서 드러나는데요, 그중 관리되는 서브시 스템managed subsystem (하위계)이 가장 대표적입니다. 개발자가 일일이 용량을 세세하게 관리하는
부담을 덜어주고, 대신 저수준으로 제어 가능한 일부 기능을 포기하자는 발상이지요. 단적으로, 메모리 관리가 그렇습니다. JVM이 탈착형(떼었다 붙였다 할 수 있는) 가비지 수집 서브시스템 형태로 메모리를 자동 관리하는 덕분에 프로그래머는 수동으로 메모리를 의식하며 개발할 필요가 없습니다. NOTE_ JVM 전반에 걸쳐 등장하는 관리되는 서브시스템은 그 존재 자체로 JVM 애플리케이션의 런타임 동작에 복잡도complexity를 유발합니다.
다음 절에서 다루겠지만, 런타임 동작이 복잡한 JVM 애플리케이션은 실험 대상처럼 다룰 수밖 에 없고, 이런저런 측정을 통해 통계치를 내어 보면 불편한 진실을 마주하게 됩니다.
JVM 애플리케이션의 성능 측정값은 정규 분포를 따르지 않는 경우가 많아서 기초 통계 기법 (예: 표준편차, 분산 )만 갖고는 측정 결과를 제대로 처리하기에 역부족입니다. 기초 통계 기법 은 대부분 암묵적으로 정규 분포를 전제로 하니까요. 쉬운 예로, JVM 애플리케이션(예: 저지연 거래 애플리케이션low-latency trading application )에서 특이
4 역자주_ 전체 원문은 http://www.win.tue.nl/~evink/education/avp/pdf/feel-of-java.pdf 참고.
28
자바 최적화
점(아웃라이어)은 매우 중요한 의미를 내포할 수 있습니다. 즉, 측정값을 샘플링sampling (표본 추출)하면 특이점을 일으킨 가장 중요한 이벤트가 묻혀버릴 가능성이 큽니다. 끝으로, 자바 성능 측정값 때문에 판단이 흐려지기 쉬우므로 조심해야 합니다. 환경이 복잡해 질수록 시스템을 개별적으로 따로 떼어내 생각하기는 몹시 어렵습니다. 측정하는 행위 자체도 오버헤드(과부하)를 일으키며, 너무 자주 샘플링하거나 매번 결과를 기 록하는 것 역시 성능 결과 수치에 적잖은 영향을 끼칩니다. 자바 성능 수치는 일정 부분 세심한 손질이 필요합니다. 자바/JVM 애플리케이션을 우직한 기법으로 접근하면 부정확한 결과가 나 올 공산이 큽니다.
1.3 성능은 실험과학이다 대부분의 최신 소프트웨어 시스템이 그렇듯, 자바/JVM 소프트웨어 스택 역시 아주 복잡합니 다. 자신이 처한 환경에 적응하며 고도로 최적화하는 JVM을 기반으로 구축된 운영 시스템의 성능 양상은 상당히 미묘하고 복잡하게 나타날 수 있습니다. 이렇게 복잡한 지경까지 이른 건 무어의 법칙Moore’s Law과 그로 인한 하드웨어 용량의 전무후무한 발전 때문일 것입니다. 소프트웨어 산업의 가장 경이적인 성과는 하드웨어 산업에서 꾸준히 이루어낸 혁신을 끊임없이 무용 지물로 만들고 있는 것이다. – 헨리 페트로스키
오랜 시간에 걸쳐 이룩한 업계의 성과를 수포로 만든 소프트웨어 시스템도 있지만, JVM은 실 로 엔지니어링의 개가라고 하지 않을 수 없습니다. 1990년대 후반 이후로 JVM은 아주 다재다 능한 초고성능, 범용 실행 환경으로 거듭났지만, 원래 세상은 공평한 법! JVM도 다른 복잡한 고성능 시스템처럼 최상의 성능을 발휘하려면 어느 수준 이상의 스킬과 경험이 필요합니다. 명확하게 정의하지 않고 측정하는 건 백해무익하다. – 엘리 골드렛
1장 성능과 최적화
29