[java] Go가 자바에 비해 느린 이유는 무엇입니까?

2010 년 컴퓨터 언어 벤치 마크 게임 에서 볼 수 있듯이 :

  • Go는 C 보다 평균 10 배 느립니다.
  • Go는 Java 보다 3 배 느립니다 !?

Go 컴파일러가 실행을위한 네이티브 코드를 생성한다는 점을 염두에두고 어떻게 이럴 수 있습니까?
Go 용 미성숙 컴파일러? 아니면 Go 언어에 내재적 인 문제가 있습니까?

편집 :
대부분의 답변은 문제가 미성숙 한 컴파일러에 있다고 주장하면서 Go 언어의 본질적인 속도를 거부합니다.
따라서 피보나치 수를 계산하기위한 몇 가지 테스트 수행 했습니다 . 반복 알고리즘은 Go (freebsd, 6g) same에서 C (O3 옵션 사용)와 같은 속도로 실행됩니다. 지루한 재귀는 Go 2 times에서 C보다 느리게 실행됩니다 (-O3 옵션 사용, -O0 사용-동일). 하지만 벤치 마크 게임 에서처럼 10 배가 떨어지는 것을 보지 못했습니다.



답변

6g 및 8g 컴파일러는 특별히 최적화하지 않으므로 생성하는 코드가 특별히 빠르지 않습니다.

그들은 스스로 빠르게 실행되고 괜찮은 코드를 생성하도록 설계되었습니다 (약간의 최적화가 있습니다). gccgoGCC의 기존 최적화 패스를 사용하고 C와 더 의미있는 비교를 제공 할 수 있지만 gccgo는 아직 기능이 완전하지 않습니다.

벤치 마크 수치는 거의 전적으로 구현 품질에 관한 것입니다. 구현시 벤치 마크에서 실제로 필요하지 않은 언어 기능을 지원하는 데 런타임을 소비하는 경우를 제외하고는 언어와 관련이 많지 않습니다. 대부분의 컴파일 된 언어에서 충분히 영리한 컴파일러는 이론상 필요하지 않은 것을 제거 할 수 있지만, 해당 언어의 실제 사용자가 해당 기능을 사용하지 않는 프로그램을 작성하는 경우가 거의 없기 때문에 데모를 리깅해야하는 시점이 있습니다. . 그것들을 완전히 제거하지 않고 이동 (예 : JIT 컴파일 된 Java에서 가상 호출 목적지 예측)하기가 까다로워지기 시작합니다.

FWIW, 나는 (기본적으로, 정수 첨가 루프) 그것에 살펴 본다 된 이동 내 자신의 아주 사소한 테스트의 범위의 빠른 끝으로 gccgo 생산 코드 gcc -O0gcc -O2동등한 C. 이동에 대한이 느린 본질적으로하지 않습니다 그러나 컴파일러는 아직 모든 작업을 수행하지 않습니다. 10 분 전의 언어로는 놀라운 일이 아닙니다.


답변

Go FAQ 의 다음 릴리스에서는 다음 과 유사한 내용이 표시됩니다.

공연

Go가 벤치 마크 X에서 성능이 떨어지는 이유는 무엇입니까?

Go의 디자인 목표 중 하나는 비교 가능한 프로그램에 대해 C의 성능에 접근하는 것이지만 일부 벤치 마크에서는 테스트 / 벤치의 여러 가지를 포함하여 매우 열악합니다. 가장 느린 것은 Go에서 비교할 수있는 성능 버전을 사용할 수없는 라이브러리에 따라 다릅니다. 예를 들어, pidigits는 다 정밀도 수학 패키지에 의존하고, C 버전은 Go와 달리 GMP (최적화 된 어셈블러로 작성 됨)를 사용합니다. 정규식 (예 : regex-dna)에 의존하는 벤치 마크는 기본적으로 Go의 stopgap regexp 패키지를 PCRE와 같이 성숙하고 고도로 최적화 된 정규식 라이브러리와 비교합니다.

벤치 마크 게임은 광범위한 조정으로 승리하며 대부분의 벤치 마크의 Go 버전은주의가 필요합니다. 비교 가능한 C 및 Go 프로그램을 측정하면 (역 보완이 하나의 예임)이 제품군이 나타내는 것보다 두 언어가 원시 성능에서 훨씬 더 가깝다는 것을 알 수 있습니다.

그래도 개선의 여지가 있습니다. 컴파일러는 좋지만 더 나을 수 있고 많은 라이브러리가 주요 성능 작업이 필요하며 가비지 수집기는 아직 충분히 빠르지 않습니다 (그렇다고하더라도 불필요한 가비지를 생성하지 않도록주의하면 큰 효과가있을 수 있습니다).

