메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

WebSphere Application Server V8의 가비지 콜렉션, Part 1: 새로운 기본 정책인 세대 콜렉션 전략

Chris Bailey, 소프트웨어 자문 엔지니어, IBM
Chris Bailey는 2000년 Southampton University의 대학원생 시절에 IBM Java Technology Centre에 입사했다. 자바 기술과 자바 플랫폼 기반 제품의 IBM 포트와 관련된 문제를 해결하는 일을 했다. 그는 "IBM Java Runtimes and SDKs" 이라는 developerWorks 포럼을 운영하고 있고 현재에는 자바 플랫폼의 IBM 포트의 사용자들이 사용할 수 있는 정보 및 툴링을 향상시키는데 주력하고 있다.
Charlie Gracie, 가비지 콜렉션 기술팀 리더, IBM
Charlie Gracie는 캐나다에 있는 Ottawa Lab, IBM Java Technology Center 팀의 구성원이다. 그는 university of New Brunswick에서 BCS 학위를 받았으며 2004년 이후로는 J9 Virtual Machine 팀에서 근무했다. 현재는 J9 Garbage Collection 팀의 리더로, IBM JVM의 모든 가비지 콜렉션 기술을 제공하는 업무를 담당하고 있다. 여가 시간에는 실내나 해변에서 배구를 하거나 다양한 실외 활동을 즐긴다.
Karl Taylor , 가비지 콜렉션 기술개발자, IBM
Karl Taylor는 캐나다에 있는 Ottawa Lab, IBM Java Technology Center 팀의 구성원이다. 그는 Carleton University에서 BCS 학위를 받았으며 프로젝트가 시작된 후로는 J9 Virtual Machine 팀에서 다양한 역할을 수행했다. 현재는 J9 Garbage Collection 팀의 수석 개발자이며, IBM의 JSR 292 및 335 활동에도 참여하고 있다. Karl은 와인 애호가로 여가 시간에는 소믈리에 자격증을 취득하기 위해 노력하고 있다.

요약:  작성된 워크로드가 모두 동일한 것은 아닙니다. 애플리케이션마다 메모리를 사용하는 방식이 다르며 따라서 애플리케이션은 다양한 가비지 콜렉션 전략으로부터 이점을 얻을 수 있습니다. IBM® JVM(Java™ Virtual Machine)은 언제나 여러 가지 다양한 GC 정책을 지원하여 다양한 유형의 애플리케이션을 지원했습니다. 그렇지만, 하드웨어는 발전하고 있으므로 소프트웨어는 하드웨어를 더 잘 사용하도록 개선되어야 합니다. IBM® WebSphere Application Server V8의 기본 가비지 콜렉션 정책에서는 세대(Generational) 및 병렬(Concurrent) 콜렉션 전략을 사용합니다. 이 기사에서는 기본 정책을 새로 구성하는 데 필요한 안내서와 더불어 IBM JVM에서 사용 가능한 가비지 콜렉션 정책을 간단하게 설명합니다. 이 연재 자세히 보기

기사 게재일:  2011 년 6 월 22 일
난이도: 초급 원문:  보기 PDF:  A4 and Letter (118KB | 15 pages)Get Adobe® Reader®
페이지뷰:  427 회
의견:  


소개

GC(Garbage Collection)는 애플리케이션이 계속해서 새 오브젝트에 메모리를 할당할 수 있게 사용되지 않는 Java 힙 메모리를 수집한다는 점에서 JVM의 핵심 부분이라고 할 수 있다. GC의 효율성과 성능은 애플리케이션의 성능과 결정론에 중요한 역할을 한다. IBM WebSphere Application Server V8과 함께 제공되는 IBM JVM은 다음과 같이 다양한 GC 정책 알고리즘을 제공한다.

  • -Xgcpolicy:optthruput
  • -Xgcpolicy:optavgpause
  • -Xgcpolicy:gencon
  • -Xgcpolicy:balanced

이러한 각 알고리즘은 다양한 성능과 결정론적 특성을 제공한다. 이외에도 WebSphere Application Server V8의 기본 정책이 -Xgcpolicy:optthruput에서 -Xgcpolicy:gencon 정책으로 변경되었다. 이러한 정책을 각각 살펴보고 기본 정책의 변경이 의미하는 바를 알아 보도록 하자.


가비지 콜렉터

서로 다른 애플리케이션은 본질적으로 메모리 사용 패턴이 다르다. 방대한 수를 계산하는 계산 집약적인 워크로드에서는 고객과 인접해 있고, 트랜잭션이 빈번한 인터페이스와 동일한 방식으로 Java 힙을 사용하지는 않는다. 이와 같은 다양한 유형의 워크로드를 적절하게 처리하려면 다양한 가비지 콜렉션 전략이 필요하다. IBM JVM은 해당 애플리케이션에 가장 적합한 전략을 선택할 수 있도록 여러 가지 가비지 콜렉션 정책을 지원한다.

