Post

자바 성능 튜닝 이야기 9주차

자바 성능 튜닝 이야기 9주차

들어가며

이 포스트는 이상민의 「자바 성능 튜닝 이야기」 Chpater21 ~ 24을 읽고 개인적으로 학습한 내용을 정리한 글입니다.

  • 책: 자바 성능 튜닝 이야기
  • 저자: 이상민
  • 출판사: 인사이트
  • 챕터: Chapter21 ~ Chapter 24

핵심 정리 내용

21장 반드시 튜닝해야 하는 대상은?

반드시 튜닝해야 하는 대상 선정

  • APM 툴이 있다면 이를 이용
  • 없다면 상위 20% 화면을 분식 및 튜닝 대상으로 선정

왜 로그인 화면을 튜닝(분석)해야 하는가?

  • 로그인이 안되면 다른 기능을 사용 못함
  • 대부분의 업무 시스템에서 로그인 후 화면은 여러 컴포넌트로 구성

22장 어떤 화면이 많이 쓰이는지 알고 싶다

웹 로그란?

  • apache, nginx, iPlanet과 같은 모든 웹 서버에서 공통적으로 제공되는 기능
  • 서버에 어떤 사용자의 요청, 결과를 파일에 한 줄씩 쌓아줌

웹 로그를 통해서 접근 통계를 분석하기 싫다면

  • 구글 애널리틱스도 적절한 방법

23장 튜닝 절차는 그때그때 달라요

성능 튜닝을 위한 아주 기초 법칙

  • ‘암달의 법칙’
    • 1 Core에서 20시간 소요되는 작업 중 1시간은 절대 개선할 수 없다면, 20배 이상의 성능 향상은 불가능하다
    • 어떤 프로그램이라도 이 패턴을 보일 수 밖에 없음 > 성능 개선에는 한계가 있음

성능 튜닝 step by step

  • 성능 튜닝 절차
    1. 원인 파악
    2. 목표 설정
    3. 튜닝 실시
    4. 개선율 확인
    5. 결과 정리 및 반영

원인 파악

  • 성능 저하가 발생하는 원인 파악 단계
    • 병목 위치를 정확하게 찾아 원인 파악해야 한다

목표 설정

  • 성능 튜닝의 목표를 설정하는 단계

튜닝 실시

  • 코드 최적화하며 튜닝하는 단계
  • 튜닝을 실시하는 가장 좋은 방법은 프로파일링 툴이나 APM과 같은 툴을 사용
  • 개선 정도는 JMH나 캘리퍼와 같은 성능 비교 도구를 사용하는 것이 도움이 됨

개선율 확인

  • 튜닝 실시 후 얼마나 개선되었는지 확인하는 단계

결과 정리 및 반영

  • 튜닝 결과를 정리하고, 실제 운영되는 시스템에 반영하는 단계

성능 튜닝의 비법

하나만 보지 말아라

  • 병목 지점은 이 세상에 있는 병목 지점의 일부분일 뿐이다
  • 병목의 대상들
대상세부 대상
서버 장비CPU, Network, Disk, Memory 등
서버 OSOS 커널, 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.