자바에서 프리미티브를 유지하는 경우

프리미티브는 1996 년 초기 출시 이후 자바 프로그래밍 언어의 일부 였지만 여전히 논쟁의 여지가있는 언어 기능 중 하나입니다. 존 무어는 프리미티브가 있거나없는 간단한 자바 벤치 마크를 비교하여 자바 언어로 프리미티브를 유지하는 강력한 사례를 만듭니다. 그런 다음 자바의 성능을 스칼라,씨++,및 자바 스크립트 프리미티브가 주목할만한 차이를 만드는 특정 유형의 응용 프로그램에서.

질문: 부동산 구입에 있는 3 개의 가장 중요 한 요소는 무엇입니까?
답변:위치,위치,위치.

이 오래되고 자주 사용되는 격언은 부동산에 관해서는 위치가 다른 모든 요소를 완전히 지배한다는 것을 암시하기위한 것입니다. 비슷한 주장에서 자바에서 원시 유형을 사용하기 위해 고려해야 할 가장 중요한 세 가지 요소는 성능,성능,성능입니다. 부동산에 대한 인수와 프리미티브에 대한 인수 사이에는 두 가지 차이점이 있습니다. 첫째,부동산,위치는 거의 모든 상황에서 지배하지만,기본 유형을 사용하여 성능 향상은 다른 응용 프로그램의 한 종류에서 크게 다를 수 있습니다. 둘째,부동산,비록 그들은 일반적으로 위치에 비해 사소한 고려해 야 할 다른 요인이 있다. 기본 형식을 사용하는 이유는 성능뿐 아니라 응용 프로그램이 해당 형식을 사용할 때 이점을 얻을 수 있는 종류인 경우에만 사용할 수 있습니다.

프리미티브는 백엔드의 데이터베이스와 함께 클라이언트-서버 프로그래밍 모델을 사용하는 대부분의 비즈니스 관련 및 인터넷 응용 프로그램에 거의 가치를 제공하지 않습니다. 그러나 수치 계산에 의해 지배되는 응용 프로그램의 성능은 프리미티브의 사용에서 크게 혜택을 누릴 수 있습니다.

자바에 프리미티브를 포함시키는 것은 이 결정과 관련된 기사 및 포럼 게시물의 수에 의해 입증된 바와 같이 언어 디자인 결정 중 가장 논란이 많은 결정 중 하나였다. 사이먼 리터는 2011 년 11 월 그의 잭스 런던에서 자바의 미래 버전에서 프리미티브를 제거하는 데 심각한 고려가 주어지고 있다고 지적했다(슬라이드 41 참조). 이 글에서 나는 간단히 프리미티브와 자바의 듀얼 타입 시스템을 소개합니다. 코드 샘플과 간단한 벤치 마크를 사용하여 특정 유형의 응용 프로그램에 자바 프리미티브가 필요한 이유에 대한 사례를 만들 것입니다. 나는 또한 자바의 성능을 스칼라,씨++및 자바 스크립트와 비교할 것이다.

프리미티브 대 객체

