Object Count Impact on Garbage Collection Performance#

원문 : http://jroller.com/page/slobodan?entry=object_count_impact_on_garbage

개발자가 빈약한 자바 애플리케이션 성능에 대해 불평할때, 그들 대부분은 가비지 컬렉션이 너무 느리고 너무 많은 시간을 소요한다고 말한다. 게다가 좀더 긴 가비지컬렉션은 상호작용하는 애플리케이션에 다양한 문제점을 야기한다. 자바 옹호론자는 가비지컬렉션 알고리즘이 때때로 C/C++내 수동 메모리 관리보다 더 빨라서 매우 효율적이라고 언제다 대답한다. 불행하게도 이것은 반만 진실이다. 그 반은 우리, 즉 자바 프로그래머는 진실로 멍청하고(pigs) 실제 사용해야하는 방법을 고려하지 않고 가비지컬렉션 알고리즘을 넘어서는 초과된 수의 객체를 할당한다. 특정문제에서 나는 많은 수의 작은 객체가 오랜기간동안 사용될때 고려된다. (노트 : 많은 수의 작은 객체보다 적은 수의 큰 객체가 좀더 성능면에서 좋다. 가비지컬렉션 성능은 그것들의 크기가 아니라 객체수에 비례한다. ) 특히 가비지컬렉션 단계는 객체와 그것들의 참조값을 찾기위해 필요한 모든 쓰레드를 일시정지해야만 한다. 그래서 객체수를 줄이는 것이 이 일시정지현상을 죄소화하게 된다. 오랜시간동안 살아있는 객체의 수를 줄이는 것이 특히 중요하다.

나는 한번에 수초동안 매우 오래동안 가비지컬렉션으로 인한 일시정지를 경험한 서버 소프트웨어의 분석을 수행했다. 이 애플리케이션은 수백메가바이트의 힙영역(jvm이 객체와 배열등을 할당하는 메모리 영역)을 가진다. 그래서 많은 수의 객체를 할당했다. 이것은 원인을 파악하기 위한 노력을 하지 않는다.

http://localhost:7002/showInstanceCounts/includePlatform/
475988 instances of class java.util.HashMap$Entry
150358 instances of class java.lang.Integer
134060 instances of class java.lang.String
128203 instances of class java.util.HashMap$Entry[]
128173 instances of class java.util.HashMap
126484 instances of class char[]
51877 instances of class java.lang.Boolean
...