병렬 MSC(Mark-Sweep-Compact) 콜렉터: optthruput

가장 단순한 가비지 콜렉션 기술은 사용 가능한 메모리가 고갈되어 애플리케이션이 중지되고 전체 힙이 처리될 때까지 계속해서 메모리를 할당하는 것이다. 이 기술이 매우 효과적인 가비지 콜렉터 역할을 하지만, 이 기술을 사용하는 경우에는 콜렉터로 인해 야기되는 일시정지 현상이 사용자 프로그램에서 허용되어야 한다. 전체 처리량만 중요한 워크로드는 이러한 전략이 도움이 될 수 있다.

optthruput 정책(-Xgcpolicy:optthruput)이 이러한 전략을 구현한다(그림 1). 이 콜렉터는 PMS(Parallel Mark-Sweep) 알고리즘을 사용한다. 간단히 말해서 이는 콜렉터가 도달 가능한 오브젝트 세트를 먼저 조사하여 이러한 오브젝트를 활성 데이터로 표시한다는 것을 의미한다. 그 다음에는 표시되지 않은 오브젝트를 완전히 없애서, 새로 할당할 때 사용될 수 있도록 사용 가능한 메모리로 남겨둔다. 이 작업은 대부분 동시에 수행되므로 콜렉터는 추가적인 스레드(기본적으로 최대 CPU 수까지)를 사용하여 이 작업을 더 신속하게 수행함으로써 애플리케이션이 일시정지되는 시간을 줄인다.


그림 1 애플리케이션과 콜렉터 CPU 사용량: optthruput
애플리케이션과 콜렉터 CPU 사용량: optthruput

MS(Mark-Sweep) 알고리즘은 단편화가 발생한다는 문제점이 있다(그림 2). 사용 가능한 메모리가 많이 있을 수 있지만, 메모리가 작은 조각으로 활성 오브젝트에 흩어져 있는 경우에는 특정 할당을 만족시킬 수 있을 정도로 크기가 충분한 개별 조각이 존재하지 않을 수도 있다.

이러한 문제점을 해결하려면 압축을 해야 한다. 이론상, 압축기는 활성 오브젝트를 모두 힙의 한쪽 끝으로 몰아서 하나의 연속된 사용 가능한 메모리 블록으로 남겨 놓는다. 이러한 조작을 수행하면 모든 활성 오브젝트가 이동되고 이동되는 오브젝트를 가리키는 모든 포인터가 새로운 위치에 맞게 업데이트되어야 하기 때문에 이러한 조작에는 값비싼 대가가 따른다. 결국 압축은 필요하다고 판단되는 경우에만 일반적으로 수행된다. 압축은 동시에 수행될 수도 있지만, 이렇게 하면 하나의 사용 가능한 블록 대신 작은 블록이 여러 개 작성될 수 있기 때문에 이렇게 활성 오브젝트를 압축하는 것은 그다지 효과적이지 못하다.


그림 2. 힙 단편화
힙 단편화

동시 콜렉터: optavgpause

일시정지 시간을 단축하기 위해 전체 처리량 중 일부를 희생할 수 있는 애플리케이션에서는 다양한 정책이 사용 가능하다. optavgpause 정책(-Xgcpolicy:optavgpause)은 애플리케이션이 정지하기 전에 가능한 많이 GC 작업을 수행하려고 시도하며 그 결과로 일시정지 시간이 단축된다(그림 3). 동일한 MSC 콜렉터가 사용되지만, 표시 및 스윕 단계 대부분이 애플리케이션이 실행될 때 수행된다. 시스템은 프로그램의 할당 비율을 기반으로 다음 가비지 콜렉션이 필요하게 될 시점을 예측한다. 이 임계값에 도달하면 동시 GC가 시작된다. 애플리케이션 스레드가 오브젝트를 할당함에 따라, 이 스레드는 할당이 이행되기 전에 소규모의 GC 작업을 수행하도록 때때로 요청을 받게 된다. 스레드가 수행하는 할당이 많아질수록 스레드는 요청을 더 많이 받게 된다. 한편으로는 하나 이상의 백그라운드 GC 스레드가 유휴 주기를 사용하여 추가적인 작업을 수행한다. 동시 작업이 모두 수행되거나 사용 가능한 메모리가 예정보다 일찍 고갈되는 경우에는 애플리케이션이 정지되고 콜렉션이 완료된다. 압축이 필요하지 않는 한, 일반적으로 이러한 일시정지 시간은 짧다. 압축을 수행하면 활성 오브젝트가 이동되고 업데이트되기 때문에 압축은 동시에 수행될 수 없다.


