Post

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

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

들어가며

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

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

핵심 정리 내용

9장 IO에서 발생하는 병목 현상

기본적인 IO는 이렇게 처리한다

  • 자바의 입출력은 stream을 통해 이루어진다
  • IO는 성능에 영향을 가장 많이 미친다
    • IO에서 발생하는 시간은 CPU를 사용하는 시간과 대기 시간 중 대기 시간에 속한다

그럼 NIO의 원리는 어떻게 되는 거지?

  • IO작업의 프로세스
    1. 파일 읽기 메서드를 자바에 전달
    2. 파일명을 전달받은 메서드가 OS의 커널에게 파일읅 읽어 달라고 요청
    3. 커널이 HDD에서 파일을 읽어 자신의 커널에 있는 버퍼에 복사하는 작업을 수행. DMA에서 이 작업을 수행
    4. 자바에서는 마음대로 커널의 버퍼를 사용하지 못하으모, JVM으로 그 데이터를 전달
    5. JVM에서 메서드에 있는 스트림 관리 클래스를 사용해 데이터 처리
  • NIO에서 도입된 개념
    • 버퍼의 도입
    • 채널의 도입
    • 문자열의 엔코더 및 디코더 제공
    • Perl 스타일의 정규 표현ㅅ힉에 기초한 패턴 매칭 방법 제공
    • 파일을 잠그거나 메모리 매핍이 가능한 파일 인터페이스 제공
    • 서버를 위한 복합적인 Non-blocking IO 제공

lastModified() 메서드의 성능 저하

  • lastModified() 메서드의 처리 절차
    1. System.getSecurityManager() 메서드를 호출해 SecurityManager 객체를 얻어옴
    2. 만약 null이 아니면 SecurityManager 객체의 checkRead() 메서드 수행
    3. File 클래스 내부의 FileSystem 클래스 객체에서 getLastModifiedTime() 메서드를 수행해 리턴
  • lastModified() 메서드의 대안
    • WatcherService

WatcherService(추가 내용)

  • WatcherService란
    • WatchService는 Java 7(NIO.2)에서 도입된 파일 시스템 모니터링 API
    • 파일이나 디렉토리의 변경사항(생성, 수정, 삭제 등)을 실시간으로 감지
  • 주요 특징
    • 비동기적 파일 시스템 모니터링
    • 이벤트 기반 처리
    • 크로스 플랫폼 지원 (Windows, Linux, macOS)
    • 효율적인 리소스 사용 (폴링 방식보다 성능 우수)
  • 주요 컴포넌트
    • WatchService: 파일 시스템 이벤트를 감지하는 서비스
    • WatchKey: 등록된 디렉토리와 발생한 이벤트들을 관리
    • WatchEvent: 실제 발생한 이벤트 정보
    • StandardWatchEventKinds: 표준 이벤트 타입들
  • 주요 메서드 상세 설명
    1. WatchService 생성 및 관리
1
2
3
4
5
// WatchService 생성
WatchService watchService = FileSystems.getDefault().newWatchService();
// 서비스 종료
watchService.close();

  1. 디렉토리 등록 메서드
1
2
3
4
5
6
// 기본 등록
WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events)

// 수정자와 함께 등록  
WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers)

  • 사용 예시
1
2
3
4
5
Path directory = Paths.get("/path/to/watch");
WatchKey key = directory.register(watchService,
    StandardWatchEventKinds.ENTRY_CREATE,
    StandardWatchEventKinds.ENTRY_DELETE,
    StandardWatchEventKinds.ENTRY_MODIFY);
  1. 이벤트 감지 메서드
    • take() - 블로킹 방식
1
WatchKey take() throws InterruptedException
  • 이벤트가 발생할 때까지 무한 대기
  • 이벤트 발생 시 WatchKey 반환

  • poll() - 논블로킹 방식
1
2
3
WatchKey poll()
WatchKey poll(long timeout, TimeUnit unit)

  • 즉시 반환 (이벤트 없으면 null)
  • 타임아웃 설정 가능
  1. WatchKey 주요 메서드
1
2
3
4
5
6
7
8
9
10
11
// 발생한 이벤트 목록 조회
List<WatchEvent<?>> pollEvents()

