일반적으로, 적시(Just-in-Time) 컴파일러와 같은 동적 컴파일러는 프로그램의 실행 중에 컴파일을 하므로 컴파일 오버헤드가 실행시간에 포함된다. 이러한 컴파일 오버헤드를 줄이기 위해서는 수행시간이 큰 핫스팟 메소드(Hotspot Method)에 대해서만 선택적으로 컴파일을 해야 한다. 그러나 핫스팟 메소드를 찾기 위한 오버헤드도 역시 수행시간의 일부이므로 작은 오버헤드로 정확하게 핫스팟 메소드를 찾는 방법이 필요하다.
핫스팟 메소드를 찾는 대부분의 방법은 기본적으로 비용-이익(cost-benefit) 모델을 바탕으로 하고 있다. 즉 어떤 메소드를 컴파일하여 수행했을 때 얻을 수 있는 수행시간의 이득이 그 메소드를 컴파일하는데 필요한 수행시간의 비용보다 더 크면 그 메소드를 컴파일하는 것이다. 다음의 수학식 1로 이 비용-이익 모델을 표현할 수 있다.
(컴파일 비용〈 컴파일 이익) → (메소드 컴파일)
어떤 메소드를 컴파일하여 얻을 수 있는 이익은 그 메소드가 앞으로 얼마만큼 수행될지를 예측해서, 해당 메소드를 컴파일한 기계어를 수행하였을 때의 수행시간 감소분을 이익으로 추정할 수 있다. 미래의 수행시간을 정확하게 예측한다는 것은 불가능하겠지만 수행 중 임의의 시점에서 어떤 메소드의 현재까지의 수행 시간을 측정한 결과를 바탕으로 그 메소드의 남은 수행시간을 추측하는 방법을 생각해볼 수 있다. 즉, 현재까지 많이 수행된 메소드가 앞으로도 많이 수행될 가능성이 높다고 판단하는 것이다.
어떤 메소드의 현재까지의 수행시간을 측정하기 위한 가장 간단하고 쉬운 방법은 그 메소드가 실행될 때 마다 메소드의 시작 부분과 끝 부분에서 시각을 측정하여 그 차이를 구하여 누적하는 것이다. 그러나 이렇게 시간을 측정하는 함수의 호출은 매우 큰 수행시간 오버헤드를 수반할 뿐 아니라 너무 짧은 시간에 대해서는 정확성이 떨어진다. 따라서 이렇게 절대적인 수행시간을 측정하는 대신 상대적인 수행시간을 비교하기 위하여 각 메소드의 수행 빈도를 측정하는 방법이 많이 사용 된다.
서버나 데스크탑용 가상머신에서 많이 사용하는 기술은 샘플링(Sampling)을 이용한 것이다.
도 1은 종래 기술에 따른 샘플링 기법을 사용하여 수행시간을 추정하는 방법을 나타내는 흐름도이고, 도 2는 종래 기술에 따른 샘플링 기법에 의해 수행 중 해석기에서 동작하는 코드를 예시하는 도면이다.
샘플링은 도 1 및 도 2에 나타낸 것처럼 별도의 쓰레드(thread)를 이용하여 주기적으로 현재 실행되고 있는 메소드들을 확인하고 각 메소드의 관찰된 횟수를 현재까지의 수행시간으로 추정한다. 즉, 관찰된 횟수가 많은 메소드는 그 만큼 많이 수행된 메소드이다. 이 기법은 작은 오버헤드로 비교적 정확하게 상대적인 수행 시간을 얻을 수 있다.
또 다른 기술은 해석기의 수행 도중 메소드의 호출 횟수나 메소드 내의 명령어들의 수행 횟수를 측정하여 상대적인 수행시간을 얻는다.
이 기술에서는 호출 횟수나 수행 횟수를 측정하는 코드를 해석기에서 추가로 수행해야 하는데 이로 인한 수행시간 오버헤드가 매우 클 수 있다. 그래서 수행시간에 큰 영향을 주는 명령어들만 횟수를 측정하여 다소 정확도가 떨어지더라도 오버헤드를 줄이는 방법이 사용되기도 한다.
선 마이크로시스템즈(Sun Microsystems)사에서 배포한 핫스팟(HotSpot) 자바 가상머신에서는 이러한 종래의 기술을 채택하여 핫스팟 휴리스틱이라는 기법을 사용하고 있다.
도 3은 종래 기술에 따른 핫스팟 휴리스틱 기법의 수행시간 추정 방법을 나타내는 흐름도이고, 도 4는 종래 기술에 따른 핫스팟 휴리스틱 기법의 수행시간 중 동작하는 코드를 예시하는 도면이다.
이는 도 3 및 도 4에 도시된 바와 같이 메소드의 호출 횟수와 메소드 내의 후방 분기 명령어의 수행 횟수만을 측정한 결과를 바탕으로 현재까지의 수행시간을 추정하는 방식이다.
구체적으로 다음의 수학식 2와 같이 수행시간을 추정한다.
(추정 수행시간) = C1× (호출 횟수) + C2× (후방 분기 수행 횟수), 여기서 C1과 C2는 상수
이것은 메소드가 호출될 때 마다 기본적인 수행시간(C1)이 더해지고 추가로 후방 분기가 수행될 때마다 이로 인한 반복문의 수행시간(C2)이 더해지는 방식으로 메소드의 수행시간을 추정하는 것이다. 이 방식은 측정에 의한 오버헤드를 최소화하면서 반복문에 의한 수행시간의 증가도 반영할 수 있다.
또 다른 방법으로, 정적 분석(Static Analysis) 기법이 있다.
도 5는 종래 기술에 따른 정적 분석 기법에서 수행시간 추정 방법을 나타내는 흐름도이고, 도 6은 종래 기술에 따른 정적 분석 기법에서 수행시간 중 동작하는 코드를 예시하는 도면이다.
해당 정적 분석 기법은 명령어의 수행 횟수를 해석기가 동적으로 따로 측정하지 않고 메소드를 정적으로 분석하여 메소드를 한 번 실행하는 것에 대한 수행시 간을 결정한 뒤, 메소드가 호출될 때마다 이 값을 바탕으로 수행시간을 추정하는 방식이다. 이 정적 분석 방식에서는 각 명령어의 종류에 따라 가중치를 부여하고 각 메소드에 속한 명령어의 가중치를 합산한 메소드의 크기로 수행시간을 추정하는데 메소드 수행의 흐름을 분석하여 반복문에 의해 증가하는 수행시간도 추산한다. 구체적으로 다음의 수학식 3에 의해 메소드의 1회 수행에 대한 수행시간을 추정한다.
(메소드 1회 수행에 대한 추정 수행시간) = (메소드의 크기) + ((반복문의 크기) × C3)
여기서 C3는 반복문의 반복 횟수를 나타내는데, 핫스팟 휴리스틱처럼 동적으로 후방 분기의 분기 횟수를 측정하는 것이 아니라 모든 반복문은 동일하게 같은 횟수(C3)가 반복된다고 가정한다. 그리고 반복문의 크기는 반복문에 속한 모든 명령어 가중치의 합과 중첩된 내부의 반복문에 의해 증가되는 추정 수행시간을 합한 결과로 반복문에 의해 반복되어 실행되는 모든 명령어 가중치의 합이다. 이 방식은 반복문이나 포함되는 명령어에 따른 메소드의 특성을 반영할 수 있고 매 실행마다 명령어들의 수행 횟수를 측정하는 오버헤드가 없다.
메소드들의 상대적인 수행 시간을 비교하여 핫스팟을 찾는 방법으로 서버나 데스크 탑에서 많이 사용하는 방법은 샘플링이다. 그러나 종래의 샘플링 방법은 얻은 값이 주기적으로 집계한 표본에 의한 추측 값이기 때문에 측정할 때마다 결과가 달라질 수 있다. 또한 핫스팟을 빨리 인식하고 컴파일 하는 데에는 불리하다. 특히 내장형 시스템에서는 일반적으로 CPU의 타이머 단위가 너무 커서 샘플링 주기를 충분히 작게 하기 힘들기 때문에 의미 있는 결과를 얻기가 힘들다.
주어진 메소드 M의 상대적인 수행시간 T(M)을 측정하는 가장 쉽고 직접적인 방법은 해석기에 의해 바이트코드를 수행할 때 수행된 명령어들의 개수를 세어 T(M)을 구하는 것이다. 특히 명령어마다 실제 수행시간이 다르므로 명령어의 종류에 따라 다른 가중치를 두고 수행된 명령어들의 가중치를 합하여 T(M)을 구하면 더 정확할 것이다.
그러나 모든 명령어가 수행될 때 마다 T(M)값을 갱신하면 이에 따르는 수행시간 오버헤드는 무시할 수 없을 정도로 크다. 따라서 수행시간에 의미있는 영향을 미치는 “중요한” 명령어를 수행할 때에만 T(M)값을 갱신하면 그 오버헤드를 줄일 수 있다. 많은 메소드가 수행시간의 대부분을 반복문에서 보내는 경향이 있으므로 반복문의 존재를 의미하는 후방 분기 명령어가 수행 시간에 큰 영향을 주는 중요한 명령어라고 볼 수 있고, 메소드의 호출과 같이 메소드 호출 과정에 의한 수행시간을 포함하여 가중치가 큰 가중 명령어들도 중요한 명령어로 볼 수 있다.
종래의 핫스팟 휴리스틱은 반복문을 고려하여 후방 분기 명령어의 수행 횟수를 측정하나 메소드의 크기나 반복문의 크기, 혹은 가중 명령어는 고려하지 않는다. 특히 메소드의 크기나 반복문의 크기에 대해 동일한 상수 값을 적용한다는 점에서 합당하지 않다. 그리고 사용되는 상수를 특정 프로그램에 맞춰 고정할 경우 프로그램에 따라 성능의 편차가 생길 수 있다. 또한 전방 분기나 메소드의 리턴에 의해 수행되지 않는 명령어의 수행시간이 더해져 정확성이 감소한다.
또한, 종래의 정적 분석의 경우 반복문의 크기는 고려하지만 후방 분기의 수행 횟수를 동적으로 측정하지 않고 모두 같은 상수 값을 사용한다. 따라서 실제 반복문의 수행 횟수와는 차이가 나서 추정 수행시간에 오차가 생긴다.
따라서, 이러한 방법들은 측정의 오버헤드는 줄일 수 있겠지만 추정한 수행시간의 정확성을 떨어져 핫스팟 메소드 감지의 정확성이 감소한다.
그리고 정적 분석 방법을 제외한 다른 방식들은 모두 메소드의 호출 횟수나 후방 분기의 횟수와 같은 동적으로 얻는 정보를 바탕으로 컴파일 여부를 결정하므로 반드시 메소드를 한 번 이상 해석기로 실행하는 것이 필요하다. 그러나 일부 핫스팟 메소드의 경우 호출횟수는 많지 않으나 일단 호출되면 압도적인 수행시간을 갖는 데 이러한 핫스팟 메소드의 경우 이렇게 한 번이라도 해석기로 수행하는 것 자체가 큰 오버헤드가 되므로 처음 호출되었을 때 바로 컴파일할 수 있는 방법이 필요하다.
최소의 오버헤드로 메소드의 수행 시간을 정확히 추정하기 위해, 후방 분기 와 가중 명령어만을 고려하는 기존의 동적 분석 방식과는 달리 전방 분기와 리턴들도 함께 고려하여 실행 경로를 따라가며 간단한 계산을 통해 수행 시간을 구하는 동적 분석 방법을 사용한다. 이 동적 방법의 그 정확도는 모든 명령어를 세어 수행 시간을 구하는 경우와 같도록 하여 핫스팟의 인식의 정확성을 높인다.
또한 정적으로 수행 시간을 분석하는 방법도 사용하여 압도적인 수행 시간을 갖는 메소드를 정적으로 핫스팟으로 예측하여 처음 호출되었을 때 바로 컴파일이 되도록 한다.
이를 위하여 본 발명은, (a-1) 메소드가 호출되면, 메소드가 호출되었을 때의 명령어의 위치(PC(A))를 기록하고, 메소드의 상대적인 수행시간(T(M))에 메소드의 크기값(M)을 증가시키는 단계; (a-2) 분기 명령어가 수행되면, 해당 분기를 통해 뛰어넘는 명령어의 크기(오프셋)를 메소드의 상대적인 수행시간(T(M))에 가감시키는 단계; (a-3) 가중 명령어가 수행되면, 해당 가중 명령어의 추가 가중치를 메소드의 상대적인 수행시간(T(M))에 합산하는 단계; (b) 상기 (a-3) 단계 수행 이후, 리턴 명령어가 수행되면, 리턴 명령어가 수행되는 명령어의 위치값(PC(R))에서 상기 메소드가 호출된 명령어의 위치값(PC(A))을 차감한 뒤 호출된 명령어의 크기를 더하고, 상기 메소드의 크기값(M)에서 해당 값을 차감하여 수행불능 명령어의 개수를 산정하는 단계; 및 (c) 상기 메소드의 상대적인 수행시간(T(M))에서 상기 수행불능 명령어의 크기를 차감하여 메소드의 상대적인 수행시간(T(M))을 보정하는 단계; 를 포함하는 것을 특징으로 한다.
바람직하게는, 상기 (a-2) 단계에서, 분기 명령어에 따른 오프셋 산정시, 후 방 분기 명령어이면 메소드의 상대적인 수행시간(T(M))에서 오프셋에 분기 명령어의 크기를 합산한 것을 합산하고, 전방 분기 명령어이면 메소드의 상대적인 수행시간(T(M))에서 오프셋을 합산한 뒤 분기 명령어의 크기를 가감하는 것을 특징으로 한다.
더욱 바람직하게는, 상기 메소드의 크기값(M)은 바이트코드의 크기의 합인 것을 특징으로 한다.
더욱 바람직하게는, 상기 가중 명령어는 바이트코드에 비해 긴 수행시간을 가지는 명령어인 것을 특징으로 한다.
더욱 바람직하게는, 상기 (a-1) 단계 이전에, 메소드의 수행 이전에 메소드 내의 명령어를 각각 정적으로 분석하여 예상되는 수행 시간을 추정하는 정적 분석 방식을 미리 실시하여 사전에 바로 컴파일할지 여부를 결정하는 단계; 가 더 포함되는 것을 특징으로 한다.
더욱 바람직하게는, 상기 정적 분석 방식에서는 후방 분기 명령어와 가중 명령어의 크기를 이용하여 예상 수행시간을 추정하는 것을 특징으로 한다.
더욱 바람직하게는, 후방 분기를 만나는 경우, 오프셋 크기에 해당하는 명령어가 반복문에 의해 반복되는 회수(C4)를 가정하고 오프셋에 해당 회수를 곱하여 예상 수행시간에 더하는 것을 특징으로 한다.
더욱 바람직하게는, 적어도 둘 이상의 후방 분기에 의해 중첩된 반복문이 형성되는 경우, 메소드 내의 모든 후방 분기 명령어의 오프셋을 이용하여 후방 분기의 대상을 구하고, 바깥의 반복문에 의해서 반복되는 예상 수행시간을 안쪽의 반복 문 오프셋을 제외한 바깥의 반복문 오프셋에 반복 회수(C4)만큼 반복된 안쪽의 반복문 오프셋을 더하여 추정하는 것을 특징으로 한다.
더욱 바람직하게는, 가중 명령어를 만나는 경우, 가중 명령어의 추가 가중치를 더하여 예상 수행시간을 추정하는 것을 특징으로 한다.
본 발명에서는 실행 경로를 따라가며 만나는 주요 경우를 고려하므로 종래의 샘플링 방식에서 샘플 주기에 따라 확률적으로 얻어지는 값에 비해 실제 수행시간에 더욱 근접한 값을 구할 수 있다. 더군다나 샘플링에 필요한 별도의 쓰레드를 구동하는 오버헤드와, 본 발명의 주요 경우에서 간단한 계산을 추가하는 오버헤드는 큰 차이가 없다.
또한, 종래의 핫스팟 휴리스틱 방식과 비교해도, 특정 포인트에서 일정한 상수를 더하는 것에 비해, 명령어의 개수와 각 명령어의 실제 수행시간에 대한 고려를 하기 때문에 훨씬 정확한 결과를 얻을 수 있다. 그럼에도 불구하고 수행시간에 추가되는 오버헤드가 전방 분기와 가중 명령어, 그리고 리턴의 경우에 불과하고 그 빈도가 낮기 때문에, 늘어나는 수행시간이 비교적 적다.
그리고 정적인 분석에 의한 핫스팟 메소드 감지를 추가하여 큰 수행시간의 메소드를 더 일찍 발견하므로 그만큼 수행시간의 단축을 꾀할 수 있다.
그리하여 해석기와 적시(Just-in-Time) 컴파일러를 함께 사용하는 동적 컴파일 시스템에서 비교적 적은 수행시간 오버헤드로도 각 메소드의 실제 수행시간과 유사한 값을 얻을 수 있어서 핫스팟 메소드를 더 정확히 빨리 찾을 수 있게 된다. 따라서 불필요한 컴파일을 줄이고 핫스팟을 빨리 컴파일 함으로써 전체적인 가상머신 수행의 속도를 높일 수 있다.
본 발명의 동적 분석에서는 측정 시간의 정확성은 높이되 그로 인한 추가 수행시간 오버헤드는 매우 작은 방법을 제시한다.
우선 종래 기술의 정적 분석에서처럼 명령어의 수행시간을 고려하여 명령어를 단순 명령어와 가중 명령어로 구분한다. 단순 명령어는 그 명령어의 크기 자체를 그 명령어의 추정 수행시간으로 규정하고 가중 명령어는 그 명령어 크기와 종류에 따라 가지는 추가 가중치를 더한 값을 추정 수행시간으로 정의한다. 주어진 메소드에 대해서 그 메소드가 호출되어 해석기에 의해 수행될 때마다 수행되는 모든 명령어들의 추정 수행시간을 합하면 그 메소드의 현재까지의 수행시간을 정확히 추정할 수 있다.
그러나 위에서 기술했듯이 수행되는 모든 명령어에 대해서 이러한 합산을 한다면 그로 인한 수행시간 오버헤드가 너무 클 것이다. 이를 줄이기 위하여 다음과 같은 방법을 사용한다. 어떤 메소드 M의 현재까지 수행 시간을 T(M)이라고 할 때, 다음의 명령어가 수행될 때만 T(M) 값을 변경시킨다.
첫번째 메소드 M이 호출될 때, 두번째 가중 명령어가 수행될 때, 세번째 분기 명령어가 수행되어 분기될 때, 네번째 리턴 명령어에 의해 현재 메소드의 수행이 완료될 때만 T(M)을 변경한다.
이를 도 7 내지 도 9를 참조하여 설명하면 다음과 같다.
도 7은 본 발명에 따른 수행시간 추정 방법을 나타내는 흐름도이고, 도 8은 본 발명에 따른 수행시간 중 동작하는 코드를 예시하는 도면이고, 도 9는 본 발명에 따른 수행시간 예측 방법을 나타내는 흐름도이다.
도 7 및 도 8을 참조하면, 첫번째로, 메소드 M이 호출되면 우선 M에 속한 명령어의 추정 수행시간의 합인 메소드 M의 크기만큼 T(M)을 증가시킨다.
이를 다음의 수학식 4와 같이 표현할 수 있다.
T(M) = T(M) + M의 크기
만약 M의 모든 명령어들이 단순 명령어들이며 분기 명령어가 없어서 모두 단 한 번씩만 수행된다면 이렇게 합산된 T(M)은 그대로 호출된 메소드 M의 수행시간이 될 것이다. 그러나 실제 그렇지 않을 가능성이 높은데, 이 경우 이하에서 설명되는 바와 같이 가중 명령어나 리턴 명령어가 수행될 때와 분기 명령어가 수행되어 분기될 때를 통해 T(M)을 보정할 수 있다.
두번째로, 가중 명령어가 수행되면 그 명령어의 추가 가중치를 상기 T(M)에 더한다. 가중 명령어가 수행될 때 가중 명령어의 크기는 이미 T(M)에 반영되어 있으므로 추가 가중치만 더하면 된다. 가중 명령어의 추가 가중치를 W라고 하면 이를 다음의 수학식 5와 같이 표현할 수 있다.
T(M) = T(M) + W
세번째로, 분기 명령어가 수행되어 실제로 분기가 일어나면(즉, 분기가 실 행(taken)되면), 분기에 의해 명령어가 반복하여 수행되거나(후방 분기 명령어의 경우) 혹은 분기에 의해 명령어가 수행되지 않으므로(전방 분기 명령어의 경우) 이에 맞춰 T(M) 값을 보정한다. 분기 명령어에 의해 뛰어넘는 명령어 크기의 합(분기 명령어에 종종 표현되어 있음)을 오프셋(offset)이라 할 때, 이 과정을 다음의 수학식 6과 같이 표현할 수 있다.
T(M) = T(M) + (오프셋) + (분기 명령어의 크기)(후방 분기의 경우)
T(M) = T(M) - (오프셋) + (분기 명령어의 크기)(전방 분기의 경우)
즉, 후방 분기가 수행되면 뛰어넘는 명령어와 분기 명령어가 추가로 한 번 더 실행될 것으로 가정하고 뛰어넘는 명령어의 추정 수행시간인 오프셋과 분기 명령어의 추정 수행시간인 그 크기를 T(M)에 더한다. 만약 가중 명령어가 오프셋에 포함되어 있다면 상술한 가중 명령어가 수행될 때의 과정을 통해 T(M)값이 보정될 것이다. 또한 오프셋 중 또 다른 분기 명령어나 리턴 명령어가 있어 가정한 것 보다 명령어가 추가로 더 수행되거나 반대로 덜 수행될 경우도 동일한 과정에 의해 추정 수행시간이 보정된다.
그리고 전방 분기가 수행되면, 메소드 M이 호출될 때나 혹은 후방 분기의 수행으로 이미 T(M)에 합산되어 있던 오프셋에 속한 명령어에서 해당 전방 분기 명령어를 제외한 나머지 명령어가 수행되지 않으므로 T(M)에서 오프셋만큼의 추정 수행시간을 뺀 뒤, 다시 분기 명령어의 추정 수행시간인 그 크기를 더한다. 가중 명령어가 오프셋에 포함되어 있더라도 전방 분기에 의해 실행되지 않으므로 상기 두번 째 가중 명령어가 수행될 때의 과정에 의해 T(M)에 합산되지 않는다. 따라서 해당 가중 명령어의 가중치를 추가로 빼지 않아도 된다.
네번째로서, 리턴 명령어가 수행되면 해당 메소드는 동작이 완료된다. 이때 메소드의 리턴 명령어가 수행될 때까지 분기 명령어가 한 번도 수행되지 않았다면, 그 메소드에서 리턴 명령어 이후의 남은 명령어들은 모두 수행되지 않는다. 리턴 명령어가 수행되기 전 후방 분기 명령어가 수행된 경우 상기 세번째 분기 명령어가 수행되어 분기될 때의 과정에 의해 추정 수행시간이 추가되는데 그 오프셋 범위 내에 리턴 명령어가 존재하고 수행된다면 더해진 추정 수행시간 중 리턴 명령어 이후의 명령어들은 역시 수행되지 않는다.
따라서 리턴 명령어가 수행될 때, 이러한 오차를 보정할 필요가 있다. 이를 위해 프로그램 카운터(PC : Program Counter)를 이용하는데, PC는 현재 수행되는 명령어의 위치를 가리킨다.
메소드가 호출되었을 때의 PC 값을 PC(A)이라 하고, 이를 저장하였다가 리턴 명령어가 수행될 때 현재의 PC 값(PC(R))에서 저장된 PC 값(PC(A))을 빼고 리턴 명령어의 크기를 더하면 그 메소드의 시작부터 리턴 명령어까지의 크기를 구할 수 있다. 이 값을 메소드의 크기인 M에서 빼면 수행하지 못한 명령어 크기의 합이 된다. 리턴 명령어가 수행될 때 이 합을 T(M)에서 빼면 보정이 완료된다. 이를 다음의 수학식 7과 같이 표현할 수 있다.
T(M) = T(M) - ( M - (PC(R) - PC(A) + (리턴 명령어의 크기)))
전방 분기의 경우는 수행과 동시에 오프셋에 포함된 명령어들이 모두 수행되지 않음이 확정되므로 오프셋 내의 리턴 명령어는 추정 수행 시간에 영향을 미치지 않는다.
상술한 첫번째 메소드 M이 호출될 때, 두번째 가중 명령어가 수행될 때, 세번째 분기 명령어가 수행되어 분기될 때, 네번째 리턴 명령어에 의해 현재 메소드의 수행이 완료될 때의 과정만을 통하면 모든 명령어가 수행될 때 T(M)을 갱신하는 것과 동일한, 정확한 추정 수행시간을 얻을 수 있으나 그 측정 오버헤드는 최소화된다.
특히 구현을 위해서는 첫번째 메소드 M이 호출될 때의 경우 메소드가 호출될 때마다 한 번 T(M)값을 메소드의 크기만큼 증가하는 동작을 해석기에 추가하면 된다. 실제 메소드의 명령어들을 수행하기 위한 해석기 내의 구조는 각 명령어에 대한 스위치문(switch 문)으로 되어있으므로 두번째 가중 명령어가 수행될 때, 세번째 분기 명령어가 수행되어 분기될 때, 네번째 리턴 명령어에 의해 현재 메소드의 수행이 완료될 때를 위해서는 해당 명령어가 수행되는 케이스문(case 문)에 T(M) 값을 변경하는 동작을 추가하면 된다(여기에서 명령어가 분기 명령어인지 가중 명령어, 또는 리턴 명령어인지를 별도로 비교하는 동작은 필요하지 않음). 따라서 구현의 오버헤드도 작다.
한편 종래 기술의 핫스팟 휴리스틱은 메소드의 호출 횟수나 후방 분기의 횟수를 동적으로 합산하여 이를 근거로 컴파일 여부를 결정하므로 비교적 정확하게 핫스팟 메소드를 감지할 수 있으나 이를 위해서는 반드시 한 번 이상의 해석기 실 행을 필요로 한다.
반면 종래 기술의 정적 분석 방식에서는 메소드의 수행 이전에 메소드 내의 명령어를 각각 분석하여 예상되는 수행시간을 구하고 메소드의 매 호출마다 이 예상 수행시간이 소요된다고 가정하므로, 실제 메소드의 수행 방식에 따라 핫스팟을 감지하는 정확도는 낮지만 큰 수행시간을 가지는 메소드의 경우 이를 사전에 파악할 수 있을 것이다.
본 발명의 정적 분석에서는 수행시간이 압도적으로 큰 일부 메소드를 컴파일 이전에 한 번 이상 해석기에서 수행하는 불이익을 제거하기 위하여 기존의 정적 분석 방식과 같이 해석기 실행 이전에 정적으로 메소드를 분석하여 핫스팟 메소드의 여부를 예측할 수 있도록 하였다. 즉 각 메소드를 해석기에서 실행하기 이전에 정적으로 분석한 결과를 바탕으로 해당 메소드를 사전에 컴파일할 것인지를 결정함으로써, 그 메소드가 압도적인 수행시간을 가지는 경우 이를 해석기에서 실행하면서 생기는 성능 저하를 방지할 수 있다. 특히 기존의 정적 분석과는 달리 매우 적은 오버헤드로 분석이 가능하고 오로지 첫 번째 호출에 대해 컴파일 여부를 결정하는 목적으로만 사용한다.
도 9를 참조하면, 본 발명의 정적 분석에서는 어떤 메소드가 최초로 호출되어 해석기에 의해 실행되기 이전에 미리 그 메소드의 수행시간을 예측한다. 임의의 메소드 M의 예측 수행시간 P(M)은 메소드가 해석기에 의해 한 번 실행될 때를 가정하여 이를 위에서 기술한 동적으로 추정 수행시간을 얻는 것과 유사한 방식에 의해 추정한 수행 시간으로 규정하되, 이 때 동적으로만 얻을 수 있는 정보는 적절한 가 정으로 대체한다.
어떤 메소드를 정적으로 분석할 때, 메소드의 모든 명령어를 순차적으로 하나씩 읽어 나가면서 앞의 동적 분석에서 고려했던 네 가지 경우에 해당되는 다음의 경우(첫번째 메소드를 분석을 시작할 때, 두번째 분기 명령어를 만났을 때, 세번째 리턴 명령어를 만났을 때, 네번째 가중 명령어를 만났을 때)에 대해 아래와 같은 동작을 수행 한다.
첫번째로 정적 분석을 시작할 때에는 동적인 수행시간 추정과 마찬가지로, 기본적으로 메소드의 모든 명령어가 처음부터 순서대로 수행된다고 가정하고 다음의 수학식 8과 같이 예측 수행시간을 메소드의 크기로 초기화한다.
P(M) = M의 크기
두번째로 분기 명령어를 만났을 때는 분기의 실행 여부를 정적 분석으로는 알 수 없으므로 본 발명에서는 단순하게 후방 분기는 일정 회수만큼 실행되고, 전방 분기는 실행되지 않는다고 가정한다.
먼저 명령어가 후방 분기일 경우 이 분기에 의해 반복문이 형성될 가능성이 높다. 그러므로 오프셋 크기에 해당하는 명령어가 반복문에 의해 일정 회수(C4)만큼 반복된다고 가정하여, 오프셋에 이 일정 회수를 곱하여 예상 수행시간에 더한다.
또한 두 개 이상의 후방 분기에 의해 중첩된 반복문이 형성되는 경우에 대해서도 적절한 수행시간의 책정이 필요하다. 먼저 메소드 내의 모든 후방 분기 명령 어의 오프셋을 이용하여 후방 분기의 대상을 구한다. 어떤 후방 분기의 대상이 이전에 위치한 다른 후방 분기의 대상보다 더 위에 있으면 전자에 의한 반복문이 후자에 의한 반복문을 포함하므로 후자에 의한 반복문이 중첩되었다고 판단한다. 후자는 전자에 의해 일정 회수(C4)만큼 반복되므로 전자에 의해 증가되는 예상 수행시간은 후자에 의해 증가한 예상 수행시간에 전자의 오프셋을 더하여 일정 회수를 곱한 값이 된다. 단 이미 후자가 전자보다 위에 위치하므로 사전에 더한 후자에 의한 예상 수행시간은 제외한다. 즉, 바깥의 반복문에 의해서 일정 회수만큼 반복되는 예상 수행시간은 안쪽의 반복문 오프셋을 제외한 바깥의 반복문 오프셋에 일정 회수만큼 반복된 안쪽의 반복문 오프셋을 더한 것이 된다. 따라서 이를 다음의 수학식 9와 같이 나타낼 수 있다.
P(M) = P(M) + (바깥의 반복문 오프셋 - 안쪽의 반복문 오프셋 + 안쪽의 반복문 오프셋 x C4) x C4
전방 분기 명령어의 경우 반복문에 의해 반복될 가능성이 낮고, 후방 분기 명령어에 비해 실제로 분기되는 빈도가 낮으므로 실행되지 않는다고 가정하여 예상 수행시간을 그대로 유지한다.
세번째로 리턴 명령어를 만나면 메소드의 실행이 완료된다고 분석한다. 대부분의 메소드에서 리턴 명령어는 메소드의 마지막 바이트코드이며, 그렇지 않은 경우는 전방 분기를 통해서 리턴 명령어로 가능 경우 인데 전방 분기가 실행되지 않는다고 가정했으므로 이런 경우도 없다고 가정한다.
네번째로 가중 명령어를 만나면 단순히 가중 명령어의 추가 가중치를 P(m)에 더해준다. 동적으로 수행시간을 추정할 때는 가중 명령어가 실행될 때마다 해당하는 추가 가중치를 추정 수행시간에 더했지만, 정적 분석에서는 해당 가중 명령어가 몇 번이나 수행될지 알 수 없으므로 한 번만 수행된다고 가정하고 다음의 수학식 10과 같이 가중 명령어의 추가 가중치(W)를 더한다.
P(M) = P(M) + W
위에 기술한 정적 분석은 동적인 수행시간 분석과 달리 동적으로 얻는 정보를 배제하므로 그 결과인 예상 수행시간은 실제 수행시간과의 오차가 상대적으로 크다. 그러나 각 메소드의 최초 해석기 실행 이전에 단 한 번만 분석하므로 동적인 수행시간 추정에 비해 오버헤드가 적으면서, 한 번의 실행에 의한 수행시간이 압도적으로 큰 메소드를 해석기 실행 이전에 발견하여 사전에 컴파일되도록 할 수 있다.
이러한 정적 분석과 동적 분석은 핫스팟 발견을 위해 다음과 같이 사용될 수 있다. 우선 어떤 메소드가 호출되면 본 발명의 정적 분석을 수행하여 핫스팟인가를 판단한다. 만약 핫스팟이라고 판단되면 컴파일하여 수행하고 그렇지 않으면 본 발명의 동적 분석을 통해 수행 시간을 추정하여 호출시마다 핫스팟 여부를 판단하여 컴파일한다. 이러한 과정은 도 10에 나타나 있다.