그림 3. 애플리케이션과 콜렉터 CPU 사용량: optavgpause
애플리케이션과 콜렉터 CPU 사용량: optavgpause

세대(Generational) 콜렉션: gencon

작성된 대다수의 오브젝트는 짧은 기간 동안에만 사용된다는 사실이 오랫동안 관찰되었다. 이러한 사실은 프로그래밍 기술과 애플리케이션 유형의 결과이다. 많은 공통 Java 이디엄에서는 신속하게 버려지는 헬퍼 오브젝트(예: StringBuffer/StringBuilder 오브젝트나 Iterator 오브젝트)를 작성한다. 이러한 오브젝트는 특정 태스크를 완료하기 위해 할당되며 그 후에는 거의 필요하지 않다. 본래 트랜잭션이 많이 수행되는 대규모 애플리케이션은 사용되는 오브젝트의 그룹을 작성했다가 사용한 후에는 이 오브젝트를 모두 버리는 경향이 있다. 데이터베이스 쿼리에 대한 응답이 리턴되면, 응답, 중간 상태 및 쿼리 자체는 더 이상 필요가 없다.

이러한 사실이 관찰되면서 세대 가비지 콜렉터가 개발되게 되었다. 개념은 힙을 다양한 영역으로 나누고 이러한 영역을 다양한 비율로 수집하는 것이다. 새 오브젝트는 nursery 또는 newspace라고 하는 하나의 영역으로부터 할당된다. 이 영역에 있는 오브젝트는 대부분 신속하게 가비지되며 이러한 가비지를 수집하면 메모리를 복구할 수 있는 최상의 기회가 확보된다. 오브젝트가 한동안 활성화된 상태로 존재하면 이 오브젝트는 tenure 또는 oldspace리고 하는 다른 영역으로 이동된다. 이러한 오브젝트는 가비지될 가능성이 적으므로 콜렉터는 이러한 오브젝트를 자주 조사하지 않게 된다. 메모리가 조사되는 양이 적을 수록 조사되는 오브젝트가 재사용되는 비율이 높아지므로 워크로드를 제대로 정렬하면 콜렉션이 더 신속하고 효과적으로 수행된다. 콜렉션이 더 신속해지면 일시정지 시간이 단축되고 따라서 애플리케이션의 응답성이 개선된다.

IBM의 gencon 정책(-Xgcpolicy:gencon)은 앞에서 언급한 동시 콜렉터("-con")를 기반으로 세대 GC("gen-")를 제공한다. tenure 공간은 위에 기술된 대로 수집되지만, nursery 공간은 copying 콜렉터를 사용한다. 이 알고리즘은 nursery 영역을 allocatesurvivor 공간으로 더 세분화함으로써 작동한다(그림 4). 여유 공간이 고갈될 때까지는 새 오브젝트가 allocate 공간에 배치된다. 애플리케이션이 정지되면 allocate 공간에 있는 모든 활성 오브젝트는 survivor 공간으로 복사된다. 이 두 개의 공간은 역할을 스왑한다. 다시 말해서 survivor가 allocate가 되면 애플리케이션이 재개된다. 오브젝트 하나가 이러한 사본 다수를 위해 살아남은 경우, 이 오브젝트는 survivor 공간 대신 tenure 영역으로 이동된다.


그림 4. 작동 중인 Gencon
작동 중인 Gencon

이론상, 이는 nursery 영역의 반(즉, survivor 공간)이 어떤 시점에서는 사용되지 않는다는 것을 의미한다. 실질적으로 survivor 공간으로 할당되는 메모리의 양은 각 콜렉션에서 살아남은 오브젝트의 비율에 따라 신속하게 조정된다. 예를 들어, 새 오브젝트가 다수 수집되고 있는 경우에는 allocate와 survivor 공간 사이에 있는 분리 선이 기울어져서 수집이 필요하기 전에 할당될 수 있는 데이터의 양이 증가한다.

이러한 콜렉터 스타일에는 각 콜렉션에서 활성 오브젝트가 이동하고 nursery 영역이 각 콜렉션에서 묵시적으로 압축된다는 중요한 이점이 있다. 그 결과 가능한 많은 여유 공간을 확보할 수 있지만, 인접 메모리의 위치와 밀접하게 관련된 오브젝트(예: Stringchar[] 데이터)도 이동되는 결과를 낳게 된다. 이는 시스템 메모리 캐시의 성능 특성을 개선하여 결과적으로 애플리케이션 자체의 성능이 개선되는 바탕이 된다.

