![](http://kr.sun.com/developers/tech_docs/java_web03/images/tit.gif) | |
Ubiquity의 SIP 애플리케이션 서버인 Application Services Broker(ASB)는 100% 순수 Java 기술이며, JVM과 가비지 컬렉션에 대한 완벽한 테스트 환경을 제공한다. SIP 애플리케이션 서버로서, ASB는 신호가 오는 네트웍으로부터 서비스 요청을 받은 다음 수정하고, 최종적으로 답변해주는 책임이 있다. SIP 트래픽을 신호가 오는 네트웍으로부터 서비스 요소(SIP Servlets)로 연결해 책임을 이행한다. 이 서비스 요소는 특정 신호 메시지에 관심이 있다고 ASB에 등록한다. ASB는 대규모 호출을 다양한 로드 분산으로 생성한다. 이는 클러스터 기반으로 구현되어 한 대나 여러 대에서나, 여러 프로세서에서 잘 확장된다. 이런 때 JVM 디자인이 한계점까지 압력을 받으며, 이런 상태를 관찰하면서 다중 쓰레드의 JVM을 개선시키는 데 많은 통찰력을 얻게 된다.
![](http://kr.sun.com/developers/tech_docs/java_web03/images/pyo02.gif) | 예를 들어 Ubiquity ASB는 호출되는 하나의 프로세스당(일반적으로 한 호출은 하나의 세션이다) 약 220KB의 가비지를 생성한다. 10%의 데이터는 40초 가까이 생존하고, 나머지 90%는 곧바로 죽어버린다. 이 10%의 데이터는 단시간이지만 평균 초당 100번을 호출한다고 하면 대단히 많은 메모리를 사용하게 된다. 40초 안에 최소한 88MB의 활성 데이터를 갖게 된다. 만약 가비지 컬렉션이 5분에 한번씩 ‘구세대’에서 일어난다면 heap의 크기는 최소한 660MB가 돼야 한다. 이전의 가비지 컬렉션 엔진이 스캔하기에 매우 커 컬렉션하는 데 100~150ms 정도 걸린다.
통신 애플리케이션 서버는 애플리케이션을 멈추는 시간을 엄격히 제한해줄 수 있는 결정적인 GC 모델을 요구하고 여러 프로세스에서도 잘 확장돼야 한다. |
J2SE 1.2와 1.3에서 GC는 단일 쓰레드이며, stop-the-world 형식이었다. 이 JVM의 가비지 컬렉션으로 인해 생기는 멈춤은 애플리케이션에 지연을 더해 처리량과 확장성으로 본 성능이 떨어지게 된다. 이런 아키텍처는 한대의 컴퓨터의 여러 CPU에서 확장하기 어럽게 만든다. 가비지 컬렉션이 여러 프로세서로 분산되지 않기 때문에, 매우 다중 쓰레드인 애플리케이션이 JVM에서 실행될 때, 애플리케이션 레벨의 작업을 이행하기에 충분한 프로세서를 갖고 있음에도 불구하고 JVM으로부터 컨트롤을 얻기 위해 기다리며, JVM은 다중 CPU 환경에서 많은 압력을 받는다. 다중 프로세서 시스템에서 단일 쓰레드 GC의 영향은 병렬 애플리케이션일수록 크게 나타난다. 만약 GC를 제외하고 애플리케이션이 완벽하게 확장한다고 가정하면, GC가 일어나는 동안 작업을 수행할 수 있는 다른 프로세서가 유휴 상태에 있게 됨으로써, GC가 확장성을 저해하는 원인(Bottleneck)이 되는 것이다.
이런 내용에서 Java를 Turbo-charge한다는 것은 많은 CPU 사용과 많은 메모리에 접근, 많은 동시 발생 소켓 연결의 처리를 의미한다.
J2SE 1.4는 새로운 기능과 버퍼 관리, 네트웍 확장성, 파일 I/O의 성능을 개선한 논블록킹 new I/O API를 구현했다. - 새로운 네트웍 I/O 패키지는 접속할 때마다 쓰레드를 배정하는 방식을 제거함으로써 서버에 동시 접속할 수 있는 수를 극적으로 증가시켰다. - 새로운 파일 I/O는 읽기와 쓰기, 복사, 이동 작업에서 현재의 파일 I/O보다 2배 가까운 속도를 낸다. 새 것은 file locking과 memory-mapped files, 동시 여러 읽기/쓰기 작업을 지원한다.
J2SE 1.4의 64비트의 JVM은 4G 이상 큰 heap을 가질 수 있을 뿐더러 300G 이상 가질 수도 있다. 만약 가비지의 생성과 배당하는 비율이 일정하다면 heap이 클수록 GC로 인한 멈춤은 더욱 빈도수가 낮아지지만 그 시간은 길어질 것이다.
애플리케이션의 효율성과 확장성을 정하는 중요한 요소는 ‘GC 순차 비용(GC sequential overhead)’이다. 이는 애플리케이션의 실행 시간 중에 애플리케이션이 멈춘 상태에서 JVM에서 GC가 실행되는 시간의 비율을 뜻한다. 다음과 같이 계산할 수 있다.
Avg. GC pause * Avg. GC frequency * 100 %. ‘GC 빈도수’는 주기적인 GC나 한 단위의 시간에 일어나는 GC수이다. ‘신세대’와 ‘구세대’의 평균 GC 멈춤과 빈도수가 매우 다르기 때문에 GC 순차 비용을 구하는 계산이 다른데, 즉 둘을 합해서 애플리케이션의 총 GC 순차 비용을 구할 수 있다. GC 순차 비용은 다음과 같이 계산될 수 있다.
Total GC time/Total wall clock run time.
총 GC 시간은 다음과 같이 계산할 수 있다.
Avg. GC pause * total no. of GCs
분명 적은 GC 순차 비용은 애플리케이션의 높은 처리량과 확장성을 의미한다. | ![](http://kr.sun.com/developers/tech_docs/images/bt_top.gif) | ![](http://kr.sun.com/developers/tech_docs/java_web03/images/txt.gif) | J2SE 1.4.1은 JVM이 더 많은 CPU와 메모리를 사용할 수 있게 해, 애플리케이션의 성능과 확장성을 높일 수 있게 디자인한 두 개의 새 가비지 컬렉터를 소개했다. 이 컬렉터는 통신 업체의 도전과제를 충족할 수 있게 해준다.
- 최대의 처리량을 위해 시스템의 자원을 확장성과 최적화로 사용하기 위해, 시스템의 GC 순차 비용은 10% 이상 될 수 없다. - 클라이언트와 서버 간에 정해진 프로토콜에 정의된 지연에 부합되고 서버의 양호한 답변 시간을 보장하기 위해서, 애플리케이션에서 발생되는 모든 GC 멈춤은 200ms 이상이 되면 안된다.
J2SE 1.4.1에서 소개한 두 개의 새로운 컬렉터는 Parallel Collector와 Concurrent mark-sweep(CMS) Collector이다.
-Parallel collector: Parallel collector는 신세대를 대상으로 구현되었다. 이는 다중 쓰레드이며, stop-the-world이다. 이 컬렉터는 다중 프로세서 컴퓨터에서 더 좋은 성능을 내도록 다중 쓰레드에서 GC를 할 수 있게 한다. 비록 모든 애플리케이션 쓰레드를 중지시키지만 시스템의 모든 CPU를 사용해 주어진 양의 GC를 더욱 빠르게 처리할 수 있다. 신세대 부분에서의 GC 멈춤을 많이 감소시킨다. 따라서 Parallel collector는 여러 CPU뿐만 아니라 더 많은 메모리에 애플리케이션이 확장할 수 있게 해준다.
-Concurrent mark-sweep(CMS) collector: CMS collector는 구세대를 대상으로 구현되었다. CMS collector는 애플리케이션과 함께 ‘mostly concurrently’하게 실행되어, 때로는 ‘mostly-concurrent garbage collector’로 불린다. GC 멈춤 시간을 짧게 하기 위해서 애플리케이션을 위해 사용할 처리 능력을 이용한다. CMS collection은 Initial mark와 Concurrent marking, Remark, Concurrent sweeping의 4단계로 나뉜다.
‘initial mark’와 ‘remark’ 단계는 CMS collector가 모든 애플리케이션 쓰레드를 일시적으로 중지시키는 stop-the-world 단계이다. initial mark 단계는 시스템의 ‘roots’에서 곧바로 접근가능하게 모든 객체를 기록한다. ‘concurrent marking’ 단계에서 모든 애플리케이션 쓰레드는 재시작되고 concurrent marking 단계가 초기화된다. ‘remark’ 단계에서 애플리케이션 쓰레드는 다시 중지되고 마지막 마킹을 끝낸다. ‘concurrent sweeping’ 단계에서 애플리케이션 쓰레드는 다시 시작되며 heap을 동시 스위핑하며 표기되지 않은 모든 객체는 회수된다. initial mark와 remark 단계는 상당히 짧다. 구세대의 크기가 1G라고 해도 200ms 이하의 시간이 걸린다. concurrent sweeping 단계는 mark-compact collector 만큼의 시간이 걸릴 것이지만 애플리케이션 쓰레드가 중지되지 않기 때문에, 멈춤이 숨겨져 있다. | ![](http://kr.sun.com/developers/tech_docs/java_web03/images/pyo03.gif) | | ‘mostly concurrent’인 CMS collector는 JVM이 큰 heap과 여러 CPU에 확장할 수 있게 해, 지연과 mark-compact stop-the-world collector로 발생한 처리량 문제를 해결한다.
표 1은 J2SE 1.4.1에 있는 여러 컬렉터의 기능을 비교해본다. 그림 1과 2, 3은 다른 여러 가비지 컬렉터를 그림으로 나타낸 것이다. 초록 화살표는 다중 CPU에서 실행되는 다중 쓰레드 애플리케이션을 뜻한다. 빨간 화살표는 GC 쓰레드를 뜻한다. GC 쓰레드의 길이는 GC 멈춤 시간을 대략적으로 나타낸다.
표 1.다른 여러 가비지 컬렉터의 기능 요약 신세대 컬렉터 | 구세대 컬렉터 | Copying collector collector Default Stop-the- world Single threaded All J2SEs | Mark-compact collector Default Stop-the-world Single threaded All J2SEs | | Parallel collector | Concurrent mark-sweep collector | Stop-the- world Multi- threaded J2SE 1.4.1+ | Mostly-concurrent Single threaded J2SE 1.4.1+ |
|
그림 1과 2, 3이 보여주듯, Parallel collector를 신세대에서 concurrent mark-sweep collector를 구세대에서 같이 사용하면 중지 시간과 GC 순차 비용을 줄일 수 있다. 이 두 컬렉터는 애플리케이션이 더 많은 프로세서와 메모리에 확장할 수 있도록 도와준다. |
|