메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

임베디드 자바

한빛미디어

|

2002-02-26

|

by HANBIT

10,947

저자: 빈센트 페리에(Vincent Perrier), 역 최원용

임베디드 자바를 위한 자바의 강력한 매력은 가끔씩 속력과 메모리 필요성에 대한 관심으로 보충되나 자바의 수행 속도를 높이고 메모리 필요성을 줄이기 위해 사용할 수 있는 기술이다. 물론 여러분이 선택하는 자바 가상 머신(JVM) 또한 자바 퍼포먼스에 영향을 미친다. 임베디드 애플리케이션을 위한 최선의 벤치마크를 선택하고 퍼포먼스에 영향을 주는 요소에 대한 한 부분으로 자바 사용과 관련하여 더 나은 결정을 할 수 있다.

애플리케이션 실행을 개선하거나 올바른 JVM을 선택하는 기술은 전체적인 자바 퍼포먼스에 영향을 주는 시스템구조 중에서도 극소수의 구조에만 사용한다. 퍼포먼스상에서 충돌을 다루는 이 기사의 범위를 넘어서 임베디드 자바 플랫폼을 선택할 때 여러분은 기타 여러 가지 요소도 고려해야 한다. 하드웨어 프로세서 선택, 자바 적합성과 API들 지원, 애플리케이션의 안전성과 확장성, 라이브러리와 드라이버로 구성된 실시간 운영체제(RTOS)의 선택, 자바 개발 툴킷과 미들웨어의 유용성, 그래픽스 지원과 ROM으로부터 애플리케이션 코드화 능력이 그것들이다.

일단 하드웨어와 소프트웨어 개발 플랫폼을 선택다면, 애플리케이션을 위한 최적화 수행의 JVM을 선택을 도와줄 수 있는 다양한 요소에 대해 생각해보도록 하자.

크고 느린 자바, 근거 없는 소리인가? 현실인가?

루츠 프렉헬트(Lutz Prechelt)가 수행한 「Comparing Java vs C/C++ Efficiency Differences to interpersonal Differences」(Communications of the ACM, October 1999) 연구에 의하면 평균적으로 자바 바이트코드 애플리케이션 수행이 C 또는 C++로 짜여진 같은 프로그램보다 약 10배 느리더라도 자바로 짜여진 애플리케이션은 수행 효과가 아주 크다고 할 수 있다고 한다. 이 연구에서 38명의 프로그래머는 똑 같은 응용 프로그램을 C/C++ 또는 자바로 작성해 줄 것을 부탁 받았다. 프로그램을 위해 퍼포먼스 데이터 통계 분석을 적용하는 것은 동적 퍼포먼스의 차이점이 기존의 언어에서 짜여진 프로그램을 위해 더 많은 것에 의지함을 드러냈다. 정말로 연구 결과는 잘 짜여진 자바 프로그램은 평균치의 C/C++프로그램보다 훨씬 더 또는 똑같이 프로그램을 수행 할 수 있다는 것을 보여준다.

바이트코드 수행 속도를 올리는 데 유용하게 사용될 수 있는 것으로는 다음과 같은 것이 있다. JIT (just-in-time) 컴파일러, ahead-of-time 컴파일러, 또는 dynamic adaptive 컴파일러, ROM에 자바 애플리케이션 코드 입력하기, 어셈블리 언어에서 JVM의 바이트코드 해석을 재작성하기, 자바 하드웨어 가속기 사용하기 등등…

컴파일러 고려 사항


자바는 왼쪽으로 보이는 무거운 그래픽 툴킷 또는 오른쪽으로 보이는 가벼운 버전의 그래픽 툴 킷과 함께 하드웨어 레벨에서 그래픽 실행한다. 가벼운 버전은 수행속도가 빠르며 더 작은 메모리 자취를 가진 반면 쓰기 기능은 어렵고 느리다