nursery 가비지 콜렉션의 대가는 살아남은 데이터의 양과 관련이 있다(그림 5). 오브젝트는 대부분 가비지될 것이라고 예상되므로 일반적으로 nursery 콜렉션으로 인해 발생하는 일시정지 시간은 매우 짧다. 오브젝트는 대부분 신속하게 수집되지만, 그렇지 않은 오브젝트도 있다. 이는 시간이 경과하면 tenure 영역이 수명이 긴 오브젝트로 채워지며 따라서 전체 힙의 가비지 콜렉션이 필요하게 된다는 점을 의미한다. 앞에서 언급한 동시 콜렉터 기술의 대부분은 여기에서도 적용된다. tenure 영역의 표시는 필요에 따라 동시에 실행되지만 할당과 콜렉션은 nursery 영역에서 발생한다. gencon 하에서는 tenure 영역의 스윕이 동시에 수행되지 않고 기본 tenure 콜렉션의 일부로 수행된다.


그림 5. 애플리케이션과 콜렉션 CPU 사용량: gencon
애플리케이션과 콜렉션 CPU 사용량: gencon

영역 기반 콜렉터: balanced

WebSphere Application Server V8에는 새로운 가비지 콜렉션 정책이 추가되었다. 이 정책은 balanced(-Xgcpolicy:balanced)라고 하며, 힙에 다양한 영역이 존재한다는 개념에서 확장되었다. 이 정책은 힙을 개별적으로 처리할 수 있는 다수의 영역으로 분리한다. 일반적인 영역 기반 가비지 콜렉션의 세부사항과 특히 balanced 정책은 Part 2에서 논의하게 된다.


비세대(Non-generational) 콜렉터에 맞게 힙 설정 튜닝

가비지 콜렉터를 모니터하고 분석하는 방법

다음과 같은 두 가지 메커니즘 중 하나를 사용하여 가비지 콜렉터와 Java 힙 사용량을 모니터할 수 있다.

  • Health Center용 실시간 모니터링 도구는 메소드 실행과 잠금 경합을 포함하여 가비지 콜렉션과 기타 데이터를 모니터하고 분석할 때의 성능 오버헤드가 매우 낮다.
  • -verbose:gc 명령행 옵션은 Garbage Collection과 Memory Visualizer 도구로 로드할 수 있는 native_stderr.log 파일을 출력한다. (-Xverbosegclog 옵션을 사용하여 -verbose:gc 출력을 자체 파일에 저장할 수도 있다.)

세부사항은 참고자료를 참조한다.

애플리케이션의 힙 크기를 튜닝하는 첫 번째 단계에서는 기본 힙 설정을 사용하여 애플리케이션을 실행하며 이렇게 하면 특별한 성능을 평가할 수 있다. 이 시점에서 힙의 여유 공간이 지속적으로 40% 미만이거나 GC로 인한 일시정지 시간이 총 실행 시간의 10%를 초과하는 경우에는 힙 크기를 늘리는 것을 고려해야 한다. 최소 및 최대 힙 크기는 각각 -Xms<value>-Xmx<value>을 지정하여 수정할 수 있다.

가비지 콜렉션의 표시 및 스윕 단계에서 GC로 인한 일시정지에 소요되는 시간은 힙에 있는 활성 오브젝트의 수에 따라 다르다. 일관된 워크로드에서는 힙 크기를 증가하더라도 표시 및 스윕 단계에 걸리는 시간은 거의 동일하게 유지된다. 따라서 힙 크기를 증가하면 GC로 인한 일시정지 시간 간의 간격이 증가하게 되어 애플리케이션의 실행 시간이 더 늘어나게 된다.

단편화 문제로 인해 GC에서 압축 단계가 수행 중인 경우에는 압축으로 인해 일시정지 시간이 늘어나는 현상을 힙 크기를 조정하여 완화할 수 있다. 압축 단계는 GC 일시정지 시간을 매우 늘어나게 하는 경향이 있으므로 일반적으로 발생하는 압축 단계인 경우에는 힙 설정을 튜닝하여 애플리케이션의 성능을 개선할 수 있다.

고정 vs. 가변 크기 힙

가변 크기 힙을 사용하면 애플리케이션에서 필요한 힙용 OS 자원만을 GC에서 사용할 수 있다. 애플리케이션 힙 요구사항이 변경되면, 힙을 확장하거나 축소하는 방식으로 GC가 대응할 수 있다. GC는 힙의 끝에 있는 연속된 메모리 블록만을 축소할 수 있으므로 힙을 축소하려면 압축을 해야 한다. 실제 축소와 확장 단계는 매우 신속하게 진행되기 때문에 이로 인해 GC 일시정지 시간이 뚜렷하게 증가되지는 않는다. 최대 힙 크기를 정상 조작에 필요한 것보다 더 크게 설정하면 애플리케이션이 힙을 확장하여 추가 워크로드를 처리하게 된다.

