본문 바로가기

프로그래밍(TA, AA)/JVM 언어

[자바성능] 프로그램 속도 측정

성능이 느리다고 할 때 가장 먼저 해야 하는 작업은 병목 지점을 파악하는 것입니다. 자바 기반의 시스템에 대하여 응답 속도나 각종 데이터를 측정하는 프로그램은 많이 있습니다. 애플리케이션의 속도에 문제가 있을 때 분석하기 위한 툴로는 프로파일링 툴이나 APM(Application Performance Monitoring 혹은 Management) 툴 등이 있습니다.


프로파일링 툴(프로파일러)이란?


프로파일링 툴

- 소스 레벨의 분석을 위한 툴입니다.

- 애플리케이션의 세부 응답 시간까지 분석할 수 있습니다.

- 메모리 사용량을 객체나 클래스, 소스의 라인 단위까지 분석할 수 있습니다.

- 가격이 APM 툴에 비해서 저렴합니다.

- 보통 사용자수 기반으로 가격이 정해집니다.

- 자바 기반의 클라이언트 프로그램 분석을 할 수 있습니다.


APM 툴

- 애플리케이션의 장애 상황에 대한 모니터링 및 문제점 진단이 주 목적입니다.

- 서버의 사용자 수나 리소스에 대한 모니터링을 할 수 있습니다.

- 실시간 모니터링을 위한 툴입니다.

- 가격이 프로파일링 툴에 비하여 비쌉니다.

- 보통 CPU 수를 기반으로 가격이 정해집니다.

- 자바 기반의 클라이언트 프로그램 분석이 불가능합니다.


프로파일링 툴은 느린 메소드, 느린 클래스를 찾는 것이 목접입니다. 하지만 APM 툴은 목적에 따라서 다르게 보아야 합니다. 어떤 APM 툴은 문제점 진단에 강한 한 편, 다른 APM 툴은 시스템 모니터링 및 운영에 강합니다.


프로파일링 툴은 기본적으로 응답 시간 프로파일링과 메모리 프로파일링 기능을 제공합니다.


- 응답 시간 프로파일링 기능: 응답 시간 프로파일링을 하는 주된 이유는 응답 시간을 측정하기 위함입니다. 하나의 클래스 내에서 사용되는 메소드 단위의 응답 시간을 측정합니다. 툴에 따라서 소스 라인 단위로 응답 속도를 측정할 수도 있습니다. 응답 시간 프로파일링을 할 때에는 보통 CPU 시간과 대기 시간, 이렇게 두가지 시간이 제공됩니다.

- 메모리 프로파일링 기능: 메모리 프로파일링을 하는 주된 이유는 잠시 사용하고 GC의 대상이 되는 부분을 찾거나, 메모리 부족 현상(Memory Leak)이 발생하는 부분을 찾기 위함입니다. 클래스 및 메소드 단위의 메모리 사용량이 분석됩니다. 마찬가지로 툴에 따라서는 소스 라인 단위의 메모리 사용량도 측정할 수 있습니다.


CPU 시간과 대기 시간이란?

하나의 메소드, 한 라인을 수행하는데 소요되는 시간은 무조건 CPU 시간과 대기시간으로 나뉩니다. CPU 시간은 CPU를 점유하는 시간을 의미하고, 대기 시간은 CPU를 점유하지 않고 대기하는 시간을 의미합니다. 그래서 CPU 시간과 대기 시간을 더하면 실제 소요 시간(Clock time)이 됩니다. CPU 시간은 툴에 따라서 스레드(Thread) 시간으로 표시되기도 합니다. 해당 스레드에서 CPU를 점유한 시간이기때문에 표현만 다르지 사실은 같은 시간입니다.


APM 툴이건 프로파일링 툴이건 자동으로 되는 툴은 없습니다. 일단 툴에서 분석을 하려면 해당 메소드가 수행 되어야 합니다. 수행되지 않은 메소드는 분석자체가 되지 않습니다. 수행이 되어야 하므로, 메모리 부족 현상이 가장 분석하고 찾아내기가 어렵습니다.



System 클래스


System 클래스의 메소드는 static으로 되어 있고 생성자(Constructor)도 없습니다. 다시 말하면, System 객체는 우리가 생성을 할 수 없으며, System.XXX와 같은 방식으로 써야 합니다.


- static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 특정 배열을 복사할 때 사용.


- static Properties getProperties(): 현재 자바 프로퍼티 값들을 받아옴.

- static String getProperty(String key): key에 지정된 자바 프로퍼티 값을 받아옴.

- static String getProperty(String key, String def): key에 지정된 자바 프로퍼티 값을 받아옴. def는 해당 key 존재하지 않을 경우 지정할 기본값.

- static void setProperties(Properties props): props 객체에 담겨있는 내용을 자바 프로퍼티에 지정

- static String setProperty(String key, String value): 자바 프로퍼티에 있는 지정된 key의 값을 value값으로 변환


- static Map<String, String> getenv(): 현재 시스템 환경을 스트링 형태의 맵으로 리턴

- static String getenv(String name): name에 지정된 환경 변수의 값을 얻음.


- static void exit(int status): 현재 수행중인 자바 VM을 멈춘다. 이 메소드는 절대로 수행하면 안된다.

- static void load(String filename): 파일명을 지정하여 네이티브 라이브러리를 로딩.

- static void loadLibrary(String libname): 라이브러리의 이름을 지정하여 네이티브 라이브러리를 로딩.


- static void gc(): GC를 수행하도록 하는 메소드로, 일반 웹 애플리케이션에 사용하면 안된다.

- static void runFinalization(): Object 객체에 있는 finalize()라는 메소드는 자동으로 호출되는데, 가비지 콜렉터가 알아서 해당 객체를 더이상 참조할 필요가 없을때 호출한다. 하지만 이 메소드를 호출하면 참조 해제 작업을 기다리는 모든 객체의 finalize() 메소드를 수동으로 수행한다. 메소드도 gc() 메소드와 마찬가지로 일반 웹 애플리케이션에서 사용하면 안된다.


- static long currentTimeMillis(): 현재의 시간을 ms로 리턴(1/1,000초)


UTC(Coordinated Universal Time)라는 시간 표준 체계를 따르는데, 1970년 1월 1일부터의 시간을 long 타입을 리턴해 줍니다. 다라서 호출할 때마다 다릅니다. 이 시간 값을 변환하면 현재 날짜를 구할 수도 있습니다. 


ms는 1/1000 초를 의미합니다. 자바에서 성능을 이야기할때는 ms로 이야기 하는 것이 가장 편하고, 확실합니다.



- static long nanoTime(): 현재의 시간을 ns로 리턴(1/1,000,000,000 초)


1ms 이하의 시간을 측정할때 사용합니다. currentTimeMillis 메소드와 차이가 나는데, 어떤 때에는 nanoTime()이 오래걸리는 것으로 나타나고, 그 반대의 경우도 있습니다. 자바성능 필자분은 되도록이면 nanoTime() 메소드의 결과로 판단하는 것을 권장하고 있습니다.



프로파일링 툴이나 APM 툴은 프로젝트에서 적어도 하나 정도는 사용하는 것이 좋습니다. 성능이 이슈가 되는 사이트의 경우 반드시 필요합니다. 프로젝트의 상황에 맞는 APM, 프로파일링 툴을 잘 선택해야 합니다.


java 프로파일링 툴 소개 ( http://egloos.zum.com/zeous/v/2068863 )



본 포스팅은 자바 성능을 결정짓는 코딩 습관과 튜닝 이야기 3장을 참고하였습니다.