이 기사를 읽고 있다면 이미 알고 있듯이 자바에는 일반적으로 프리미티브 유형 및 객체 유형이라고하는 이중 유형 시스템이 있으며 종종 단순히 프리미티브 및 객체로 축약됩니다. 이 자바에 미리 정의 된 여덟 원시적 인 유형이 있으며,그 이름은 예약 키워드입니다. 일반적으로 사용되는 예로는int,doubleboolean가 있습니다. 기본적으로 모든 사용자 정의 유형을 포함하여 자바의 다른 모든 유형은 객체 유형입니다. (배열 유형이 약간 하이브리드이기 때문에”본질적으로”라고 말하지만 원시 유형보다 객체 유형과 훨씬 더 비슷합니다. 예를 들어int의 경우Integer,double의 경우Double,boolean의 경우Boolean가 있습니다.

원시 유형은 값 기반이지만 객체 유형은 참조 기반이며 원시 유형의 힘과 논쟁의 원천이 모두 있습니다. 차이점을 설명하기 위해 아래의 두 선언을 고려하십시오. 첫 번째 선언은 기본 형식을 사용하고 두 번째 선언은 래퍼 클래스를 사용합니다.두 번째 선언을 간단히

Integer n2 = 100;

로 단축 할 수 있지만 기본 의미는 변경되지 않습니다. 오토박싱은 래퍼 클래스의 사용을 단순화하고 프로그래머가 작성해야 하는 코드의 양을 줄이지 만 런타임에 아무 것도 변경하지 않습니다.

프리미티브n1과 래퍼 객체n2의 차이는 그림 1 의 다이어그램에 의해 설명된다.

그림 1. 프리미티브 대 객체의 메모리 레이아웃

변수n1은 정수 값을 보유하지만 변수n2은 개체에 대한 참조를 포함하며 정수 값을 보유하는 개체입니다. 또한n2이 참조하는 개체에는Double클래스 개체에 대한 참조도 포함됩니다.

프리미티브의 문제점

내가 원시적 유형의 필요성을 여러분에게 확신시키기 전에,나는 많은 사람들이 나와 동의하지 않을 것임을 인정해야 한다. 셔먼 알퍼트”유해한 것으로 간주되는 원시 유형”에서 프리미티브는”절차 적 의미론을 균일 한 객체 지향 모델로 혼합하기 때문에 해롭다 고 주장합니다. 프리미티브는 퍼스트 클래스 객체가 아니지만 주로 퍼스트 클래스 객체를 포함하는 언어로 존재합니다.”프리미티브와 객체(래퍼 클래스 형태)는 논리적으로 유사한 유형을 처리하는 두 가지 방법을 제공하지만 기본 의미는 매우 다릅니다. 예를 들어,평등을 위해 두 인스턴스를 어떻게 비교해야합니까? 기본 형식의 경우==연산자를 사용하지만 개체의 경우 기본 형식에 대한 옵션이 아닌equals()메서드를 호출하는 것이 좋습니다. 마찬가지로 값을 할당하거나 매개 변수를 전달할 때 다른 의미가 있습니다. 예를 들어int의 경우0Integer의 경우null이 다릅니다.

이 문제에 대한 자세한 배경은 에릭 브루노의 블로그 게시물,”현대 원시 토론,”프리미티브의 장단점 중 일부를 요약 한 것입니다. 스택 오버플로에 대한 많은 논의는”왜 사람들은 여전히 자바에서 원시 유형을 사용합니까?”를 포함하여 프리미티브에 초점을 맞 춥니 다.”그리고”항상 프리미티브 대신 객체를 사용하는 이유가 있습니까?.”프로그래머 스택 교환은 자바에서 원시 대 클래스를 사용할 때”라는 제목의 유사한 토론을 호스팅합니까?”.

메모리 사용률

자바의double은 항상 메모리에서 64 비트를 차지하지만 참조의 크기는 자바 가상 머신에 따라 달라집니다. 내 컴퓨터는 64 비트 버전의 윈도우 7 과 64 비트를 실행하므로 내 컴퓨터의 참조가 64 비트를 차지합니다. 그림 1 의 다이어그램을 기반으로n1과 같은 단일double이 8 바이트(64 비트)를 차지할 것으로 예상하고n2과 같은 단일Double이 24 바이트를 차지할 것으로 예상합니다. 또한 자바는 추가 메모리를 사용하여 객체 유형에 대한 가비지 수집을 지원하지만 기본 유형은 지원하지 않습니다. 의 그것을 확인 할 수 있습니다.

“자바 원시 유형 대”에서 글렌 맥클러스키와 유사한 접근 방식을 사용합니다. 래퍼,”목록 1 에 표시된 방법은 엔-바이-엔 매트릭스(2 차원 배열)double.

목록 1. 유형 이중

의 메모리 사용률 계산 명백한 유형 변경(미도시)으로 목록 1 의 코드를 수정하면Double의 엔 바이 엔 행렬이 차지하는 바이트 수를 측정 할 수 있습니다. 1000 단위 행렬을 사용하여 컴퓨터에서이 두 가지 방법을 테스트 할 때 아래 표 1 에 표시된 결과를 얻습니다. 예시 된 바와 같이,원시 유형double의 버전은 매트릭스의 항목 당 8 바이트를 조금 넘는 것과 같습니다. 그러나 객체 유형Double의 버전은 행렬의 항목 당 28 바이트를 조금 넘어야합니다. 따라서,이 경우Double의 메모리 사용률은double의 메모리 사용률의 3 배 이상이며,이는 상기 도 1 에 도시된 메모리 레이아웃을 이해하는 사람에게는 놀랄 일이 아니다.

런타임 성능

프리미티브 및 객체의 런타임 성능을 비교하려면 수치 계산이 지배하는 알고리즘이 필요합니다. 이 기사에서는 행렬 곱셈을 선택했으며 두 개의 1000 대 1000 행렬을 곱하는 데 필요한 시간을 계산합니다. 아래 목록 2 와 같이 간단한 방식으로double에 대한 행렬 곱셈을 코딩했습니다. 행렬 곱셈을 구현하는 더 빠른 방법(아마도 동시성 사용)이있을 수 있지만 그 점은이 기사와 실제로 관련이 없습니다. 내가 필요로하는 것은 원시double을 사용하는 것과 래퍼 클래스Double을 사용하는 두 가지 유사한 방법의 공통 코드입니다. 유형Double의 두 행렬을 곱하는 코드는 명백한 유형 변경과 함께 목록 2 에서 정확히 같습니다.

목록 2. 두 가지 유형의 행렬을 두 번 곱하면

컴퓨터에서 두 개의 1000 대 1000 행렬을 여러 번 곱하는 두 가지 방법을 실행하고 결과를 측정했습니다. 평균 시간은 표 2 에 나와 있습니다. 따라서 이 경우double의 런타임 성능은Double의 런타임 성능보다 4 배 이상 빠릅니다. 그건 단순히 너무 많이 무시 하는 차이.

지금까지 필자는 프리미티브가 객체보다 훨씬 더 뛰어난 컴퓨팅 성능을 얻을 수 있음을 보여주기 위해 행렬 곱셈의 단순한 단일 벤치마크를 사용했습니다. 내 주장을 강화하기 위해 좀 더 과학적인 벤치 마크를 사용합니다. 이 라이브러리는 그러한 문제를 표준화된 프로그래밍 인터페이스를 제공함으로써 해결합니다. 이 벤치 마크의 소스 코드를 다운로드하고 프리미티브를 사용하는 원래 버전과 래퍼 클래스를 사용하는 두 번째 버전의 두 가지 버전을 만들었습니다. 두 번째 버전의 경우intInteger로 대체하고doubleDouble으로 대체하여 래퍼 클래스를 사용하는 전체 효과를 얻었습니다. 두 버전 모두 이 문서의 소스 코드에서 사용할 수 있습니다.1239>

다운로드

존 무어,주니어

시마크 벤치마크는 여러 계산 루틴의 성능을 측정하고,대략 복합 점수(초당 수백만 개의 부동 소수점 연산)를 보고한다. 따라서 더 큰 숫자가이 벤치 마크에 더 좋습니다. 표 3 은 내 컴퓨터에서이 벤치 마크의 각 버전의 여러 실행에서 평균 합성 점수를 제공합니다. 도시 된 바와 같이,초승달 모양 2.0 벤치 마크의 두 버전의 런타임 성능은 프리미티브를 가진 버전이 래퍼 클래스를 사용하는 버전보다 거의 5 배 빠르다는 점에서 위의 행렬 곱셈 결과와 일치했다.

당신은 자체 개발 한 벤치 마크와보다 과학적인 하나를 모두 사용하여 수치 계산을하는 자바 프로그램의 몇 가지 변형을 보았다. 그러나 자바는 다른 언어와 어떻게 비교됩니까? 자바의 성능이 스칼라,씨++및 자바 스크립트의 세 가지 다른 프로그래밍 언어와 어떻게 비교되는지 간단히 살펴 보겠습니다.

벤치마킹 스칼라

스칼라는 프로그래밍언어로서,이 언어들이 인기를 얻고 있는 것으로 보인다. 스칼라는 프리미티브와 객체를 구별하지 않는다는 것을 의미하는 통합 유형 시스템을 가지고 있습니다. 에 따르면 에릭 오샤 임 스칼라의 숫자 유형 클래스(태평양 표준시. 1)스칼라는 가능한 경우 기본 유형을 사용하지만 필요한 경우 객체를 사용합니다. 마찬가지로,스칼라의 배열에 대한 마틴 오 데르 스키의 설명은”… 스칼라 배열Array는 자바int,Array는 자바double로 표시됩니다…”

그래서 이것은 스칼라의 통합 유형 시스템이 자바의 기본 유형과 비교할 수있는 런타임 성능을 가질 것이라는 것을 의미합니까? 어디 보자.

나는 자바와 같이 스칼라에 능숙하지는 않지만 자바에서 스칼라로 직접 행렬 곱셈 벤치 마크에 대한 코드를 변환하려고 시도했다. 결과는 아래 목록 3 에 나와 있습니다. 내 컴퓨터에서 벤치 마크의 스칼라 버전을 실행했을 때 평균 12.30 초 였는데,이는 스칼라의 성능을 프리미티브와 자바의 성능에 매우 가깝게 만듭니다. 그 결과는 내가 예상했던 것보다 훨씬 좋으며 스칼라가 숫자 유형을 처리하는 방법에 대한 주장을 뒷받침합니다.

다운로드

존 무어 주니어

목록 3. 스칼라

에 두 개의 행렬을 곱하면 벤치마킹 씨++

씨++는 가상 머신이 아닌”베어 메탈”에서 직접 실행되기 때문에 자연스럽게 씨++가 자바보다 빠르게 실행될 것으로 기대합니다. 또한,자바 성능은 자바가 배열에 대한 액세스를 검사하여 각 인덱스가 배열에 대해 선언 된 범위 내에 있는지 확인한다는 사실에 의해 약간 감소합니다. 나는 기본 2 차원 배열을 다루는 데있어 자바보다 다소 어색하다는 것을 알았지 만,다행스럽게도 이러한 어색함의 대부분은 클래스의 사적인 부분 안에 숨어있을 수 있습니다. 에 대한 씨++,나는Matrix클래스의 간단한 버전을 만들었고 두 행렬을 곱하기 위해 연산자*를 오버로드했지만 기본 행렬 곱셈 알고리즘은 자바 버전에서 직접 변환되었습니다. 소스 코드는 목록 4 에 나와 있습니다.

다운로드

존 무어 주니어

목록 4. 응용 프로그램의 디버그 버전과 릴리스 버전을 모두 만들 수 있습니다. 나는 릴리스 버전을 여러 번 실행하고 결과를 평균화했다. 예상대로 씨++이 간단한 벤치 마크에서 눈에 띄게 빠르게 실행되어 내 컴퓨터에서 평균 7.58 초가되었습니다. 원시 성능이 프로그래밍 언어를 선택하는 주요 요소라면 숫자 집약적 인 응용 프로그램에서 선택할 수있는 언어입니다.

벤치마킹 자바 스크립트

좋아,이 사람은 나를 놀라게했다. 자바 스크립트가 매우 역동적 인 언어라는 것을 감안할 때,나는 그 성능이 래퍼 클래스가있는 자바보다 더 나빠질 것으로 예상했다. 그러나 사실,자바 스크립트의 성능은 프리미티브와 자바의 훨씬 더 가까이 있었다. 자바 스크립트를 테스트하기 위해 노드를 설치했습니다.매우 효율적인 것으로 명성을 얻은 자바 스크립트 엔진. 결과는 평균 15.91 초였습니다. 목록 5 는 내가 노드에서 실행 한 행렬 곱셈 벤치 마크의 자바 스크립트 버전을 보여줍니다.2015 년 11 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일,2015 년 12 월 1 일 자바 스크립트에 두 개의 행렬을 곱하기

결론적으로

자바가 약 18 년 전에 처음 현장에 도착했을 때,그것은 수치 계산에 의해 지배되는 응용 프로그램에 대한 성능 관점에서 최고의 언어가 아니었다. 그러나 시간이 지남에 따라,같은 저스트-인-타임(지트)컴파일(일명 적응 또는 동적 컴파일)등의 분야에서 기술 발전과 함께,이러한 종류의 응용 프로그램에 대한 자바의 성능은 이제 원시 유형이 사용되는 경우 네이티브 코드로 컴파일되는 언어의 그것과 비교된다.

또한 프리미티브는 가비지 수집의 필요성을 제거하여 객체 유형에 비해 프리미티브의 또 다른 성능 이점을 제공합니다. 표 4 는 내 컴퓨터의 행렬 곱셈 벤치 마크의 런타임 성능을 요약 한 것입니다. 이러한 유지 보수성,이식성 및 개발자 전문 지식과 같은 다른 요인은 많은 이러한 응용 프로그램에 대한 자바 더 나은 선택합니다.

앞서 논의한 바와 같이,오라클은 자바의 미래 버전에서 프리미티브의 제거를 진지하게 고려하고 있는 것으로 보인다. 자바 컴파일러가 프리미티브에 필적하는 성능을 가진 코드를 생성 할 수 없다면,나는 자바에서 자신의 제거 응용 프로그램의 특정 클래스에 대한 자바의 사용을 배제 것이라고 생각;즉,수치 계산에 의해 지배 그 응용 프로그램. 이 글에서 나는이 점을 주장 행렬 곱셈과 더 과학적인 벤치 마크,초승달 모양 2.0 을 기반으로 간단한 벤치 마크를 사용했다.

저자 소개

존 무어 주니어 시타델의 수학 및 컴퓨터 과학 교수는 객체 지향 기술,소프트웨어 엔지니어링 및 응용 수학 분야에서 특정 전문 지식을 갖춘 산업 및 학계에서 광범위한 경험을 보유하고 있습니다. 30 년 이상 동안 그는 관계형 데이터베이스와 여러 고차 언어를 사용하여 소프트웨어를 설계하고 개발했으며 버전 1.1 이후 자바에서 광범위하게 작업했습니다. 또한 그는 컴퓨터 과학의 고급 주제에 대한 수많은 학술 과정과 산업 세미나를 개발하고 가르쳤습니다.

추가 읽기

  1. 폴 크릴은”오라클은 장거리 자바 의도를 제시한다”(자바월드,2012 년 3 월)에서 오라클의 자바에 대한 장거리 계획에 대해 썼다. 이 기사는 관련 댓글 스레드와 함께 프리미티브에 대한 방어를 작성하도록 동기를 부여했습니다.
  2. 시몬 구즈는”자바의 프리미티브 및 객체 벤치 마크”(시모논 소프트웨어,2011 년 1 월)에서 기본 유형 및 래퍼 클래스를 벤치마킹 한 결과에 대해 씁니다.이 문서의 내용은 한국어,조선말,한국어뿐만 아니라 기타 여러 언어로 번역될 수 있습니다.
  3. 존 로즈,브라이언 괴츠,가이 스틸”값의 상태”에서 값 유형이라는 개념에 대해 토론합니다.OpenJDK.net2014 년 4 월). 값 유형은 객체와 프리미티브의 속성을 결합하여 정체성이없는 불변의 사용자 정의 집계 유형으로 생각할 수 있습니다. 값 유형에 대한 만트라는”클래스와 같은 코드,지능처럼 작동합니다.”

답글 남기기

이메일 주소는 공개되지 않습니다.