힙 요구사항이 일관된 애플리케이션은 고정 힙 크기를 사용하여 GC 일시정지 시간을 개선할 수 있다.


세대 GC 튜닝

admin 콘솔에서 명령행 옵션을 설정하는 방법

프로세스 정의의 Java Virtual Machine 패널에서 제네릭 JVM 인수 옵션을 사용하여 WebSphere Application Server 관리 콘솔에서 Java 명령행 옵션을 설정할 수 있다. Java Virtual Machine 패널을 찾으려면 다음과 같이 한다.

  1. admin 콘솔로 이동하여 왼쪽 패널에서 Servers > Server Types > WebSphere application servers를 선택한다.
  2. 기본 패널에서 해당 애플리케이션 서버를 선택한다.
  3. 기본 패널 오른쪽에서 Java and Process Management 옵션을 펼치고 Process definition을 선택한다.
  4. 오른쪽에서 Java Virtual Machine 옵션을 선택한다.
  5. Generic JVM 인수 텍스트 상자가 기본 패널 아래에 표시된다.

옵션이 추가되면 애플리케이션 서버를 다시 시작하여 변경사항을 적용하기 전에 변경사항을 저장하고 동기화해야 한다.

세대 가비지 콜렉션에 적합하도록 튜닝할 때, 가장 단순한 접근방식은 비세대 케이스에서 사용되는 Java 힙 영역 이외의 nursery 공간을 새로운 Java 힙 영역으로 처리하는 것이다. 따라서 비세대 가비지 콜렉션에 맞는 Java 힙은 tenured 힙이 된다.

이러한 접근방식은 보수적이다. nursery 영역이 도입되면 결과적으로 tenured 힙의 점유율이 떨어지게 되지만, tenured 힙은 안전한 시작점을 제공하며, 특히 비세대 정책에서 마이그레이션하는 경우에는 더욱 그러하다. 글로벌(전체) 콜렉션 이후의 tenured 힙의 점유율을 모니터할 수 있으면 앞에서 기술한 바와 같이 tenured 힙의 크기를 조정할 수 있다.

  • -Xmn<size>는 nursery 영역의 초기 및 최대 크기를 설정하며 -Xmns-Xmnx를 모두 효과적으로 설정한다.
  • -Xmns<size>는 nursery 영역의 초기 크기를 지정된 값으로 설정한다.
  • -Xmnx<size>는 nursery 영역의 최대 크기를 지정된 값으로 설정한다.

nursery 힙의 크기는 고정되어야 하므로 이러한 옵션 중 하나인 -Xmn만 필요하다. 그러므로 nursery 힙의 크기를 올바르게 지정하는 방법을 이해하기만 하면 된다.

nursery 힙의 크기 지정

nursery 힙의 크기를 올바르게 지정하려면, 먼저 nursery 콜렉션에서 사용되는 메커니즘과 그 결과로 발생하는 부차적 특성을 고려해야 한다.

  • Nursery 콜렉션은 데이터를 allocate 공간에서 survivor 공간으로 복사함으로써 작동한다. 데이터를 복사하는 작업은 비교적 많은 대가를 치러야 하고 시간도 많이 소비되는 태스크이다. 결과적으로 nursery 수집 기간은 복사되는 테이터 양에 의해 좌우된다. 복사되는 오브젝트의 수와 nursery 힙 자체의 크기에도 영향을 받지만, 실제 데이터를 복사하는 데 따르는 대가와 비교할 때 이러한 영향은 비교적 작다. 결과적으로 nursery 수집 기간은 복사되는 데이터 양에 비례한다.
  • 주어진 콜렉션에서는 한정된 고정 데이터 양만 "활성" 상태로 존재한다. 애플리케이션이 시작을 완료하여 해당 캐시가 완전히 채워지면 nursery 힙에 복사되어야 하는 "활성" 데이터의 양은 그 시점에서 수행 중인 작업 양에 의해 고정된다. 트랜잭션을 처리하는 시스템에서는 복사되어야 하는 활성 데이터의 양이 활성 트랜잭션 세트 하나에 상당한다. 예를 들어, WebContainer 스레드 50개가 트랜잭션 50개를 동시에 처리하도록 애플리케이션 서버를 구성한 경우에는 활성 데이터의 양이 이러한 트랜잭션 50개와 연관된 양이 된다.