수행을 하는 동안에 바이트코드를 컴파일하는 JIT컴파일러는 일반적으로 임베디드 애플리케이션에는 적합하지 않다. 그것은 데스크탑 자바 애플리케이션에서 훌륭하게 퍼포먼스 실행을 하지만 추가적으로 애플리케이션에서 16~3MB의 RAM을 필요로 한다. 메모리가 많이 필요한 임베디드 애플리케이션의 많은 분야에서 JIT 컴파일러가 쓰인다.

Ahead-of-time 컴파일러는 JIT 컴파일러와 자바 수행속도를 증가시키기 위해서 경쟁관계에 있다. JIT 컴파일러와는 달리 Ahead-of-time 컴파일러는 애플리케이션이 타켓 디바이스에서 작동되기 전에 사용되었다 마치 이름을 지정한 것처럼 Ahead-of-time 컴파일러는 필요한 추가 RAM을 제거하나 플래시 메모리 또는 더 많은 ROM을 필요하게 만든다. 왜냐하면 머신 코드를 컴파일 하는 것은 자바 바이트코드를 4~5번 정도 필요로 하기 때문이다. ahead-of-time 컴파일은 동적 확장 측정을 잃어버릴수 있기 때문에 자바 플래폼의 장점 중 하나를 잊어버릴 수 있다. 따라서 컴파일된 클래스의 새 버전을 다운받을 수 없을지도 모른다. 부가적으로 거주자가 코드를 컴파일 하는 것 보다 실행 속도가 느리며 ahead-of-time 컴필레이션으로부터 이득을 얻지 못한다.

자바 코드가 복잡할지라도, ahead-of-time 컴파일러를 이용하면 코드 확장을 최소화 하는 데 도움이 된다. 최상의 목표는 애플리케이션이 80% 또는 그 이상을 보내는 자바 클래스를 단지 20%로 컴파일하는 것이다.


위 그림에서처럼 Dynamic adaptive 컴파일러는 JIT와 ahead-of-time 컴파일러와 비교해 볼 때 장점이 있다(위 그림 참고). 바이트코드를 머신 코드로 바꿔주는 것이 JIT 컴파일러와 비슷하다. 그러나 Dynamic adaptive 컴파일러는 코드 장점을 컴파일하고 JVM이 바이트코드를 해석하도록 하게하는 결정하는 애플리케이션 코드를 통계적인 분석을 수행한다. 이런 타입의 컴파일러를 사용하는 메모리는 사용자용으로 제작된다. 따라서 컴파일러에 얼마의 메모리를 할당해야 할 지 결정하고 메모리와 속도 교환을 평가할 수 있다.

ROM으로 바이트코드를 입력하는 것은 애플리케이션 퍼포먼스를 향상시켜주지만 코드를 빠르게 해주지는 않는다. 그렇지만 코드가 ROM에서 직접 실행할 수 있게 JVM에서 형식을 바꾸어 준다. 즉 클래스 로딩과 코드 확인과정이 없어 코드 로딩이 빠르다. 이는 보통 JVM에 의해 수행된다.

dynamic compilation 기술 또는 ahead-of-time을 사용하지 않고 바이트코드 수행속도를 올리는 다른 방법은 JVM에서 바이트코드 인터프리터를 재기술한다. 왜냐하면 인터프리터가 큰 용량의 C 프로그램이기 때문에 어셈블리 언어를 재작성하여 빨리 작동하게 만들어줄 수 있기 때문이다. 의외로 빨리 사용하는 것이 없는 바이트코드 실행 또는 동적인 편집물 기술의 속도를 빠르게 하는 또 다른 길은 JVM에서 바이트코드 통역을 다시 쓴다. 변환은 거대한 C 프로그램이기 때문에 어셈블리 언어로 다시 써주면 더 빠르게 실행시킬 수도 있다.