그리고 여기 최근 메일 링리스트 스레드에서 컴퓨터 벤치 마크 게임대한 자세한 내용 있습니다.

gccgo의 가비지 수집 및 성능 (1)

gccgo의 가비지 수집 및 성능 (2)

컴퓨터 벤치 마크 게임은 단순한 게임이라는 점에 유의하는 것이 중요합니다. 성능 측정 및 용량 계획에 대한 경험이있는 사람들은 실제 및 실제 워크로드와 마찬가지로 신중하게 일치합니다. 그들은 게임을하지 않습니다.


답변

내 대답은 다른 모든 사람만큼 기술적이지는 않지만 여전히 관련이 있다고 생각합니다. Go 학습을 시작하기로 결정했을 때 Computer Benchmarks Game에서 동일한 벤치 마크를 보았습니다. 하지만 솔직히 이러한 모든 종합적인 벤치 마크는 Go가 당신에게 충분히 빠른지 결정하는 데 무의미하다고 생각합니다.

최근에 Tornado + TornadIO + ZMQ를 사용하여 Python으로 메시지 서버를 작성했으며 첫 Go 프로젝트에서 Go로 서버를 다시 작성하기로 결정했습니다. 지금까지 서버를 Python 버전과 동일한 기능으로 설정 한 결과, 테스트 결과 Go 프로그램에서 약 4.7 배 속도가 증가했습니다. 저는 Go로 1 주일 정도만 코딩했고 Python으로 5 년 넘게 코딩했습니다.

Go는 계속해서 작업할수록 더 빨라질 것입니다. 실제로는 작은 계산 벤치 마크가 아니라 실제 응용 프로그램에서 어떻게 수행되는지에 달려 있다고 생각합니다. 저에게 Go는 분명히 제가 Python으로 생성 할 수있는 것보다 더 효율적인 프로그램을 만들었습니다. 이것이이 질문에 대한 대답입니다.


답변

여러가지가 바뀌었다.

귀하의 질문에 대한 현재 정답은 진행 속도가 느리다는 개념에 이의를 제기하는 것입니다. 귀하의 문의 당시 귀하의 판단은 정당화되었지만 그 이후로 성능 측면에서 많은 근거를 얻었습니다. 지금은 여전히 ​​C만큼 빠르지는 않지만 일반적인 의미에서 10 배 정도 더 느린 곳은 아닙니다.

컴퓨터 언어 벤치 마크 게임

이 글을 쓰는 시점 :

source  secs    KB      gz      cpu     cpu load

reverse-complement
1.167x
Go      0.49    88,320  1278    0.84    30% 28% 98% 34%
C gcc   0.42    145,900 812     0.57    0% 26% 20% 100%

pidigits
1.21x
Go      2.10    8,084   603 2.10    0% 100% 1% 1%
C gcc   1.73    1,992   448 1.73    1% 100% 1% 0%

fasta
1.45x
Go      1.97    3,456   1344    5.76    76% 71% 74% 73%
C gcc   1.36    2,800   1993    5.26    96% 97% 100% 97%

regex-dna
1.64x
Go      3.89    369,380 1229    8.29    43% 53% 61% 82%
C gcc   2.43    339,000 2579    5.68    46% 70% 51% 72%

fannkuch-redux
1.72x
Go      15.59   952 900 62.08   100% 100% 100% 100%
C gcc   9.07    1,576   910 35.43   100% 99% 98% 94%

spectral-norm
2x
Go      3.96    2,412   548 15.73   99% 99% 100% 99%
C gcc   1.98    1,776   1139    7.87    99% 99% 100% 99%

n-body
2.27x
Go      21.73   952 1310    21.73   0% 100% 1% 2%
C gcc   9.56    1,000   1490    9.56    1% 100% 1% 1%

k-nucleotide
2.40x
Go      15.48   149,276 1582    54.68   88% 97% 90% 79%
C gcc   6.46    130,076 1500    17.06   51% 37% 89% 88%

mandelbrot
3.19x
Go      5.68    30,756  894 22.56   100% 100% 99% 99%
C gcc   1.78    29,792  911 7.03    100% 99% 99% 98%

그러나 이진 트리 벤치 마크에서는 잔인하게 고통받습니다.

binary-trees
12.16x
Go      39.88   361,208 688 152.12  96% 95% 96% 96%
C gcc   3.28    156,780 906 10.12   91% 77% 59% 83%


답변

CPU 사이클 사용에 대한 Go의 효율성은 좋지 않지만 Go 동시성 모델은 예를 들어 Java의 스레드 모델보다 훨씬 빠르며 C ++ 스레드 모델과 비교할 수 있습니다.