이는 nursery 수집 기간이 nursery 힙의 크기가 아니라 수집 시점에서 발생하는 동시 트랜잭션 수와 연관된 데이터의 크기에 의해 설정된다는 것을 의미한다. 또한, nursery 힙의 크기가 더 커지더라도 nursery 수집 기간은 증가하지 않고 nursery 수집 시간 간의 시간 간격이 증가한다. 실제로는 nursery 힙의 크기가 커지면, 가비지 콜렉션에 소요되는 전체 시간이 줄어든다.

그림 6에는 nursery 힙의 크기가 트랜잭션 세트 하나와 연관된 활성 데이터의 크기보다 작고 이로 인해 nursery 수집 시간 간의 시간 간격이 트랜잭션 하나보다 적은 경우에는 데이터가 여러 번 복사되어야 한다는 사실이 표시되어 있다.


그림 6. 데이터가 복사되는 평균 횟수 vs. nursery 수집 시간 간의 시간 간격
데이터가 복사되는 평균 횟수 vs. nursery 수집 간의 시간 간격

nursery 힙의 크기가 커지고 nursery 수집 간의 시간 간격이 증가함에 따라 데이터가 복사되는 평균 횟수는 줄어들고 가비지 콜렉션의 오버헤드가 감소한다.

nursery 힙 크기의 한계

IBM 가비지 콜렉터나 JVM에 의해 부과되는 nursery 힙 크기에 직접적인 한계는 없으며, 사실상 nursery 힙의 크기가 대략 수십 기가바이트나 수백 기가바이트로 설정되는 경우도 있다. 그러나 충분한 실제 메모리(RAM)의 가용성뿐만 아니라 가상 메모리와 프로세스 주소 공간과 관련하여 Java 프로세스가 고수해야 하는 한계(운영 체제에 의해 부과되는)가 있다. 32비트 프로세스용 플랫폼의 운영 체제의 한계는 그림 7에 표시되어 있다.


그림 7. 운영 체제별 32비트 주소 공간
운영 체제별 32비트 주소 공간

64비트 프로세스의 한계는 훨씬 더 크다. 주소로 지정이 가능한 메모리가 수백에서 수십억 기가바이트에 이르지만 훨씬 더 중요한 것은 사용 가능한 실제 메모리(RAM)의 한계이다.


종합하기

위에서 살펴본 바와 같이 가장 단순한 접근방식은 nursery 힙을 추가적인 메모리 공간으로 처리하는 것이다. 그러나 사실상 nursery 힙과 tenured 힙은 -Xmx 설정으로 메모리의 크기를 제어할 수 있는 연속된 단일 메모리 세그먼트로 할당된다. -Xmx 설정만 사용하는 경우에는 -Xmx 값의 25%가 최대 nursery 힙 크기로 사용되며 25% 내에서 nursery 힙의 크기를 늘리거나 줄일 수 있다. 그림 8에는 Java 힙의 레이아웃이 표시되어 있다.


그림 8. 기본 힙 레이아웃
기본 힙 레이아웃

그러나 nursery 힙의 크기를 큰 값으로 수정하여 가비지 콜렉션에 소요되는 시간을 최소화해야 하고, tenured 힙이 점유율에 따라 스스로 크기를 조정하여 복원력을 갖추도록 해야 한다. 따라서 선호하는 Java 힙 레이아웃은 그림 9와 같이 된다.


그림 9. 권장되는 힙 레이아웃
기본 힙 레이아웃

이러한 레이아웃을 완성하기 위해서는 nursery 및 tenured 영역의 최소 및 최대 힙 크기의 개별 값을 설정해야 하며 최소 및 최대 nursery 힙 크기를 서로 동일하게 설정하고 최소 및 최대 tenured 공간 크기를 서로 다른 값으로 설정해야 한다.

예를 들어, nursery 힙의 크기를 256MB로 하고 tenured 힙의 크기를 756MB와 1024MB 사이로 하면 개별 값은 다음과 같이 된다.

-Xmns256M
-Xmnx256M
-Xmos756M
-Xmox1024M


세대 정책으로 마이그레이션하기

WebSphere Application Server V8에서는 기본 GC 정책이 optthruput에서 gencon으로 변경되었기 때문에 이전에 선택한 튜닝 매개변수를 조정해야 한다. 기본적인 문제는 힙의 크기를 변경하여 nursery 힙을 보완하는 데 있다. 이전에 optthruput 하에서 1GB 힙(즉, -Xmx1G)으로 제대로 실행된 프로그램이 tenure 공간 768MB와 nursery 공간 256MB만으로는 제대로 실행되지 않을 수도 있다. 위에서 언급한 기술은 힙 매개변수를 새로 선택하는 데 도움이 된다.

gencon이 다른 작동을 표시할 수도 있는 기타 불분명한 상황이 있다.