자바 하드웨어 가속기 또는 자바 칩은 코드 실행 속도를 빠르게 해주는 훌륭한 기능이다. 이것은 두 가지 기초적인 설정을 떠오르게 한다. 칩은 Chicory 시스템의 HotShot과 Nazomi Communication의 JSTAR와 같은 첫 번재 타입의 칩이다. 그래픽 액샐레이터를 사용한 것과 같은 방식의 일반용 마이크로프로세서와 함께 자바 프로세서로서 가동된다. 다른 타입의 자바 칩들은 일반 CPU에 설치된 Patriot Scientific의 PSC1000 과 aJile의 aJ-100과 비슷하다.

분명 후자는 자바로 완전히 쓰여질 수 있는 애플리케이션을 제한했다. 첫 번째 타입에 대해 말하자면, 구성요소 증가는 물론 비용 증가를 의미한다. 따라서 이 타입은 단 적절한 비용이 투입되었을 때 실행할 수 있는 기능이 제공된다. 실제로 자바 칩의 가격은 생산량이 많지 않기 때문에 비싼 편이다. 하지만 좋은 해결책으로 Jazelle라고 불리는 통합 자바 가속기와 함께 일반적인 프로세서인 ARM940 형식이 해결책이 될 수도 있다.

메모리 요구사항

프렉헬트가 수행한 연구는 자바로 작성된 프로그램의 평균 메모리 요구량이 C/C++로 작성된 같은 프로그램보다 2,3배정도 크다고 했다. 바아트코드의 간결한 특징상 대개 C/C++ 머신 코드로 컴파일된 것 보다 약 50% 정도가 작다고 해도 오버해드를 보충할 수 없다. 임베디드 시스템이 작동하지 않는 데스크탑 지향 형태인 자바 개발사인 썬 마이크로시스템즈는 임베디드 환경에서도 적응할 수 있는 언어를 만들기 위해 여러 가지 진화를 거듭하였다. 오늘날, 자바 2 플랫폼 Micro Edition(J2ME)은 임베디드 공간을 위해 자바를 잘 업데이트시킨 초경량화 된 최신품이다.

J2ME는 애플리케이션에 필요하지 않은 클래스와 코드 구성 요소를 제거할 수 있다. ROM에 JVM, 기본 라이브러리, 코어 클래스와 애플리케이션 바이트코드를 입력한다. 임베디드 자바를 위한 JVM는 일반적으로 500 kb미만에서 작동하는데 반해, J2ME를 위한 클래스 라이브러리는 일반적으로 1.5 MB를 능가하지 않는다. RAM 필요량에 영향을 미치는 자바 구성 요소는 JVM(바이트코드 실행에 대해), 잠재적인 dynamic 컴파일러, 자바들, 스레드(뒤에 언급된 두 가지는 분명 애플리케이션에 의존함)를 포함한다. 허가 할 수 있는 실행 퍼포먼스를 유지하는 동안 인터프리터를 사용하는 애플리케이션을 사용하는 것은 메모리를 추적할 수 있게 해준다.

확장가능한 운영체제와 C 런 타임 패키지를 선택하는 것은 최적의 메모리 능률을 위해 이러한 소프트웨어 구성 요소를 조정할 수 있게 한다. 대개 2단계의 절차를 포함하고 있어 자바 환경을 확장하는 것은 복잡할 수 있다. 첫째, 여러분은 명령 라인 verbose 옵션, 애플리케이션이 사용하는 클래스를 보기위한 Java ?v를 사용할 수 있고, 그 다음 필요한 라이브러리와 클래스를 수동으로 뽑아낼 수 있다. 만일 이 과정에서 충분한 공간을 저장하지 않는다면 썬사의 임베디드자바 플랫폼에서 JavaFilter 같은 필터링 도구들을 사용할 수 있다.

만일 자바를 사용하고 있다면, C/ C++(아래 그림 참조)를 사용한 것과 비교하여 메모리과 CPU 리소스를 늘릴 것을 예상해야 한다.


적절한 자바 플랫폼 선택

물론 JVM 선택은 애플리케이션을 위해 자바 퍼포먼스를 최적화하는 핵심 중 하나이다. 분명히 임베디드 애플리케이션을 위해 설계된 JVM를 필요로 한다.

