JVM 학습 노트와 실전 개선(3): 자바 대상 메모리 분배와 탈출 분석

4898 단어
태그:JVM
1. Java 객체의 할당:
  • 창고분배
  • 스레드 사유 소대상
  • 무탈출
  • 스칼라 교체 지원
  • 튜닝 필요 없음(가상 머신 자동 최적화, 튜닝 필요 없음)
  • TLAB(Thread Local Allocation Buffer) 스레드 로컬 할당
  • eden 점용, 기본 1%, 무더기 신청, 라인 전용
  • 다중 스레드 시 경쟁(잠금)eden 없이 신청 공간(동시 제거), 효율 향상
  • 소형 객체
  • 튜닝 불필요
  • 구시대
  • 큰 대상(대수조, 긴 문자열)
  • eden
  • new 일반 대상

  • 분배 정책: JVM이 탈출 분석을 시작하면 new의 대상이 먼저 창고에 분배를 시도한다. 분배가 안 되면 루트 로컬에 분배를 시도한다. 만약에 창고에 분배와 루트 로컬에 분배가 모두 실패하면 그 대상이 큰 대상인지 아닌지를 먼저 판단하고 큰 대상이라면 오래된 시대에 메모리를 분배한다. 그렇지 않으면 신세대 eeden구에 분배한다.2. 탈출 분석: 탈출 분석은 다른 최적화 수단에 근거를 제공하는 분석 기술로 그 기본적인 행위는 분석 대상의 동태적 역할 영역이다. 한 대상이 방법에 정의된 후에 외부 방법에 인용될 수 있다. 예를 들어 호출 파라미터로 다른 방법에 전달되는 것을 방법 탈출이라고 한다.클래스 변수에 복사되거나 다른 라인에서 접근할 수 있는 실례 변수인 외부 라인에 접근할 수도 있습니다. 이를 라인 탈출이라고 합니다.객체가 메서드나 스레드 외부로 도주하지 않을 경우 객체를 효율적으로 최적화할 수 있습니다.
  • 스택에 Stack Allocation 할당: 객체가 메소드 외부로 도주하지 않을 경우 해당 객체가 스택에 메모리를 할당하여 실행 효율을 높일 수 있으며 객체가 차지하는 메모리는 스택 프레임이 스택을 벗어나면서 폐기됩니다.일반적인 응용에서 탈출이 없는 국부 변수 대상이 차지하는 비율이 비교적 크다. 만약에 창고에서 분배를 사용할 수 있다면 대량의 대상은 방법의 끝에 따라 자동으로 소각되고 GC압력은 많이 줄어든다.
  • 동기화 제거 Synchronization Elimination: 스레드 동기화는 상대적으로 시간이 걸리는 과정이다. 만약에 탈출 분석이 한 변수가 스레드에서 탈출하지 않고 다른 스레드에 접근할 수 없다는 것을 확정할 수 있다면 이 변수의 읽기와 쓰기는 경쟁 관계가 존재하지 않는다. 즉, 이 변수에 대한 동기화 조치를 제거할 수 있다
  • 스칼라 교체:
  • 표량: 하나의 데이터가 더 작은 데이터로 분해될 수 없다는 것을 의미한다. 자바 가상기의 원시 데이터 형식(int,float 등 수치 유형과reference 유형)은 더 이상 분해할 수 없다
  • 집합량: 표량에 비해 한 데이터가 계속 분해될 수 있다면 집합량이라고 할 수 있고 자바 대상은 전형적인 집합량이다.
  • 자바 대상을 분리하면 프로그램이 접근하는 상황에 따라 사용한 구성원 변수를 원시 형식으로 복원하고 이 과정은 표량 교체
  • 가 된다.
  • 만약에 탈출 분석을 통해 한 대상이 외부에 접근하지 않고 이 대상이 해체될 수 있음을 확인할 수 있다면 프로그램이 실제로 실행될 때 이 대상을 만들지 않고 그 대상을 직접 만드는 구성원 변수로 대체할 수 있다.객체를 버스트한 후 스택에 메모리를 할당할 수 있음

  • 3. 테스트 실례: 참고 코드
    package com.vechace.JVM;
    
    /**
    * Description: 10000000 , , JVM 
    *  
    * @author vechace
    *    -XX:-DoEscapeAnalysis   
    *    -XX:-EliminateAllocations  
    *    -XX:-UseTLAB  
    *    -XX:-PrintGC  GC 
    */
    public class JVMTest1 {
        
        class User{
            int id;
            String name;
            
            User(int id,String name){
                this.id = id;
                this.name = name;
                
            }
        }
        
        void alloc(int i){
            new User(i,"name"+i);
        }
    
        public static void main(String[] args) {
            
                JVMTest1 t = new JVMTest1();
                long s1 = System.currentTimeMillis();
                for(int i = 0;i<10000000;i++){
                    t.alloc(i);
                }
                long s2 = System.currentTimeMillis();
                System.out.println(s2-s1);
    
        }
    
    }
    

    IDE:Eclipse
    run As --> run configuration --> Argument --> VM argument: 다음 구성을 입력합니다.
    -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB -XX:+PrintGC
    

    결과 분석:
    a. 탈출 분석, 스택에 할당되지 않음, 스레드 로컬 메모리를 사용하지 않음:
    -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB -XX:+PrintGC
    

    콘솔 출력:
    [GC (Allocation Failure)  49152K->688K(188416K), 0.0010012 secs]
    [GC (Allocation Failure)  49840K->728K(188416K), 0.0009848 secs]
    [GC (Allocation Failure)  49880K->640K(188416K), 0.0007432 secs]
    [GC (Allocation Failure)  49792K->672K(237568K), 0.0008412 secs]
    [GC (Allocation Failure)  98976K->640K(237568K), 0.0012708 secs]
    [GC (Allocation Failure)  98944K->656K(328704K), 0.0008696 secs]
    [GC (Allocation Failure)  197264K->624K(328704K), 0.0017397 secs]
    [GC (Allocation Failure)  197232K->624K(320512K), 0.0003312 secs]
    791
    

    b. 스레드 로컬 메모리를 사용하여 eeden 구역에서 메모리를 분배할 때 잠그지 않아도 효율이 높아진다
    -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+UseTLAB -XX:+PrintGC
    

    콘솔 출력:
    [GC (Allocation Failure)  49760K->640K(188416K), 0.0007129 secs]
    [GC (Allocation Failure)  49792K->624K(237568K), 0.0008062 secs]
    [GC (Allocation Failure)  98928K->608K(237568K), 0.0014966 secs]
    [GC (Allocation Failure)  98912K->728K(328704K), 0.0008608 secs]
    [GC (Allocation Failure)  197336K->588K(328704K), 0.0016310 secs]
    [GC (Allocation Failure)  197196K->620K(525312K), 0.0003275 secs]
    528
    

    c. 탈출 분석 활성화, 스레드 대체 사용, 스레드 로컬 메모리 사용, 효율 향상
    -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+UseTLAB -XX:+PrintGC
    

    콘솔 출력:
    [GC (Allocation Failure)  49152K->688K(188416K), 0.0010576 secs]
    [GC (Allocation Failure)  49840K->640K(188416K), 0.0009443 secs]
    [GC (Allocation Failure)  49792K->640K(188416K), 0.0007502 secs]
    [GC (Allocation Failure)  49792K->696K(237568K), 0.0008981 secs]
    [GC (Allocation Failure)  99000K->656K(237568K), 0.0011229 secs]
    [GC (Allocation Failure)  98960K->608K(328704K), 0.0010558 secs]
    [GC (Allocation Failure)  197216K->644K(328704K), 0.0015396 secs]
    486
    

    문제 분석: 탈출 분석을 시작할 때 비용이 존재하고 때로는 효율이 탈출 분석을 하지 않았을 때의 효율보다 높지 않다.

    좋은 웹페이지 즐겨찾기