일반적으로 클래스는 오랫동안 활성화되는 오브젝트이므로 직접 tenure 공간에 할당된다. 결과적으로 클래스 로드 해제는 tenure 콜렉션의 일부로서만 수행될 수 있다. 애플리케이션이 단기간 활성화되는 클래스 로더에 매우 의존하고 nursery 콜렉션에서 할당된 기타 오브젝트와 접촉할 수 있는 경우에는 tenure 콜렉션이 매우 빈번하게 발생하지는 않는다. 이는 클래스와 클래스 로더의 수가 계속해서 증가하고 이로 인해 기본 메모리에 대한 압력이 가중되면 수행할 클래스 로드 해제 작업이 너무 많아지기 때문에 이러한 현상이 발생할 때는 tenure 콜렉션에 소요되는 시간이 매우 길어진다는 것을 의미한다.

이러한 문제점이 발생하는 경우에는 두 가지 해결책이 있다. 첫 번째는 대용량 클래스 로더가 존재하는 상태에서 tenure 콜렉션을 추가로 진행하는 것이다. 명령행 옵션 -Xgc:classUnloadingKickoffThreshold=<number>는 클래스 로더 <number>개가 새로 작성될 때마다 동시 tenure 콜렉션이 시작되도록 시스템에 지시한다. 따라서 이 명령행 옵션을 -Xgc:classUnloadingKickoffThreshold=100으로 지정하면 마지막 tenure 콜렉션 이후로 클래스 로더 100개가 새로 작성되었다는 것을 nursery 콜렉션에서 확인할 때마다 동시 tenure 콜렉션이 시작된다. 두 번째 해결책은 기타 GC 정책 중 하나를 변경하는 것이다.

비슷한 문제점이 참조 오브젝트(예: java.lang.ref.Reference의 서브클래스)와 finalize() 메소드가 있는 오브젝트에서 발생할 수 있다. 이러한 오브젝트 중 하나가 도달 불가능한 상태가 되기 전에 tenure 공간으로 이동하게 될 정도로 충분히 오래 존재하는 경우에는 tenure 콜렉션이 실행되어 해당 오브젝트가 도달 불가능한 상태에 있다는 것이 "파악"되려면 시간이 오래 걸릴 수 있다. 이러한 오브젝트가 대규모 자원이나 희소 원시 자원에 의지하는 경우에는 이점이 문제가 될 수 있다. 이 오브젝트는 Java 힙 중 적은 용량만 차지하지만, 그 이면에는 가비지 콜렉터가 확인할 수 없는 대용량 원시 자원이 숨어 있다는 점에서 필자는 이 오브젝트를 "iceberg" 오브젝트라고 부른다. 실제 빙산에서와 마찬가지로 가장 좋은 전략은 가능한 문제점을 피해가는 것이다. 기타 GC 정책 중 하나를 사용하는 경우에도 종결 가능한 오브젝트가 도달 불가능한 상태로 발견되고 종결자가 적절한 방식으로 실행된다는 보장이 없다. 희소 자원이 관리되고 있는 경우에는 가능하면 이 자원을 수동으로 릴리스하는 것이 언제나 가장 좋은 전략이다.

정책 변경

기본 정책은 대부분의 워크로드에 적합한 성능을 제공하지만, 특정 애플리케이션에서는 기본 정책이 이상적인 선택이 아닐 수도 있다.

"일괄처리 작업"처럼 작동하는 애플리케이션은 초기 상태를 설정한 후에는 조작할 데이터를 로드한다. 이러한 오브젝트의 대부분은 작업 기간에는 활성화되어 있으며 작업이 실행됨에 따라 소수의 오브젝트만 추가로 작성된다. 태스크가 완료될 때까지는 가비지가 거의 없을 것으로 예상되므로 이러한 워크로드는 optthruput 모델에 적합하다. 이와 매우 유사한 경우에는 매우 신속하게 완료되거나 거의 오브젝트를 할당하지 않는 작업은 힙 크기가 적절하게 지정된 가비지 콜렉션을 하지 않아도 실행할 수 있다. 이러한 경우에는 optthruput 콜렉터의 최소 오버헤드가 좋은 선택이 된다.

이와는 반대로 트랜잭션 애플리케이션은 오브젝트 그룹을 계속해서 작성하고 버린다. 이러한 상황에서는 "트랜잭션"이라는 용어가 거의 문자 그대로의 의미로 사용되거나(예: 데이터베이스 업데이트나 전자상거래를 통해 물품을 구입하는 경우) 훨씬 더 광범위한 의미의 개별 작업 단위로 사용될 수 있다. 예를 들면, 웹 페이지를 서비스하는 것은 트랜잭션으로 간주된다. 클라이언트가 URL을 제출하면 서버가 이 페이지의 컨텐츠를 처리하여 다시 클라이언트로 전송한다. 클라이언트가 이 페이지를 수신하면 서버는 처리된 데이터를 버린다.