임베디드 JVM은 서로 다른 내장 시스템 요구를 매치하기위한 고도의 사용자 설정식(user-configuration)이다. 그러나 여러분이 사용해야 할 임베디드 JVM은 과연 무엇인가? 자바 벤치 마크는 여러분이 JVM과 자바 퍼포먼스를 평가하는 데 도움을 준다는 데 의미가 있다. 그러나 이때 여러분은 어느 것을 사용할 지와 이로부터 얻은 결론에 대해 주의할 필요가 있다. 특별한 JVM를 위한 좋은 벤치마크 점수가 반드시 애플리케이션을 더 빠르게 만들어주는 것을 의미하지는 않는다.

따라서 JVM을 평가하기 전에, 여러분은 어떤 벤치 마크라도 전체 Java 환경을 고려하면서, 그것이 애플리케이션에 얼마나 의미가 있을 지를 결정하기 위하여 평가해야 한다. 어떤 벤치 마크는 너무 애플리케이션 특정적이며(예를 들면 VolanoMark와 같은 채팅 서버 벤치 마크), 개발중인 자바 애플리케이션이 이와 같은 부류의 애플리케이션을 지원하지 않을지도 모른다. 게다가 JVM 벤더가 좋은 벤치 마크 점수를 얻기 위해 자신들의 제품을 일반적으로 최적화하기 때문에 JVM이 특정 애플리케이션의 퍼포먼스를 얼마나 향상시킬 것인지에 관하여 오보할 수도 있다. 반대로 만일 애플리케이션이 어떤 부분에서 특정 문제를 가지고 있으면, 일반 처리를 개선하기 위해 최적화된 환경은 이와 같은 특정의 처리 문제를 해결하지 않을 것이다.

애플리케이션 퍼포먼스 측정하기

벤치 마크가 자바 애플리케이션의 총체적인 성능을 결정한다고 생각할 때, 바이트코드 실행, 원시 코드 실행과 그래픽에 대한 각각의 역할을 염두해 두어야 한다. 이것들의 충돌은 특정 애플리케이션의 특성에 따라 변화한다. 애플리케이션의 역할, 원시 코드 대 바이트코드의 수, 얼마나 많은 그래픽이 사용되는지 등이 애플리케이션에 영향을 미치는 요소이다. 주어진 애플리케이션에서 JVM이 얼마나 잘 수행할 것이냐는 이와 같은 세 분야의 혼합에 크게 의존한다. JVM을 벤치마크 하기위한 가장 좋은 방법 애플리케이션 대신에 변수를 주는 것이다. 여러분은 애플리케이션을 작성 전 그 이후로, 여러분이 작성하려는 애플리케이션에 가장 관련 있는 벤치 마크를 찾아야합니다.

임베디드 애플리케이션과 관련 있는 것들을 찾기 위해 자바 벤치 마크를 분류하는 것은 혼란스러울 수 있다. 예를 들어 SpecJVM98은 JVM의 다양한 측면을 테스트하는 비교적 완성된 벤치마크 세트를 제공한다. 이것은 흥미롭게 들리긴 하지만 Spec-JVM-98은 클라이언트/서버 환경으로 작동되며 JVM를 위해 최소한 클라이언트 측에 48 MB의 RAM을 필요로 한다. 이것은 어떤 관련성으로부터 대부분의 임베디드 자바를 제외한다. 게다가 그것은 사전 컴파일된 클래스들과 함께 사용될 수 없다.

다른 벤치 마크에도 다른 함정들이 있다. 예를 들어 VolanoMark는 채팅용 서버 도구이다. 따라서 그러므로 채팅 서버를 벤치마킹하는 애플리케이션과만 관계가 있다. JMark 벤치 마크는 애플리케이션이 자바의 추상 윈도우 툴킷(AWT, Abstract Windowing Toolkit) 전체 툴과 애플릿 뷰어를 포함하는 것을 당연하다고 생각한다. 따라서 이 벹치마크는 그래픽이 없는 수많은 임베디드 애플리케이션과 관계가 없을 수 있거나 개인용 자바 미니 AWT 구현을 실행시키는 디바이스처럼 완전한 AWT 지원을 요구하지 않는 제한되 그래픽을 갖게될 수 있다.