HashMap관련 클래스는 매우 크다(top). 많은 수의 integer래퍼객체가 있다. 더 나쁘게도 나는 51877개의 boolean인스턴스를 발견했다. 우리가 원시(primitive) 래퍼와 같은 작은 객체를 풀링하는것을 더이상 괴롭히지 않도록 말하는 동안, 우리가 new를 사용하여 힙영역에 언제나 그것들을 할당해야 한다는것을 의미하지는 않는다. 사실, 래퍼클래스는 할당된 인스턴스의 수를 명백하게 줄일수 있는 것이 적당할때 간단한 풀링기법을 구현한다. 내가 이전에 말했던것처럼, integer와 boolean객체조차 매우 작고 많은 메모리를 사용하지 않는다. 이것은 가비지컬렉션 성능을 떨어뜨리는 많은 객체 갯수이다. new Integer(.. 와 new Boolean 를 Integer.valueOf(.. 와 Boolean.valueOf(..로 교체한후에.. 나는..

...
50853 instances of class java.lang.Integer
...
24 instances of class java.lang.Boolean 
...

이것은 매우 간단한 기술이다. 하지만 쉽게 잋혀진다. new를 사용하여 짧은주기 객체를 할당하는것은 좋다. 그것들은 가비지컬렉션을 괴롭히기에 충분할만큼 오래 살지 않기 때문이다. 오래 살아있는 객체를 위해 valueOf factory메소드의 사용을 확실히 하자. 처음의 객체 갯수의 리스트로 돌아가서.

http://localhost:7002/showInstanceCounts/includePlatform/
476039 instances of class java.util.HashMap$Entry
138654 instances of class java.lang.String
132946 instances of class char[]
128197 instances of class java.util.HashMap$Entry[]
128175 instances of class java.util.HashMap
...

대부분의 서버 소프트웨어처럼 우리는 많은 수의 문자열(string)과 문자(character)들을 가진다. 또한 우리는 많은 수의 hash map객체를 가진다. 분석해보자. 약 128K의 hash map과 대략 같은 수의 hash map항목 배열. 각각의 map은 하나의 배열을 가진다. 그리고 우리는 476K 항목의 객체를 가진다. 그렇다면 map당 약 476/128 = 3.7의 항목이 된다. 이 시점에 경고가 나온다. "왜 그렇게나 많은 수의 작은 map이죠.?"

map은 가장 유용하고 가장 자주 사용되는 데이터구조중 하나이다. 이것은 java.util.Map인터페이스에 의해 정의된다. java.util.HashMap은 가장 자주 사용되는 구현물이다. map은 어떤것을 인덱스화할수 없을때마다 관련된것을 위해 사용된다. 게다가 우리는 종종 새로운 클래스를 정의하는데 매우 느리고 결국엔 map을 대신해서 사용한다. 예를 들면:

class Person
  String name =null;
  int age =null;
  int weight =0f;
  int height =0f;
  ...

몇개의 객체인가.? 하나의 person객체에 의해 사용되는것은 총 1 Person+1 string = 2 객체이다. 어쨌든, 나는 다른 클래스를 생성하는것을 좋아하지 않는다. 그렇다면 나는 작은 map을 사용할것이다.

Map<String,Object> person = new HashMap<String,Object>();
person.put("name", "Joe Doe");
person.put("age", Integer.valueOf(22));
person.put("weight", Integer.valueOf(80));
person.put("height", Integer.valueOf(170));

객체의 갯수는 다소 다루기 쉽지 않다. key들은 모든 map에 의해 공유될것이다. 그래서 그것들은 카운트 하지 않는것이 효과적이다. integer객체는 아마도 잘 공유된다. 그래서 우리는 2개의 새로운 인스턴스만을 할당하여 공유하도록 하기 위해 3개의 integer객체를 사용할것이다. 그러므로 우리는 하나의 person map에 의해 사용되는 총 1 Map + 1 entry array + 4 entries (1 entry/mapping) + 1 string (for name) + 2 integers = 9개의 객체를 가진다. 우리는 9개를 사용하여 끝났음에도 불구하고 person을 위해 오직 2개의 객체만을 사용해야만 한다. 이것을 수행하기 위해 이전보다 더 형편없는 대부분의 프로그래머는 map을 사용하는 좋지 않은 작은 영향를 고려하지 않는다. 대부분의 다른 map구현물은 많은 객체를 사용한다. 종종 추가적인 7개의 객체가 위치하는 map을 우리가 사용하면 추가적으로 서버 소프트웨어내 50만개의 객체에 도달할때 커다란 문제점에 접하게된다.

이 문제를 접근하기 위한 방법은 적당한 클래스를 선언하고 가능한 원시타입을 사용하도록 시도하는 것이다. map은 편리한 도구인것을 부정하지 않고 그것들을 사용하기 위해 프로그래머를 벌주길 원하지 않는다. 그러므로, 나는 내부적으로 최소한의 객체를 사용하는 다른 map구현물을 생성하는것을 결정한다. 그 방법은 많은 수의 객체 생성없이 map사용을 유지할수 있다. 특히, 항목 객체를 제거할수 있다면 위 person map은 4개의 적은 객체를 사용하고 차이점은 나쁘지 않을것이다.

나는 이후에 최소한의 객체갯수를 가지는 map인 MocMap에 대한 글을 시작할것이다. 나는 당신에게 그것들이 재미있지는 않을것이라고 경고해야만 한다. 사실 당신들중 몇몇은 존재하지 않는 문제점을 위한 노력을 비난할것이다. 이 클래스는 어떠한 상황에서만 관련된다는것을 명심하라. 다른 경우, java.util.* map은 괜찮고 나의 구현물은 적용가능하지 않을것이다.

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-8) was last changed on 20-Feb-2013 10:18 by DongGukLee