이러한 정의를 조금 더 확장하기 위해 표준 사용자 인터페이스를 생각해보자. 사용자가 Save 단추를 클릭하면 시스템은 파일 대화 상자를 열어서 사용자가 파일 시스템을 탐색하여 해당 문서의 위치를 선택할 수 있게 한다. 사용자가 이 대화 상자에서 떠나면 이러한 중간 상태는 모두 불필요해진다. 드러나지는 않았지만 사실상 일부 일괄처리 작업도 트랜잭션이다. 대형 이미지 파일 콜렉션용 썸네일 이미지를 작성하는 태스크는 하나의 대형 일괄처리 작업처럼 보이지만, 내부적으로는 작업에서 이미지가 별도로 처리되고 있으며 각 작업은 하나의 트랜잭션으로 구성된다. 이러한 워크로드의 경우에는 gencon 모델을 사용하는 것이 좋다.

optavgpause 모델은 어중간하다. 프로그램이 실행됨에 따라 천천히 변하는 수명이 긴 데이터가 많은 애플리케이션은 이 모델이 적합하다. 이는 특별한 워크로드 패턴이며 일반적으로, 수명이 긴 데이터는 거의 변경되지 않거나 자주 변경되지 않는다. 그렇지만, 중간 오브젝트를 많이 생성하지 않는, 천천히 변경되는 데이터 세트가 있는 시스템은 이 정책을 사용하는 것이 좋다. 위에서 논의한 문제점 중 하나로 인해 gencon 하에서 효과적으로 실행할 수 없는 프로그램은 optavgpause의 동시 특성을 이용하는 것이 좋다.


결론

이 기사에서는 WebSphere Application Server V8의 Java Virtual Machine에서 사용 가능한 가비지 콜렉션 전략을 간단하게 설명했다. 대부분의 경우에는 기본 설정만으로도 잘 수행되지만, 성능을 최적화하려면 약간 튜닝을 해야 한다. 사용되는 GC 정책을 워크로드 유형에 맞추고 적합한 힙 매개변수를 선택하면 가비지 콜렉션이 애플리케이션에 미치는 영향을 줄일 수 있다.

이 시리즈의 Part 2에서는 대형 64비트 멀티코어 시스템에 배치하는 경우에 확장성을 개선할 수 있게 설계된, 영역 기반 가비지 콜렉션 전략인 balanced를 새로 소개할 것이다. 이 기사에서는 이 새로운 옵션에 대한 튜닝 팁과 힌트뿐만 아니라 이 전략이 제공하는 새로운 기술과 성능 개선사항 이면에 있는 동기를 다루게 된다.


참고자료

교육

제품 및 기술

필자소개

Chris Bailey는 2000년 Southampton University의 대학원생 시절에 IBM Java Technology Centre에 입사했다. 자바 기술과 자바 플랫폼 기반 제품의 IBM 포트와 관련된 문제를 해결하는 일을 했다. 그는 "IBM Java Runtimes and SDKs" 이라는 developerWorks 포럼을 운영하고 있고 현재에는 자바 플랫폼의 IBM 포트의 사용자들이 사용할 수 있는 정보 및 툴링을 향상시키는데 주력하고 있다.

Charlie Gracie는 캐나다에 있는 Ottawa Lab, IBM Java Technology Center 팀의 구성원이다. 그는 university of New Brunswick에서 BCS 학위를 받았으며 2004년 이후로는 J9 Virtual Machine 팀에서 근무했다. 현재는 J9 Garbage Collection 팀의 리더로, IBM JVM의 모든 가비지 콜렉션 기술을 제공하는 업무를 담당하고 있다. 여가 시간에는 실내나 해변에서 배구를 하거나 다양한 실외 활동을 즐긴다.

Karl Taylor는 캐나다에 있는 Ottawa Lab, IBM Java Technology Center 팀의 구성원이다. 그는 Carleton University에서 BCS 학위를 받았으며 프로젝트가 시작된 후로는 J9 Virtual Machine 팀에서 다양한 역할을 수행했다. 현재는 J9 Garbage Collection 팀의 수석 개발자이며, IBM의 JSR 292 및 335 활동에도 참여하고 있다. Karl은 와인 애호가로 여가 시간에는 소믈리에 자격증을 취득하기 위해 노력하고 있다.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=WebSphere
ArticleID=787564
ArticleTitle=WebSphere Application Server V8의 가비지 콜렉션, Part 1: 새로운 기본 정책인 세대 콜렉션 전략
publish-date=06222011

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.