Pendragon Software사의 CaffeineMark 벤치 마크의 임베디드 버전인 Embedded CaffeineMark(ECM)는 단지 기본적인 자바 코어 클래스만을 필요로 하고 큰 메모리를 필요로 하지 않기 때문에 어떤 임베디드 JVM이라도 동작이 쉽다. 더 중요한 것은 이 벤치마크의 좋은 점수와 임베디드 애플리케이션의 바이트코드 퍼포먼스를 개선한 것과 높은 상관관계가 있다는 사실이다.

ECM에서 의미가 있는 결과를 얻기 위해, 여러분은 다른 JVM들을 테스트할 때 정확하게 같은 하드웨어를 사용해야 한다. 그리고 테스트하고 있는 JVM의 도구들 사이의 차이점에 대해 주의를 기울여야 한다. 예를 들어 만일 아무것도 없이 JVM에 반대하여 JVM를 JIT 컴파일러와 비교하면, 애플 대 애플 비교를 보증하기위해 명령 라인에 java -nojit 옵션을 JIT와 함께 가지는 JVM을 작동시키는 것은 중요하다.

ECM은 컴필레이션의 타입과는 상관없이 좋아보이는 컴필레이션을 사용해 JVM을 만들 것이다. 컴필레이션 타입이 어떤 것인지는 중요하지 않다. 이유는 항상 같은 명령 세트를 되풀이하고 작은 클래스들의 세트를 포함하고 있기 때문이다. 동적 컴파일러는 단지 RAM에 있는 자바 코드의 완벽한 변환을 캐시하고 원시 코드에 있는 테스트를 되풀이 해서 실행할 것이다. ahead-of-time 컴파일러는 ECM에 사용했던 알고리즘과 루프로 쉽게 최적화 할 수 있다.

자바 업계에서는 Java Grande, SciMa, jBYTEma, Dhrystone 벤치마크, 이 외에도 자바를 위한 UCSD 벤치마크처럼 다른 자바 벤치마크는 많이 있지만 임베디드 애플리케이션에서 자바와 JVM 퍼포먼스에 대한 확실한 결과를 주는 그런 최고의 벤치마크는 없다. 최선의 전략은 애플리케이션과 가장 유사한 관계가 있는 벤치마크 세트로 확인하고 특정 시스템 환경에서 자바 퍼포먼스를 예측하는데 도움을 주기위해 사용하는 것 뿐이다.

기존 벤치마크는 애플리케이션 코드의 다른 측면은 측정할 수 없다. 퍼포먼스 수행능력을 달성하기 위해 자바 애플리케이션을 튜닝하는 것은 바이트코드 실행 외에도 많은 프로그램 함수 처리를 요구할 수 있다. 예를들어 스레드 관리, 동기화, 메소드 대 메소드 호출, 클래스 결정, 객체 할당, 힙 관리(가비지 컬렉션 포함), 원시 메소드로 호출, 바이트코드 검증 및 예외처리와 같은 기능은 모두 JVM에서 나온다. 만약 어떤 벤치마크라도 이런 기능들에 대해 설명한다면 디자인이 애플리케이션에 얼마나 영향을 미칠지를 이해하기 위해 JVM의 내면적 특징을 면밀하게 연구하게 한다. JVM의 치명적인 부분을 연습하는 특별한 프로그램을 작성하는 것은 여러분이 애플리케이션을 평가하는데 도움을 줄 수 있다. 예를 들어 애플리케이션에 자바와 C 코드가 혼합되어 있다면 여러분은 원시 메소드 호출 퍼포먼스를 테스트하는 프로그램을 작성하여 이득을 얻을 수 있다. 다른 기능으로 JVM의 외부에서 원시 코드 수행, 네트워크 대기시간 같은 요소를 포함한 기능들이 있을 수도 있다.