에 있습니다 스레드 링 벤치 마크 , 이동했다 16 배 빠른 자바보다. 동일한 시나리오에서 Go CSP는 C ++와 거의 비슷했지만 메모리를 4 배 더 적게 사용했습니다.

Go 언어의 가장 큰 힘은 70 년대에 Tony Hoare가 지정한 동시성 모델 인 Communicating Sequential Processes, CSP로, 구현이 간단하고 동시 요구 사항에 적합합니다.


답변

Java가 Go 및 C ++보다 빠르며 대부분의 경우 C보다 빠를 수있는 두 가지 기본 이유가 있습니다.

1) JIT 컴파일러. 런타임 프로필을 기반으로 OO 클래스에서도 여러 수준을 통해 가상 함수 호출을 인라인 할 수 있습니다. 이것은 정적으로 컴파일 된 언어에서는 불가능합니다 (기록 된 프로필을 기반으로 한 최신 재 컴파일이 도움이 될 수 있음). 이것은 반복적 인 알고리즘을 포함하는 대부분의 벤치 마크에서 매우 중요합니다.

2) GC. GC 기반 메모리 할당은 malloc에 ​​비해 거의 무료입니다. 그리고 ‘무료’페널티는 전체 런타임에 걸쳐 상각 될 수 있습니다. 모든 가비지가 수집되기 전에 프로그램이 종료되기 때문에 종종 건너 뜁니다.

GC / JVM을 효율적으로 만드는 매우 재능있는 개발자가 수백 명 (수천?) 있습니다. “모든 것보다 더 잘 코딩”할 수 있다고 생각하는 것은 어리석은 일입니다. 그것은 인간의 자아 문제입니다. 인간은 재능있는 인간의 적절한 훈련을 받으면 컴퓨터가 그것을 프로그래밍 한 인간보다 더 잘 수행 될 것이라는 사실을 받아들이 기가 어렵습니다.

Btw, C ++는 OO 기능을 사용하지 않으면 C만큼 빠를 수 있지만 처음에는 C로 프로그래밍하는 데 매우 가깝습니다.

가장 중요한 것은 이러한 테스트의 “속도 차이”가 일반적으로 의미가 없다는 것입니다. IO 비용은 성능 차이보다 훨씬 더 많으므로 IO 비용을 최소화하는 적절한 설계는 통역 언어에서도 항상 승리합니다. CPU 바운드 시스템은 거의 없습니다.

마지막으로, 사람들은 “컴퓨터 언어 벤치 마크 게임”을 “과학적 측정”이라고합니다. 예를 들어 nbody에 대한 Java 테스트를 보면 테스트에 완전히 결함이 있습니다. 동일한 OS / 하드웨어에서 테스트를 실행하면 Java의 경우 약 7.6 초, C의 경우 4.7 초가 소요됩니다. 이는 합리적입니다. 테스트가보고하는 속도의 4 배가 아닙니다. 사이트 트래픽을 생성하도록 설계된 클릭 미끼, 가짜 뉴스입니다.

마지막으로 마지막 메모로 … Go를 사용하여 테스트를 실행했는데 7.9 초였습니다. Go를 클릭하면 Java와 비교하고 Java를 클릭하면 C와 비교한다는 사실은 진지한 엔지니어에게 위험 신호가되어야합니다.

Java, Go 및 C ++의 실제 비교를 보려면 https://www.biorxiv.org/content/10.1101/558056v1 스포일러 경고를 참조 하십시오 . Java는 원시 성능에서 1 위를 차지하고 Go는 결합 된 메모리 사용으로 상위에 올랐습니다. 그리고 벽 시간.


답변

자주 간과되는 사실은 JIT 컴파일이 특히 (런타임) 후기 바인딩 된 함수 또는 메서드에 대해 정적 컴파일이 될 수 있다는 것입니다. 핫스팟 JIT는 RUNTIME에 인라인 할 메소드를 결정하며 현재 실행중인 CPU의 캐시 크기 / 아키텍처에 맞게 데이터 레이아웃을 조정할 수도 있습니다. 일반적으로 C / C ++는 하드웨어에 직접 액세스하여 보완 할 수 있습니다 (전체적으로 더 나은 성능을 발휘 함). Go의 경우 C에 비해 더 높은 수준으로 보일 수 있지만 현재 런타임 최적화 시스템 / 컴파일러가 없습니다. 내 직감은 Go가 포인터 추적을 그다지 강요하지 않고 더 나은 데이터 구조 지역성을 장려하기 때문에 Java보다 더 빠를 수 있다고 말합니다 .