// WatchKey 유효성 검사 및 재설정
boolean reset()

// 등록 취소
void cancel()

// 감시 대상 객체 반환
Watchable watchable()
  1. WatchEvent 주요 메서드
1
2
3
4
5
6
7
8
// 이벤트 종류 반환
WatchEvent.Kind<?> kind()

// 이벤트 발생 횟수
int count()

// 이벤트와 관련된 객체 (파일명 등)
T context()
  • 표준 이벤트 타입
1
2
3
4
5
6
7
8
9
10
11
// 파일/디렉토리 생성
StandardWatchEventKinds.ENTRY_CREATE

// 파일/디렉토리 수정
StandardWatchEventKinds.ENTRY_MODIFY

// 파일/디렉토리 삭제
StandardWatchEventKinds.ENTRY_DELETE

// 이벤트 유실 시 발생
StandardWatchEventKinds.OVERFLOW

10장 로그는 반드시 필요한 내용만 찍자

System.out.println()의 문제점

  • System.out.println() 사용 시 내용이 완전히 프린트되거나 저장될 때까지 애플리케이션도 대기하므로 느려짐

System.out.format() 메서드

  • System.out.format()은 C에서 프린트하던 방식으로 소스가 더 간결해짐
    • format(String format, Object… args)
      • 지정된 포맷으로 프린트, 뒤에 있는 매개변수를 쉼표로 나열
    • format(Locale l, String format, Object… agrs)
      • 이전과 동일하면서 지역만 추가
  • System.out.println() 보다 응답 시간이 느려짐
    • 값을 항상 파싱하기 때문에 문자열을 그냥 더하는 것보다 성능이 좋을 수 없음

로그를 더 간결하게 처리하는 방법

  • Logger를 사용하는 것이 가장 안정적
  • Logger를 사용할 수 없다면?
    • 자체 Logger 클래스를 만드는 방법
    • 시스템 로그를 컴파일할 때 삭제하도록 하는 방법

로거 사용 시 문제점

  • 로거를 사용하기 위해선 어차피 객체를 생성해야한다
    • 그 객체 생성으로 인한 메모리와 시간 소비

11장 jsp와 서블릿, Spring에서 발생할 수 있는 여러 문제점

JSP와 Servlet의 기본적인 동작 원리는 꼭 알아야 한다

  • JSP의 라이프 사이클
    1. JSP URL 호춣
    2. 페이지 번역
    3. JSP 페이지 컴파일
    4. 클래스 로드
    5. 인스턴스 생성
    6. jspInit 메서드 호출
    7. _jspService 메서드 호출
    8. jspDestory 메서드 호출
  • 서블릿의 라이프 사이클
    • Servlet 객체가 자동으로 생성되고 초기화되거나
    • 사용자가 해당 Servlet을 처음으로 호출했을 때 생성되고 초기화 된다
    • 그 다음에는 계속 ‘사용 가능’ 상태로 대기
    • 해당 서블릿이 더 필요없을 때는 ‘파기’ 상태로 넘어간 후 JVM에서 ‘제거’
  • 특정 값이 여러 스레드(서블릿)에서 접근하면 데이터가 꼬여 원하지 않는 값이 출력될 수 있다
    • 서블릿의 service 메서드 구현 시 메멉 변수나 static한 클래스 변수를 선언해 지속적으로 변경하는 작업은 피해야 한다

적절한 include 사용하기

  • JSP의 include 방식
    • 정적 방식 : <%@ include file=”관련 URL” %>
    • 동적 방식 :
    • 동적이 정적보다 30배 느림
    • 정적 방식만 쓰면 메인 jsp와 정적 jsp 사이의 동일한 변수에서 오류 발생함
    • 적절하게 사용하는 것이 중요

스프링 프레임워크 간단 정리

  • Spring의 가장 큰 특징
    • 복잡한 애플리케이션도 POJO(Plain old Java Object)로 개발가능

스프링의 핵심 기술

  • DI(Dependency Injection)
    • 객체 간의 관계를 관리하는 기술
    • 의존성을 주입해주는 기술
This post is licensed under CC BY 4.0 by the author.