그래픽 퍼포먼스

만약 애플리케이션에 그래픽을 포함되어 있다면 어떻게 할 것인가? 그래픽 실행에 영향을 미치는 두 가지 주요한 요인이 자바 애플리케이션에 있다. 애플리케이션의 그래픽 디스플레이 드라이버는 그래픽 다중프로세서 하드웨어 가속을 사용하는가? 애플리케이션이 AWT의 lightweight(빠름)이나 heavyweight(느림) 도구와 함께 설정 되는가? 게다가 다른 고수준 자바 서비스처럼 그래픽 퍼포먼스는 그래픽 서비스가 저수준 원시 라이브러리와 함께 통합되는 방식으로 그래픽 퍼포먼스에 영향을 준다.

Wind River의 퍼스널 JWorks는 임베디드 시스템에서 그래픽 퍼포먼스를 평가하기 좋은 벤치 마크를 내장하고 있다. 벤치 마크는 기본 2D 그래픽, 텍스트, 스크롤링, 버튼, 39개의 테스트 이미지 세트로 PersonalJAVA AWT를 목표로 한다.

실무 수행능력

이제 여러분은 CPU 퍼포먼스 고려하게 될 것이다. CPU 퍼포먼스 확인을 돕기 위해 용량이 크고 복잡한 자바코드를 실행하는 실무 애플리케이션을 실행함으로써 단순한 벤치마크를 대체해야 한다. 이와 같은 테스트 코드는 몇 가지 요구 조건을 충족해야 한다. 이런 조건으로는 실제 애플리케이션 평가를 반영하는 많은 클래스들을 포함해야 할 것, 용량이 커야 하며 (적어도 1000줄) 파일 시스템 접근과 그래픽이 없어야 하는 것 등이 있다. 기존 프로그램들은 모든 표준을 충족한다. 예를 들어 GNU 정규표현 패키지, regexp는 파싱하고 매칭하는 수많은 표현을 제공하면서 3,000줄이나 되는 코드와 21개 이상의 클래스로 이루어져 있습니다. 다른 프로그램인 빈 셸 변환기는 수천 줄의 코드와 70개의 클래스를 가지는 간략한 기본체이다. JavaCodeCompact는 썬의 PersonalJava ROMizing 도구이며 훌륭한 테스트 프로그램이다.

테스트 경우처럼 이러한 프로그램의 실행 결과는 벤치마크 점수에서 다양한 의미를 나타낸다. 예를 들어 JIT 컴파일러를 이용하는 JVM은 nojit 옵션이 포함되었을 때보다 임베디드 CaffeineMark를 30배까지 빠르게 실행할 수 있다(따라서 단순한 변환 모드에서 실행됨). 그렇지만 같은 JVM이라고 하더라도 JIT 컴파일러를 사용할 때 빈 셸과 regexp 테스트는 겨우 1.5배 빠르게 실행할 뿐이다. (임베디드 CaffeineMark와 같은 간단한 벤치마크에서 30배 정도의 눈에 띄는 속도향상은 ECM의 클래스들과 코드의 적은 양을 이용하는 것처럼 캐싱 기술을 통해 확보된 것이다.) 결과상 차이는 분명 높은 벤치마크 점수가 실무 애플리케이션에서 성능 향상의 적정한 수준으로 변환되지 않을 수 있다는 것을 증명한다.

실제로 SpecJVM98, JMark은 실무 애플리케이션을 위한 가장 근접한 적정 레벨 변환의 결과를 낳는다. 위에서 언급된 한계점들이 있지만 그것들은 해결될 수 있다. 특히 임베디드 영역에서 SpecJVM98, Jmark의 유용성은 시험 인프라 요구사항과 관련된 문제를 극복할 수 있는 여러분의 능력에 달려있다고 할 수 있다.

빈센트 페리에(Vincent Perrier)는 자바 플랫폼 관리자로 임베디드 개발자 저널에서 편집자로 일하고 있다.
TAG :
댓글 입력
자료실

최근 본 책0