자바 성능 튜닝 이야기 4주차
자바 성능 튜닝 이야기 4주차
들어가며
이 포스트는 이상민의 「자바 성능 튜닝 이야기」 Chpater6 ~ 8을 읽고 개인적으로 학습한 내용을 정리한 글입니다.
- 책: 자바 성능 튜닝 이야기
- 저자: 이상민
- 출판사: 인사이트
- 챕터: Chapter9 ~ Chapter 11
핵심 정리 내용
9장 IO에서 발생하는 병목 현상
기본적인 IO는 이렇게 처리한다
- 자바의 입출력은 stream을 통해 이루어진다
- IO는 성능에 영향을 가장 많이 미친다
- IO에서 발생하는 시간은 CPU를 사용하는 시간과 대기 시간 중 대기 시간에 속한다
그럼 NIO의 원리는 어떻게 되는 거지?
- IO작업의 프로세스
- 파일 읽기 메서드를 자바에 전달
- 파일명을 전달받은 메서드가 OS의 커널에게 파일읅 읽어 달라고 요청
- 커널이 HDD에서 파일을 읽어 자신의 커널에 있는 버퍼에 복사하는 작업을 수행. DMA에서 이 작업을 수행
- 자바에서는 마음대로 커널의 버퍼를 사용하지 못하으모, JVM으로 그 데이터를 전달
- JVM에서 메서드에 있는 스트림 관리 클래스를 사용해 데이터 처리
- NIO에서 도입된 개념
- 버퍼의 도입
- 채널의 도입
- 문자열의 엔코더 및 디코더 제공
- Perl 스타일의 정규 표현ㅅ힉에 기초한 패턴 매칭 방법 제공
- 파일을 잠그거나 메모리 매핍이 가능한 파일 인터페이스 제공
- 서버를 위한 복합적인 Non-blocking IO 제공
lastModified() 메서드의 성능 저하
- lastModified() 메서드의 처리 절차
- System.getSecurityManager() 메서드를 호출해 SecurityManager 객체를 얻어옴
- 만약 null이 아니면 SecurityManager 객체의 checkRead() 메서드 수행
- File 클래스 내부의 FileSystem 클래스 객체에서 getLastModifiedTime() 메서드를 수행해 리턴
- lastModified() 메서드의 대안
- WatcherService
WatcherService(추가 내용)
- WatcherService란
- WatchService는 Java 7(NIO.2)에서 도입된 파일 시스템 모니터링 API
- 파일이나 디렉토리의 변경사항(생성, 수정, 삭제 등)을 실시간으로 감지
- 주요 특징
- 비동기적 파일 시스템 모니터링
- 이벤트 기반 처리
- 크로스 플랫폼 지원 (Windows, Linux, macOS)
- 효율적인 리소스 사용 (폴링 방식보다 성능 우수)
- 주요 컴포넌트
- WatchService: 파일 시스템 이벤트를 감지하는 서비스
- WatchKey: 등록된 디렉토리와 발생한 이벤트들을 관리
- WatchEvent: 실제 발생한 이벤트 정보
- StandardWatchEventKinds: 표준 이벤트 타입들
- 주요 메서드 상세 설명
- WatchService 생성 및 관리
1
2
3
4
5
// WatchService 생성
WatchService watchService = FileSystems.getDefault().newWatchService();
// 서비스 종료
watchService.close();
- 디렉토리 등록 메서드
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);
- 이벤트 감지 메서드
- take() - 블로킹 방식
1
WatchKey take() throws InterruptedException
- 이벤트가 발생할 때까지 무한 대기
이벤트 발생 시 WatchKey 반환
- poll() - 논블로킹 방식
1
2
3
WatchKey poll()
WatchKey poll(long timeout, TimeUnit unit)
- 즉시 반환 (이벤트 없으면 null)
- 타임아웃 설정 가능
- WatchKey 주요 메서드
1
2
3
4
5
6
7
8
9
10
11
// 발생한 이벤트 목록 조회
List<WatchEvent<?>> pollEvents()
// WatchKey 유효성 검사 및 재설정
boolean reset()
// 등록 취소
void cancel()
// 감시 대상 객체 반환
Watchable watchable()
- 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)
- 이전과 동일하면서 지역만 추가
- format(String format, Object… args)
- System.out.println() 보다 응답 시간이 느려짐
- 값을 항상 파싱하기 때문에 문자열을 그냥 더하는 것보다 성능이 좋을 수 없음
로그를 더 간결하게 처리하는 방법
- Logger를 사용하는 것이 가장 안정적
- Logger를 사용할 수 없다면?
- 자체 Logger 클래스를 만드는 방법
- 시스템 로그를 컴파일할 때 삭제하도록 하는 방법
로거 사용 시 문제점
- 로거를 사용하기 위해선 어차피 객체를 생성해야한다
- 그 객체 생성으로 인한 메모리와 시간 소비
11장 jsp와 서블릿, Spring에서 발생할 수 있는 여러 문제점
JSP와 Servlet의 기본적인 동작 원리는 꼭 알아야 한다
- JSP의 라이프 사이클
- JSP URL 호춣
- 페이지 번역
- JSP 페이지 컴파일
- 클래스 로드
- 인스턴스 생성
- jspInit 메서드 호출
- _jspService 메서드 호출
- 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.