자바 성능 튜닝 이야기 9주차
자바 성능 튜닝 이야기 9주차
들어가며
이 포스트는 이상민의 「자바 성능 튜닝 이야기」 Chpater21 ~ 24을 읽고 개인적으로 학습한 내용을 정리한 글입니다.
- 책: 자바 성능 튜닝 이야기
- 저자: 이상민
- 출판사: 인사이트
- 챕터: Chapter21 ~ Chapter 24
핵심 정리 내용
21장 반드시 튜닝해야 하는 대상은?
반드시 튜닝해야 하는 대상 선정
- APM 툴이 있다면 이를 이용
- 없다면 상위 20% 화면을 분식 및 튜닝 대상으로 선정
왜 로그인 화면을 튜닝(분석)해야 하는가?
- 로그인이 안되면 다른 기능을 사용 못함
- 대부분의 업무 시스템에서 로그인 후 화면은 여러 컴포넌트로 구성
22장 어떤 화면이 많이 쓰이는지 알고 싶다
웹 로그란?
- apache, nginx, iPlanet과 같은 모든 웹 서버에서 공통적으로 제공되는 기능
- 서버에 어떤 사용자의 요청, 결과를 파일에 한 줄씩 쌓아줌
웹 로그를 통해서 접근 통계를 분석하기 싫다면
- 구글 애널리틱스도 적절한 방법
23장 튜닝 절차는 그때그때 달라요
성능 튜닝을 위한 아주 기초 법칙
- ‘암달의 법칙’
- 1 Core에서 20시간 소요되는 작업 중 1시간은 절대 개선할 수 없다면, 20배 이상의 성능 향상은 불가능하다
- 어떤 프로그램이라도 이 패턴을 보일 수 밖에 없음 > 성능 개선에는 한계가 있음
성능 튜닝 step by step
- 성능 튜닝 절차
- 원인 파악
- 목표 설정
- 튜닝 실시
- 개선율 확인
- 결과 정리 및 반영
원인 파악
- 성능 저하가 발생하는 원인 파악 단계
- 병목 위치를 정확하게 찾아 원인 파악해야 한다
목표 설정
- 성능 튜닝의 목표를 설정하는 단계
튜닝 실시
- 코드 최적화하며 튜닝하는 단계
- 튜닝을 실시하는 가장 좋은 방법은 프로파일링 툴이나 APM과 같은 툴을 사용
- 개선 정도는 JMH나 캘리퍼와 같은 성능 비교 도구를 사용하는 것이 도움이 됨
개선율 확인
- 튜닝 실시 후 얼마나 개선되었는지 확인하는 단계
결과 정리 및 반영
- 튜닝 결과를 정리하고, 실제 운영되는 시스템에 반영하는 단계
성능 튜닝의 비법
하나만 보지 말아라
- 병목 지점은 이 세상에 있는 병목 지점의 일부분일 뿐이다
- 병목의 대상들
| 대상 | 세부 대상 |
|---|---|
| 서버 장비 | CPU, Network, Disk, Memory 등 |
| 서버 OS | OS 커널, OS 설정, 수행중인 프로세스 등 |
| 자바 애플리케이션 | 스레드 풀 설정, DB Connection Pool 설정, Cache 설정, GC 설정, Heap 크기 설정, 검증되지 않은 프레임워크의 버그, 개발된 애플리케이션 등 |
| 웹 서버 | 프로세스 개수 설정, Connector 설정, 개발된 모듈의 버그 등 |
| 네트워크 | 사용자의 네트워크의 종류, 사용자의 위치, L4 및 Switch 등 네트워크 장비, 방화벽 등 |
| 클라이언트 | 클라이언트 장비의 CPU, Network, Disk, Memory, OS 등의 성능, 클라이언트 애플리케이션, 클라이언트 장비에서 수행 중인 프로세스 등 |
큰 놈을 없애라
- 가장 큰 성능 저하가 발생하는 부분을 찾아서 튜닝해야한다
- 라이브러리가 문제가 되는 경우
- 해당 라이브러리를 튜닝
- 비용이 많이 절감
- 다른 것으로 교체
- 어쩔 수 없는 경우
- 해당 라이브러리를 튜닝
깊게 알아야 한다
- 개발 언어, OS, DB, N.W, 서버 중 하나라도 전문가가 되어야한다
결과 공유는 선택이 아닌 필수
- 결과 정리 시 꼭 포함되어야 하는 내용
- 개요 : 튜닝을 실시한 배경
- 튜닝 환경 : 튜닝을 실시하고 성능을 측정한 서버 및 툴에 대한 상세한 내용
- 튜닝 결과 : 튜닝 전과 후의 결과를 비교
- 결론 : 어느 부분을 어떻게 변경하는 것이 가장 큰 효과를 줄 지, 튜닝 작업을 진행한 담당자의 의견을 포함
- 튜닝 결과 정리 시 유의사항
- 확실한 결과 위주로 포함
- 기존 대비 얼마나 성능 개선이 이루어졌는지 수치로 보여주기
- 개선 효과가 가장 큰 것부터 나열하자
- 개선 효과가 가장 큰 부분부터 정리
- 개발한 사람의 심기를 나쁘게 하지 말자
- 최대한 존중을 하면서 결과를 정리해야 한다
- 확실한 결과 위주로 포함
그래프를 그릴 때 유의 사항
- 그래프의 타이틀, 라벨 추가
- 산포도를 그릴 때 데이터를 나타내는 각 점은 되도록 작게
- Y축을 그릴 때
- 정수 값일 경우 1000단위에 콤마 추가
- 소수까지 내려가는 값일 경우 적어도 3자리를 보여주자
- 주 단위를 표시하는 경우에는 그래프 내 주 단위가 4개 이상 표시되지 않는 것이 좋음
- X축을 그릴 때
- X축의 주 단위는 10개 내외로
- 주 단위 선으로 보여줄 지, 눈금으로만 보여 줄지 상황에 맞게 결정
24장 애플리케이션에서 점검해야 할 대상들
패턴과 아키텍처는 잘 구성되어 있는가?
- 너무 많은 패턴을 사용하지 않았는가?
- 너무 많은 패턴을 적용하면 유지보수성이 떨어지고, 문제 발생 시 추적이 어려워짐
- 꼭 필요한 패턴만 사용해야 한다
- 데이터를 리턴할 때 VO 패턴을 사용하였는가? 아니면 Collection 관련 클래스를 사용하였는가?
- VO 패턴 혹은 Collection을 이용한 개발 표준이 없는 경우 유지보수성이 떨어짐
- service locator 패턴은 적용이 되어 있는가?
- 서비스 로케이터 패턴을 사용하면 애플리케이션에서 필요한 대상을 찾는 lookup 작업을 할 때 소요되는 대기 시간을 줄일 수 있다
- 만약 서버의 CPU 사용량이 높지 않을 때 응답 속도가 느리다면, 서비스 로케이터를 적용해야 하는 부분이 있지 않은 지 확인 필요
기본적인 애플리케이션 코딩은 잘 되어 있는가?
- 명명 규칙은 잘 지켰는가?
- 그 클래스 이름을 보고 어떤 일을 하는 클래스인지 바로 인식이 가능한지 확인해야 한다
- 자바의 기본 명명 규칙을 따라야한다
- 필요한 부분에 예외 처리는 되어 있는가?
- 문제 발생 시 원인 규명을 위해 예외 처리는 필수
- 예외 화면은 지정되어 있는가?
- 예외 화면에 대한 표준이 있는지 확인 필요
- 예외 정보를 혹시 e.printStackTrace()로만 처리하고 있지 않은가?
- e.printStackTrace() 메서드를 호출하면 서버에서 스택 정보를 취합해야하므로 서버에 많은 부하가 발생
- System.gc() 메서드가 포함되어 있지 않은가?
- 개발자가 GC의 타이밍을 신경써서는 ‘안된다’
- System.exit() 메서드가 소스에 포함되어 있지 않은가?
- 이 메서드가 수행되면 WAS의 프로세스가 죽는다
- 반드시 제거
- 문자열을 계속 더하도록 코딩하지는 않았는가?
- “String +=” 형태가 아닌 StringBuilder나 StringBuffer를 사용
- StringBuilder나 StringBuffer 클래스도 제대로 사용했는가?
- StringBuilder나 StringBuffer 클래스 안에서 문자열을 더하면, 두 클래스를 사용할 필요가 없다
- 무한 루프가 작동할 만한 코드는 없는가?
- static을 남발하지 않았는가?
- 메모리를 아낀다고 static을 남발하다가 시스템이 심각한 오류를 발생시킬 수 있다
- 필요한 부분에 synchronized 블록을 사용하였는가?
- 필요 없는 부분에 synchronized 블록을 사용하면 성능 저하가 발생
- IO가 계속 발생하도록 개발되어 있지 않은가?
- 설정 파일을 매번 파일에서 읽도록 개발하는 것은 문제이다
- 필요 없는 로그는 다 제거했는가?
- 개발에 필요한 print하라
- 디버그용 System.out.println은 다 제거했는가?
웹 관련 코딩은 잘 되어 있는가?
- jsp의 include는 동적으로 했는가? 아니면 정적으로 했는가?
- jsp를 동적으로 include하면 서버에도 부하가 발생하며, 응답 시간에도 영향을 준다
- 꼭 필요한 부분에만 동적 include를 사용, 그렇지 않으면 정적 include로 해야한다
- 자바 빈즈는 너무 많이 사용하지 않았나?
- 하나의 VO를 사용해 처리할 수 있다면, 여러 개ㅑ의 자바 빈즈를 사용해 응답 시간에 영향을 주는 일이 없도록 하자
- 태그 라이브러리는 적절하게 사용했나?
- 적절하게 태그 라이브러리를 사용하라
- EJB는 적절하게 사용하였나?
- EJB 하나하나는 일반 클래스보다 많은 메모리를 점유하며, 서버 기동 시 많은 시간을 소요하므로, 반드시 필요한 경우에만 EJB를 사용
- 이미지 서버를 사용할 수 있는 환경인가?
- 정적 컨텐츠가 많고 사용자의 요청이 많은 경우 웹 서버 외에 이미지 서버를 사용할 수 있다
- 사용 중인 프레임워크는 검증되었는가?
DB 관련 코딩은 잘 되어 있는가?
- 적절한 JDBC 드라이버를 사용하는가?
- 되도록이면 가장 최신의 WAS 및 DB 벤더에서 추천하는 문제 없는 JDBC를 사용할 것
- DB Conncection, Statement, ResultSet은 잘 닫았는가?
- 반드시 finally 구문을 사용해 Conncection, Statement, ResultSet를 명시적으로 닫을 것
- DB Connection Pool은 잘 사용하고 있는가?
- DB Connection Pool을 반드시 사용해 DB 리소스를 보다 효율적으로 사용해야한다
- 자동 커밋 모드에 대한 고려는 하였는가?
- 기본 커밋 모드는 자동 커밋
- 조회성 프로그램도 자동 커밋 여부를 지정하면, 약간의 응답 시간 저하 발생
- ResultSet.last() 메서드를 사용하였는가?
- 전체 건수 처리를 위해 last() 메서드를 사용했는지 확인해야 한다
- 전체 건수를 가져오기 위해 last() 메서드를 사용하는 것은 자제
- PreparedStatements를 사용하였는가?
- Statement를 사용하면 매번 쿼리를 수행할 때마다 SQL 쿼리를 컴파일하게 되므로 DB에 부하가 발생
- 쿼리 문장이 계속 동적으로 변경되어야 하는 경우를 제외하곤 PreparedStatements를 사용하는 것을 권장
서버의 설정은 잘 되어 있는가?
- 자바 VM 관련 옵션들은 제대로 설정되어 있는가?
- 64비트 기반의 시스템을 사용하면서 -d64 옵션을 사용하지 않으면 32비트로 사용됨
- 클래스 패스는 순차적으로 인식
- 같은 패키지명에 같은 클래스가 있는 경우 앞에 명시한 클래스패스에 우선권이 있음
- 메모리는 몇 MB로 설정해 놓았는가?
- GC 설정은 어떻게 되어 있는가?
- -client로 설정되어 있는지 확인
- GC 방식에 따라 서버 성능에 차이가 있으므로, 서버와 시스템에 맞는 GC 옵션 설정 필요
- 서버가 운영 모드인지 개발 모드인지 확인하였는가?
- WAS의 인스턴스가 몇 개 기동되고 있는가?
- CPU가 4개 인데, 인스턴스가 30개 정도 있는 것은 아닌지 확인 필요
- WAS의 CPU 개수가 적을 경우, 때에 따라 인스턴스 개수를 증가시키면 서버의 처리량이 증가될 수 있음
- 서버 및 애플리케이션의 상황에 맞게 성능 테스트를 통해서 시스템의 적절한 인스턴스 개수를 도출해야 한다
- JSP Precompile 옵션은 지정해 놓았는가?
- 서버 기동 시 jsp를 미리 컴파일하도록 해 놓으면 사용자는 jsp가 수정 되었는지 여부와 상관없이 일정한 응답 속도를 느낄 수 있다
- DB Connection Pool 개수와 스레드 개수는 적절한가?
- 스레드 개수가 DB Connection pool의 수보다 절대로 적어서는 안된다
- 스레드의 개수는 DB Connection pool의 개수보다 보통 10개 정도 더 많이 설정
- 세션 타임아웃 시간은 적절한가?
- 세션을 더 이상 사용하지 않을 때 세션 정보는 삭제되어야 한다
- 검색 서버가 있다면 ,검색 서버에 대한 설정 및 성능 테스트를 하였는가?
- 검색 서버에서 주기적으로 데이터를 모으기 위해 서버의 리소스를 많이 사용하므로, 검색 서버의 세팅을 점검해야한다
모니터링은 어떻게 하고 있는가?
- 웹 로그(Access log)는 남기고 있는가?
- 웹 로그는 애플리케이션의 사용 흔적을 남기는 가장 간단하고도 많은 자료
- 애플리케이션의 사용량과 자주 사용하는 애플리케이션을 분석하기 위해, 추후 용량 산정의 기초 자료가 되는 웹 로그는 반드시 남겨서 관리하자
- verbosegc 옵션은 남기고 있는가?
- GC가 어떤 형태로 발생하는지를 확인하고자 한다면, 반드시 verbosegc 옵션을 사용해 로그를 남기자
- GC 튜닝을 하지 않을 시스템에 verbosegc 옵션을 남기는 것은 리소스 낭비
- 각종 로그 파일에 대한 규칙은 있는가?
- 일별로 로그를 쌓도록 설정
- 서버의 시스템 사용률은 로그로 남기고 있는가?
- WAS나 DB가 얼마나 사용을 하고 있는지 로그를 남겨야 한다
- 모니터링 툴은 사용 중인가?
- WAS를 모니터링 하기 위한 툴을 사용하자
- 모니터링 툴에 대한 설정은 적절하게 되어 있는가?
- 꼭 필요한 내용만 모니터링이 되도록 설정를 잘 맞추어야 한다
- 서버가 갑자기 코어 덤프를 발생시키지 않는가?
- 10000건 이상 조회하는 것이 있는지 확인이 필요 > 대량 데이터가 발생하면 많은 메모리가 필요한데, 이 때 코어덤프가 발생할 수 있다
- 메모리 릭이 있는지 확인해야 한다 > 메모리를 점유하고 해제하지 않는 로직이 있으면 서버를 매일 재기동해도 메모리를 점차적으로 부족해진다. 서버 기동 후 힙 덤프를 받아 놓은 뒤, 운영 중-후에 각각 덤프를 받아 메모리 사용량의 추이를 확인해야 한다
- 응답 시간이 너무 느리지 않은가?
This post is licensed under CC BY 4.0 by the author.