C ++ 성능 vs. Java / C #


119

내 이해는 C / C ++가 특정 기계 아키텍처에서 실행되는 네이티브 코드를 생성한다는 것입니다. 반대로 Java 및 C #과 같은 언어는 네이티브 아키텍처를 추상화하는 가상 머신 위에서 실행됩니다. 논리적으로이 중간 단계 때문에 Java 또는 C #이 C ++의 속도와 일치하는 것이 불가능 해 보이지만 최신 컴파일러 ( "핫스팟")가이 속도를 달성하거나 초과 할 수 있다고 들었습니다.

아마도 이것은 언어 질문보다 컴파일러 질문에 가깝지만, 누구나 이러한 가상 머신 언어 중 하나가 모국어보다 더 나은 성능을 발휘할 수있는 방법을 일반 영어로 설명 할 수 있습니까?


Java 및 C #은 런타임에 제공되는 코드를 사용하여 애플리케이션이 실제로 실행되는 방식을 기반으로 최적화 할 수 있습니다. 예를 들어, 프로그램이 실행되는 동안 실제로 변경 될 수 있고 여전히 올바른 공유 라이브러리의 코드를 인라인 할 수 있습니다.
Peter Lawrey

이 답변에서 매우 색다른 이론을 읽기 전에 확인해야 할 몇 가지 실제 측정 : shootout.alioth.debian.org/u32/…
Justicle

답변:


178

일반적으로 C # 및 Java는 JIT 컴파일러 (처음 실행될 때 IL을 컴파일하는 컴파일러)가 시스템을 쿼리 할 수 ​​있기 때문에 C ++ 컴파일 된 프로그램이 할 수없는 최적화를 수행 할 수 있기 때문에 빠르거나 빠를 수 있습니다. 시스템이 Intel 또는 AMD인지 확인할 수 있습니다. Pentium 4, Core Solo 또는 Core Duo; 또는 SSE4 등을 지원하는 경우

C ++ 프로그램은 일반적으로 혼합 최적화를 사용하여 미리 컴파일해야합니다. 그래야 모든 컴퓨터에서 제대로 실행되지만 단일 구성 (예 : 프로세서, 명령어 세트, 기타 하드웨어)에 대해 최적화되지는 않습니다.

또한 특정 언어 기능을 통해 C # 및 Java의 컴파일러는 C / C ++ 컴파일러가 수행하기에 안전하지 않은 특정 부분을 최적화 할 수 있도록 코드에 대한 가정을 할 수 있습니다. 포인터에 액세스 할 수있는 경우 안전하지 않은 최적화가 많이 있습니다.

또한 Java와 C #은 가비지 수집기와 코드 간의 추상화 계층을 통해 모든 힙 압축을 한 번에 수행 할 수 있기 때문에 C ++보다 더 효율적으로 힙 할당을 수행 할 수 있습니다 (상당히 비용이 많이 드는 작업).

이제이 다음 요점에서 Java에 대해 말할 수는 없지만 예를 들어 C #은 메서드 본문이 비어 있음을 알 때 실제로 메서드와 메서드 호출을 제거한다는 것을 알고 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다.

보시다시피 특정 C # 또는 Java 구현이 더 빨라지는 데에는 많은 이유가 있습니다.

이제는 C ++로 특정 최적화를 수행 할 수 있으므로 C #으로 할 수있는 모든 작업, 특히 그래픽 영역에서 그리고 하드웨어에 가까울 때마다 할 수 있습니다. 포인터는 여기서 놀라운 일을합니다.

그래서 당신이 쓰는 것에 따라 나는 둘 중 하나와 함께 갈 것입니다. 그러나 하드웨어에 의존하지 않는 무언가 (드라이버, 비디오 게임 등)를 작성하는 경우 C #의 성능에 대해 걱정하지 않을 것입니다 (다시 Java에 대해서는 말할 수 없음). 잘 될 것입니다.

하나의 Java 측 @Swati 는 좋은 기사를 지적합니다.

https://www.ibm.com/developerworks/library/j-jtp09275


귀하의 추론은 가짜입니다. C ++ 프로그램은 대상 아키텍처에 맞게 빌드되므로 런타임에 전환 할 필요가 없습니다.
Justicle

3
@Justicle 다양한 아키텍처에 대해 C ++ 컴파일러가 제공 할 수있는 최선의 방법은 일반적으로 x86, x64, ARM 등입니다. 이제 특정 기능 (예 : SSE2)을 사용하도록 지시 할 수 있으며 운이 좋으면 해당 기능을 사용할 수없는 경우 일부 백업 코드를 생성 할 수도 있지만 이는 얻을 수있는만큼 세분화되어 있습니다. 캐시 크기 및 기타 사항에 따라 확실히 전문화되지 않습니다.
Voo

4
이 이론 일어나지 않는 예는 shootout.alioth.debian.org/u32/… 를 참조하십시오 .
Justicle 2011-09-18

1
솔직히 이것은 최악의 답변 중 하나입니다. 근거가 너무 없어서 뒤집을 수 있습니다. 너무 많은 일반화, 너무 많은 무지 (빈 함수를 최적화하는 것은 실제로 빙산의 일각에 불과합니다). 고급 C ++ 컴파일러에는 시간이 있습니다. 또 다른 사치 : 검사가 시행되지 않습니다. 그러나 stackoverflow.com/questions/145110/c-performance-vs-java-c/… 에서 더 많은 것을 찾으십시오 .
Sebastian Mach

1
@OrionAdrian ok 우리는 이제 완전한 원입니다 ... 이 이론이 일어나지 않는 예를 보려면 shootout.alioth.debian.org/u32/ 를 참조하십시오 . 즉, 모호한 추측을하기 전에 당신의 이론이 옳다 는 것을 증명할 수 있음을 보여주십시오 .
Justicle

197

JIT 대 정적 컴파일러

이전 게시물에서 이미 언급했듯이 JIT는 런타임에 IL / 바이트 코드를 네이티브 코드로 컴파일 할 수 있습니다. 그 비용은 언급되었지만 결론은 아닙니다.

JIT에는 모든 것을 컴파일 할 수 없다는 큰 문제가 있습니다. JIT 컴파일에는 시간이 걸리므로 JIT는 코드의 일부만 컴파일하는 반면 정적 컴파일러는 완전한 네이티브 바이너리를 생성합니다. 어떤 종류의 프로그램에서는 정적 컴파일러는 JIT를 쉽게 능가합니다.

물론 C # (또는 Java 또는 VB)은 일반적으로 C ++보다 실행 가능하고 강력한 솔루션을 생성하는 데 더 빠릅니다 (C ++에 복잡한 의미 체계가 있고 C ++ 표준 라이브러리는 흥미롭고 강력하지만 전체와 비교할 때 상당히 열악한 경우) .NET 또는 Java의 표준 라이브러리 범위), 따라서 일반적으로 C ++와 .NET 또는 Java JIT의 차이점은 대부분의 사용자에게 표시되지 않으며 중요한 바이너리의 경우 C ++ 처리를 호출 할 수 있습니다. C # 또는 Java에서 (이러한 종류의 기본 호출 자체에 비용이 많이들 수 있음에도 불구하고) ...

C ++ 메타 프로그래밍

일반적으로 C ++ 런타임 코드를 C # 또는 Java의 해당 코드와 비교합니다. 그러나 C ++에는 기본적으로 Java / C #을 능가 할 수있는 한 가지 기능이 있습니다. 즉, 템플릿 메타 프로그래밍입니다. 코드 처리는 컴파일 시간에 수행되므로 (따라서 컴파일 시간이 크게 증가하여) 런타임이 0 (또는 거의 0)이됩니다.

나는 아직 이것에 대한 실제 효과를 보았지만 (나는 개념으로 만 연주했지만 그 당시 차이는 JIT의 실행 시간, C ++의 경우 0 이었습니다), 사실 템플릿 메타 프로그래밍과 함께 이것은 언급 할 가치가 있습니다. 하찮은...

편집 2011-06-10 : C ++에서 유형을 가지고 노는 것은 컴파일 타임에 수행됩니다. 즉, 비 제네릭 코드를 호출하는 제네릭 코드를 생성합니다 (예 : 문자열에서 유형 T로 일반 파서, 인식하는 유형 T에 대한 표준 라이브러리 API 호출, 사용자가 파서를 쉽게 확장 할 수 있도록하는 것은 매우 쉽고 효율적입니다. 반면 Java 또는 C #의 동등한 것은 작성하기가 힘들고 컴파일 시간에 유형이 알려진 경우에도 런타임에 항상 느리고 해결됩니다. 당신의 유일한 희망 은 JIT가 모든 것을 인라인하는 것입니다.

...

2011-09-20 편집 : Blitz ++ ( Homepage , Wikipedia ) 팀 은 그렇게했으며, 분명히 그들의 목표는 C ++ 템플릿 메타 프로그래밍을 통해 런타임 실행에서 컴파일 시간으로 가능한 한 많이 이동하여 과학적 계산에 대한 FORTRAN의 성능에 도달하는 것입니다. . 은 "그래서 나는 아직 너무이를 실생활 효과를 볼 수 있습니다 제가 위에서 쓴 부분"분명히 않는 현실에 존재합니다.

네이티브 C ++ 메모리 사용량

C ++는 Java / C #과 메모리 사용량이 다르므로 장점 / 결함이 다릅니다.

JIT 최적화에 관계없이 메모리에 대한 직접 포인터 액세스만큼 빠른 것은 없습니다 (프로세서 캐시 등을 잠시 무시하겠습니다). 따라서 메모리에 연속적인 데이터가있는 경우 C ++ 포인터 (예 : C 포인터 ... Caesar에 만료 됨)를 통해 데이터에 액세스하면 Java / C #보다 시간이 더 빠릅니다. 그리고 C ++에는 RAII가있어 C # 또는 Java에서보다 훨씬 쉽게 처리 할 수 ​​있습니다. C ++는 using개체의 존재 범위를 지정할 필요가 없습니다 . 그리고 C ++에는 finally절이 없습니다 . 이것은 오류가 아닙니다.

:-)

그리고 C # 프리미티브와 같은 구조체에도 불구하고 C ++ "스택상의"객체는 할당 및 소멸시 비용이 전혀 들지 않으며, 정리를 위해 독립 스레드에서 작동하는 데 GC가 필요하지 않습니다.

메모리 조각화와 관련하여 2008 년의 메모리 할당자는 일반적으로 GC와 비교되는 1980 년의 오래된 메모리 할당자가 아닙니다. C ++ 할당은 메모리에서 이동할 수 없습니다. 사실이지만 Linux 파일 시스템에서와 같이 : 누가 하드 디스크가 필요합니까? 조각화가 발생하지 않을 때 조각 모음? 올바른 작업에 올바른 할당자를 사용하는 것은 C ++ 개발자 툴킷의 일부 여야합니다. 이제 할당자를 작성하는 것은 쉽지 않습니다. 우리 대부분은 더 나은 일을 할 수 있으며, 대부분의 경우 RAII 또는 GC는 충분합니다.

2011-10-04 편집 : 효율적인 할당 자에 대한 예 : Windows 플랫폼에서는 Vista 이후로 낮은 조각화 힙 이 기본적으로 활성화됩니다. 이전 버전의 경우 WinAPI 함수 HeapSetInformation ) 을 호출하여 LFH를 활성화 할 수 있습니다 . 다른 OS에서는 대체 할당자가 제공됩니다 (목록은 https://secure.wikimedia.org/wikipedia/en/wiki/Malloc )

이제 메모리 모델은 멀티 코어 및 멀티 스레딩 기술의 부상으로 다소 복잡해지고 있습니다. 이 분야에서 나는 .NET이 이점을 가지고 있다고 생각하고 Java가 우위를 차지했다고 들었습니다. 일부 "베어 메탈"해커는 자신의 "머신 근처"코드를 칭찬하기 쉽습니다. 그러나 이제는 컴파일러가 작업을 수행하도록하는 것보다 손으로 더 나은 어셈블리를 생성하는 것이 훨씬 더 어렵습니다. C ++의 경우 컴파일러는 일반적으로 10 년 이후 해커보다 나아졌습니다. C # 및 Java의 경우이 작업이 훨씬 더 쉽습니다.

그럼에도 불구하고 새로운 표준 C ++ 0x는 C ++ 컴파일러에 간단한 메모리 모델을 적용하여 C ++의 효과적인 다중 처리 / 병렬 / 스레딩 코드를 표준화 (따라서 단순화)하고 컴파일러에 대한 최적화를 더 쉽고 안전하게 만듭니다. 그러나 우리는 그 약속이 진실인지 몇 년 후에 보게 될 것입니다.

C ++ / CLI 대 C # / VB.NET

참고 :이 섹션에서는 C ++ / CLI, 즉 네이티브 C ++가 아닌 .NET에서 호스팅하는 C ++에 대해 설명합니다.

지난주에 .NET 최적화에 대한 교육을 받았으며 어쨌든 정적 컴파일러가 매우 중요하다는 것을 발견했습니다. JIT보다 중요합니다.

C ++ / CLI (또는 그 조상 인 Managed C ++)로 컴파일 된 동일한 코드는 C # (또는 컴파일러가 C #과 동일한 IL을 생성하는 VB.NET)에서 생성 된 동일한 코드보다 훨씬 빠를 수 있습니다.

C ++ 정적 컴파일러가 C #보다 이미 최적화 된 코드를 생성하는 것이 훨씬 낫기 때문입니다.

예를 들어, .NET의 함수 인라인은 바이트 코드 길이가 32 바이트 이하인 함수로 제한됩니다. 따라서 C #의 일부 코드는 40 바이트 접근자를 생성하며, 이는 JIT에 의해 인라인되지 않습니다. C ++ / CLI의 동일한 코드는 JIT에 의해 인라인되는 20 바이트 접근자를 생성합니다.

또 다른 예는 C # 컴파일러에 의해 생성 된 IL에서 여전히 언급되는 동안 C ++ 컴파일러에 의해 단순히 컴파일되는 임시 변수입니다. C ++ 정적 컴파일 최적화는 더 적은 코드를 생성하므로 더 적극적인 JIT 최적화를 다시 승인합니다.

그 이유는 C ++ / CLI 컴파일러가 C ++ 네이티브 컴파일러의 방대한 최적화 기술로부터 이익을 얻었 기 때문으로 추측되었습니다.

결론

저는 C ++을 좋아합니다.

그러나 내가 보는 한, C # 또는 Java가 모두 더 나은 선택입니다. C ++보다 빠르기 때문이 아니라 품질을 더하면 생산성이 높아지고 교육이 덜 필요하며 C ++보다 완전한 표준 라이브러리를 갖게되기 때문입니다. 그리고 대부분의 프로그램의 경우 속도 차이 (어떤면에서든)는 무시할 수있을 것입니다.

편집 (2011-06-06)

C # /. NET에 대한 나의 경험

저는 이제 거의 독점적 인 전문 C # 코딩을 5 개월 동안 받았습니다 (이미 C ++ 및 Java로 가득 찬 CV와 C ++ / CLI 터치에 추가됨).

나는 WinForms (Ahem ...)와 WCF (멋지다!), WPF (Cool !!!! 둘 다 XAML과 raw C #를 통해 놀았다. WPF는 스윙이 그것과 비교할 수 없다고 생각한다), C # 4.0으로 놀았다.

결론은 C ++보다 C # / Java에서 작동하는 코드를 생성하는 것이 더 쉽고 빠르지 만 C ++보다 C #에서 강력하고 안전하며 강력한 코드를 생성하는 것이 훨씬 더 어렵습니다 (자바에서는 더 어렵습니다). 이유는 많지만 다음과 같이 요약 할 수 있습니다.

  1. 제네릭 템플릿만큼 강력하지 않은 ( T로 문자열에서 효율적인 일반적인 구문 분석 방법을 (작성하려고), 또는 부스트의 효율적인 동등한 :: lexical_cast C #에서 문제를 이해하기 )
  2. RAII는 타의 추종을 불허합니다 ( GC는 여전히 누수 될 수 있으며 (예, 해당 문제를 처리해야했습니다). 메모리 만 처리합니다. C #조차도 using올바른 Dispose 구현을 작성하는 것이 어렵 기 때문에 쉽고 강력하지 않습니다. )
  3. C # readonly및 Java는 final유용으로 아무데도 C ++의const ( 가 내장 된 C ++의 기능입니다. 불변의 데이터가 흥미로운 솔루션입니다 중에도 엄청난 작업없이 C #에서 읽기 전용 복잡한 데이터 예를 들어 노드의 (나무를) 노출 할 수있는 방법은 없습니다 ,하지만 모든 것을 불변으로 만들 수있는 것은 아니기 때문에 충분하지 않습니다 .

따라서 C #은 작동하는 것을 원하는 한 유쾌한 언어로 남아 있지만 항상 안전하게 작동 하는 것을 원하는 순간에는 실망스러운 언어 입니다.

Java는 C #과 동일한 문제를 가지고 있기 때문에 훨씬 더 실망 스럽습니다. C #의 using키워드에 상응하는 기능이 부족한 저의 매우 숙련 된 동료는 리소스가 올바르게 해제되었는지 확인하는 데 너무 많은 시간을 소비했지만 C ++에서는 (소멸자와 스마트 포인터 사용) 쉬웠습니다.

그래서 저는 C # / Java의 생산성 향상이 대부분의 코드에서 볼 수 있다고 생각합니다. 코드가 최대한 완벽해야하는 날까지. 그날, 당신은 고통을 알게 될 것입니다. (서버와 GUI 앱에서 요청한 내용을 믿지 못할 것입니다 ...).

서버 측 Java 및 C ++ 정보

건물 반대편에있는 서버 팀 (GUI 팀으로 돌아 가기 전에 2 년 동안 일했습니다)과 계속 연락했고 흥미로운 것을 배웠습니다.

지난 몇 년 동안 Java에는 많은 프레임 워크 / 도구가 있고 유지 관리, 배포 등이 쉽기 때문에 Java 서버 앱이 이전 C ++ 서버 앱을 대체하도록하는 경향이있었습니다.

... 저 지연 문제가 지난 몇 달 동안 추악한 머리를 떨칠 때까지. 그런 다음 Java 서버 앱은 숙련 된 Java 팀이 시도한 최적화에 관계없이 실제로 최적화되지 않은 C ++ 서버와의 경쟁에서 간단하고 깔끔하게 패했습니다.

현재 결정은 성능이 여전히 중요하면서도 지연 시간이 짧은 대상에 관심이없는 일반적인 사용을 위해 Java 서버를 유지하고 지연 시간이 짧고 지연 시간이 매우 짧은 요구 사항을 위해 이미 더 빠른 C ++ 서버 애플리케이션을 적극적으로 최적화하는 것입니다.

결론

예상만큼 간단한 것은 없습니다.

Java 및 훨씬 더 많은 C #은 광범위한 표준 라이브러리와 프레임 워크를 갖춘 멋진 언어로, 빠르게 코딩 할 수 있고 곧 결과를 얻을 수 있습니다.

그러나 원시 성능, 강력하고 체계적인 최적화, 강력한 컴파일러 지원, 강력한 언어 기능 및 절대적인 안전성이 필요한 경우 Java 및 C #을 사용하면 경쟁에서 우위를 유지하는 데 필요한 마지막 누락되었지만 중요한 품질 비율을 얻기가 어렵습니다.

평균 품질의 코드를 생성하는 데 C ++보다 C # / Java에서 경험이 적은 개발자와 시간이 덜 필요한 것처럼 보이지만, 반면에 완벽하고 우수한 품질의 코드가 필요한 순간 ​​갑자기 결과를 얻는 것이 더 쉽고 빨라졌습니다. 바로 C ++에서.

물론 이것은 우리의 특정 요구에 국한된 내 자신의 인식입니다.

그러나 여전히 GUI 팀과 서버 측 팀 모두에서 오늘날 일어나는 일입니다.

물론 새로운 일이 생기면이 게시물을 업데이트하겠습니다.

편집 (2011-06-22)

"성능과 관련하여 C ++가 큰 차이를 보였습니다. 그러나 가장 광범위한 튜닝 작업이 필요했습니다.이 중 대부분은 일반 프로그래머가 사용할 수없는 정교함 수준에서 수행되었습니다.

[...] Java 버전은 아마도 구현하기 가장 간단했지만 성능 분석이 가장 어려웠습니다. 특히 가비지 수집과 관련된 효과는 복잡하고 조정하기가 매우 어려웠습니다. "

출처 :

편집 (2011-09-20)

"페이스 북에서는 ' 합리적으로 작성된 C ++ 코드가 빠르게 실행됩니다. '라는 말은 PHP 및 Java 코드를 최적화하는 데 막대한 노력을 기울 였다는 점 을 강조합니다. 역설적으로 C ++ 코드는 다른 언어보다 작성하기가 더 어렵지만 효율적인 코드는 [다른 언어보다 C ++로 작성하기가 훨씬 쉽습니다]. "

- 허브 셔터는// 빌드 / , 인용 안드레이 Alexandrescu의를

출처 :


8
C # 5 개월 후에 편집하면 내 경험이 정확히 설명됩니다 (템플릿 더 나은, const 더 나은, RAII). +1. 이 세 가지는 C ++ (또는 아직 시간이 없었던 D)에 대한 나의 개인적인 킬러 기능으로 남아 있습니다.
Sebastian Mach

"코드 처리는 컴파일 시간에 수행됩니다". 따라서 템플릿 메타 프로그래밍은 프로그램에서만 작동하며 컴파일 타임에는 사용할 수없는 경우가 많습니다. 예를 들어, 런타임 코드 생성이 불가능하기 때문에 바닐라 C ++에서 경쟁력있는 정규 표현식 라이브러리를 작성하는 것이 불가능합니다. 메타 프로그래밍).
JD

"타입을 가지고 노는 것은 컴파일 시간에 수행됩니다. Java 또는 C #의 동등한 기능은 작성하기가 힘들며 컴파일 시간에 유형이 알려진 경우에도 런타임에 항상 느리고 해결됩니다." C #에서는 참조 형식에만 해당되며 값 형식에는 해당되지 않습니다.
JD

1
"JIT 최적화에 관계없이 메모리에 대한 직접 포인터 액세스만큼 빠른 것은 없습니다. 메모리에 연속 데이터가있는 경우 C ++ 포인터 (예 : C 포인터 ... Caesar에게 기한을 부여하겠습니다)를 통해 데이터에 액세스하면 시간이 걸립니다. Java / C #보다 빠릅니다. " 사람들은 포인터가 앨리어싱 관련 최적화를 방해하기 때문에 SciMark2 벤치 마크의 SOR 테스트에서 Java가 C ++를 능가하는 것을 관찰했습니다. blogs.oracle.com/dagastine/entry/sun_java_is_faster_than
JD

또한 .NET은 링크 후 동적으로 링크 된 라이브러리에서 제네릭의 유형 특수화를 수행하는 반면 C ++는 링크하기 전에 템플릿을 확인해야하기 때문에 불가능합니다. 제네릭이 템플릿에 비해 갖는 가장 큰 장점은 이해할 수있는 오류 메시지입니다.
JD

48

관리 성능과 관리되지 않는 성능에 대해 이야기 할 때마다 Rico (및 Raymond)가 중국어 / 영어 사전의 C ++ 및 C # 버전을 비교 한 시리즈를 언급하고 싶습니다. 이 Google 검색 을 통해 직접 읽을 수 있지만 Rico의 요약이 마음에 듭니다.

그래서 나는 내 압도적 인 패배에 부끄럽습니까? 거의. 관리 코드는 거의 모든 노력으로 매우 좋은 결과를 얻었습니다. 관리되는 Raymond를 물 리치려면 다음을 수행해야합니다.

  • 자신의 파일 I / O 작성
  • 자신의 문자열 클래스 작성
  • 자신의 할당 자 작성
  • 자신의 국제 매핑 작성

물론 그는이 작업을 위해 사용 가능한 하위 수준 라이브러리를 사용했지만 여전히 많은 작업입니다. 남은 STL 프로그램을 부를 수 있습니까? 나는 그렇게 생각하지 않는다. 나는 그가 std :: vector 클래스를 유지했는데 궁극적으로 문제가되지 않았고 find 함수를 유지했다고 생각한다. 거의 모든 것이 사라졌습니다.

그래서, 당신은 확실히 CLR을 이길 수 있습니다. Raymond는 그의 프로그램을 더 빠르게 만들 수 있다고 생각합니다.

흥미롭게도 두 프로그램 내부 타이머가보고 한 파일을 구문 분석하는 데 걸리는 시간은 거의 같습니다 (각각에 대해 30ms). 차이점은 오버 헤드에 있습니다.

저에게 결론은 관리되지 않는 버전이 원래의 관리되지 않는 코드의 단순 포트였던 관리되는 버전을 능가하기 위해 6 개의 수정이 필요하다는 것입니다. 모든 마지막 성능이 필요하고 (그리고이를 얻을 수있는 시간과 전문 지식이있는 경우) 관리되지 않는 상태로 이동해야하지만 저에게는 33보다 첫 번째 버전에서 내가 가진 엄청난 이점을 취할 것입니다. % 6 회 시도하면 얻는다.


3
링크가 죽었습니다. 여기에서 언급 된 기사를 찾았습니다. blogs.msdn.com/b/ricom/archive/2005/05/10/416151.aspx
gjvdkamp 2011 년

우선 Raymond Chen의 코드를 보면 그는 분명히 C ++ 나 데이터 구조를 잘 이해하지 못합니다. 그의 코드는 C 코드가 성능상의 이점이없는 경우에도 저수준 C 코드에 거의 도달합니다 (일종의 불신과 프로파일 러 사용 방법에 대한 지식이 부족한 것 같습니다). 그는 또한 사전을 구현하는 가장 알고리즘 적으로 건전한 방법을 이해하지 못했습니다 (그는 그리스도를 위해 std :: find를 사용했습니다). Java, Python, C # 등에 대해 좋은 점이 있다면-모두 매우 효율적인 사전을 제공합니다 ...
stinky472

시도 또는 std :: map은 C ++ 또는 해시 테이블에 훨씬 유리합니다. 마지막으로 사전은 고수준 라이브러리 및 프레임 워크에서 가장 많은 이점을 얻는 프로그램 유형입니다. 관련된 라이브러리만큼 언어의 차이를 보여주지는 않습니다 (C #이 훨씬 더 완전하고 작업에 적합한 훨씬 더 많은 도구를 제공한다고 기꺼이 말할 것입니다). 대규모 행렬 / 벡터 코드와 같이 비교하여 큰 메모리 블록을 조작하는 프로그램을 보여줍니다. 이 경우와 같이 코더가 무엇을 모르
더라도이

26

특정 CPU 최적화를위한 컴파일은 일반적으로 과대 평가됩니다. C ++로 된 프로그램을 가져 와서 pentium PRO에 대한 최적화를 사용하여 컴파일하고 펜티엄 4에서 실행하십시오. 그런 다음 pentium 4에 대한 최적화를 사용하여 다시 컴파일하십시오. 나는 여러 프로그램을 사용하여 긴 오후를 보냈습니다. 일반적인 결과 ?? 일반적으로 2-3 % 미만의 성능 향상. 따라서 이론적 인 JIT 이점은 거의 없습니다. 대부분의 성능 차이는 스칼라 데이터 처리 기능을 사용할 때만 관찰 할 수 있으며, 어쨌든 최대 성능을 달성하려면 결국 수동 미세 조정이 필요합니다. 이러한 종류의 최적화는 수행하는 데 느리고 비용이 많이 들기 때문에 때때로 JIT에 적합하지 않습니다.

실제 및 실제 응용 프로그램에서 C ++는 일반적으로 Java보다 빠릅니다. 주로 더 나은 캐시 성능을 제공하는 더 가벼운 메모리 풋 프린트 때문입니다.

그러나 모든 C ++ 기능을 사용하려면 개발자가 열심히 노력해야합니다. 우수한 결과를 얻을 수 있지만이를 위해서는 뇌를 사용해야합니다. C ++는 더 많은 도구를 제공하기로 결정한 언어로, 언어를 잘 사용하기 위해 배워야하는 비용을 청구합니다.


4
CPU 최적화를 위해 컴파일하는 것이 그리 많지는 않지만 런타임 경로 최적화를 위해 컴파일하고 있습니다. 특정 매개 변수를 사용하여 메서드가 매우 자주 호출되는 경우 해당 매개 변수를 상수로 사용하여 해당 루틴을 미리 컴파일하여 (흐름을 제어하는 ​​부울의 경우) 거대한 작업 덩어리를 제거 할 수 있습니다. C ++는 이러한 종류의 최적화를 수행 할 수 없습니다.
Bill K

1
그렇다면 관찰 된 런 패스를 활용하기 위해 루틴을 재 컴파일 할 때 JIT는 어떻게할까요?
David Thornley

2
@Bill 내가 두 가지를 혼합하고있을 수 있지만, 명령어 파이프 라인에서 런타임에 분기 예측이 수행되어 언어와 관계없이 비슷한 목표를 달성하지 않습니까?
Hardy

@Hardy 예, CPU는 언어에 관계없이 분기 예측을 수행 할 수 있지만 루프가 어떤 것에 영향을 미치지 않음을 관찰하여 전체 루프를 고려할 수는 없습니다. 또한 mult (0)이 0을 반환하도록 고정 연결되어 있지 않고 전체 메서드 호출을 if (param == 0) result = 0으로 대체합니다. 전체 함수 / 메소드 호출을 피하십시오. C는 컴파일러가 무슨 일이 일어나고 있는지에 대한 포괄적 인 개요를 가지고 있다면 이러한 일을 할 수 있지만 일반적으로 컴파일 타임에 충분한 정보가 없습니다.
Bill K

21

JIT (Just In Time Compiling)는 대상 플랫폼에 최적화되기 때문에 매우 빠를 수 있습니다.

이는 개발자가 코드를 작성한 CPU에 관계없이 CPU가 지원할 수있는 모든 컴파일러 트릭을 활용할 수 있음을 의미합니다.

.NET JIT의 기본 개념은 다음과 같이 작동합니다 (매우 단순화 됨).

처음으로 메서드 호출 :

  • 프로그램 코드는 Foo () 메서드를 호출합니다.
  • CLR은 Foo ()를 구현하는 형식을 확인하고 이와 관련된 메타 데이터를 가져옵니다.
  • 메타 데이터에서 CLR은 IL (중간 바이트 코드)이 저장된 메모리 주소를 알고 있습니다.
  • CLR은 메모리 블록을 할당하고 JIT를 호출합니다.
  • JIT는 IL을 네이티브 코드로 컴파일하고 할당 된 메모리에 배치 한 다음이 네이티브 코드를 가리 키도록 Foo () 형식 메타 데이터의 함수 포인터를 변경합니다.
  • 네이티브 코드가 실행됩니다.

두 번째로 메서드 호출 :

  • 프로그램 코드는 Foo () 메서드를 호출합니다.
  • CLR은 Foo ()를 구현하는 형식을 살펴보고 메타 데이터에서 함수 포인터를 찾습니다.
  • 이 메모리 위치의 네이티브 코드가 실행됩니다.

보시다시피 실시간 최적화의 이점을 제외하고는 두 번째로 C ++와 거의 동일한 프로세스입니다.

즉, 관리 언어를 느리게하는 다른 오버 헤드 문제가 여전히 있지만 JIT가 많은 도움이됩니다.


그건 그렇고, 조나단, 누군가가 여전히 당신 물건에 반대하는 것 같아요. 내가 당신에게 투표했을 때 당신은이 게시물에 -1을 가졌습니다.
Brian R. Bondy

12

나는 Orion Adrian 의 대답을 좋아 하지만 다른 측면이 있습니다.

어셈블리 언어와 FORTRAN과 같은 "인간"언어에 대해 동일한 질문이 수십 년 전에 제기되었습니다. 그리고 대답의 일부는 비슷합니다.

예, C ++ 프로그램은 주어진 (사소하지 않은?) 알고리즘에서 C #보다 빠를 수 있지만 C #의 프로그램은 종종 C ++의 "순진한"구현 및 C ++의 최적화 된 버전보다 빠르거나 빠릅니다. 개발하는 데 시간이 더 오래 걸리며 여전히 C # 버전을 매우 작은 차이로 이길 수 있습니다. 그래서, 그만한 가치가 있습니까?

이 질문에 하나씩 대답해야합니다.

즉, 저는 C ++의 오랜 팬이며 믿을 수 없을 정도로 표현력이 풍부하고 강력한 언어라고 생각합니다. 그러나 많은 "실제"문제 (개인적으로는 "해결을 위해 돈을받는 종류"를 의미 함)에서 C #은 작업을 더 빠르고 안전하게 수행 할 수 있습니다.

당신이 지불하는 가장 큰 벌금은? 많은 .NET 및 Java 프로그램은 메모리를 많이 사용합니다. .NET 및 Java 응용 프로그램이 비슷한 복잡성의 C ++ 프로그램이 "수십"MB를 거의 긁지 않을 때 "수백"메가 바이트의 메모리를 사용하는 것을 보았습니다.


7

핫스팟을 사용하더라도 Java 코드가 C ++보다 더 빠르게 실행될 수 있다는 사실을 얼마나 자주 알 수 있을지는 모르겠지만 어떻게 일어날 수 있는지 설명해 드리겠습니다.

컴파일 된 Java 코드를 JVM 용으로 해석 된 기계어라고 생각하십시오. 핫스팟 프로세서는 컴파일 된 코드의 특정 부분이 여러 번 사용될 것임을 감지하면 기계 코드에 대해 최적화를 수행합니다. 수동 튜닝 어셈블리는 거의 항상 C ++ 컴파일 코드보다 빠르기 때문에 프로그래밍 방식으로 튜닝 된 기계 코드가 그리 나쁘지 않을 것이라고 생각하는 것이 좋습니다.

따라서 매우 반복적 인 코드의 경우 가비지 수집이 작동 할 때까지 Hotspot JVM이 C ++보다 빠르게 Java를 실행할 수있는 위치를 알 수있었습니다. :)


주장을 확장 할 수 Since hand-tuning Assembly is almost always faster than C++ compiled code있습니까? "핸드 튜닝 어셈블리"와 "C ++ 컴파일 코드"란 무엇을 의미합니까?
paercebal

글쎄요, 그것은 컴파일러의 옵티마이 저가 규칙을 따르고 코더는 그렇지 않다는 생각에 기초합니다. 따라서 최적화 프로그램이 완벽하게 최적화 할 수없는 코드가 항상 존재하는 반면, 인간은 더 큰 그림을 보거나 코드가 실제로 수행하는 작업에 대해 더 많이 알 수 있습니다. 나는 이것이 3 년 된 코멘트라고 덧붙일 것이다. 그리고 나는 내가 예전보다 HotSpot에 대해 더 많이 알고 있으며, 동적 최적화가 코드를 더 빠르게 실행하는 아주 좋은 방법이라는 것을 쉽게 볼 수있다.
billjamesdev

1. Hotspot 또는 기타 JIT의 최적화는 여전히 컴파일러 최적화입니다. JIT는 일부 결과 (자주 호출되는 코드)를 인라인 할 수 있거나 실행중인 프로세서를 기반으로 최적화 할 수 있다는 점에서 정적 컴파일러에 비해 장점이 있지만 여전히 컴파일러 최적화입니다. . . 2. "어셈블리 미세 조정"이 아니라 알고리즘 최적화에 대해 이야기하고있는 것 같습니다. "인간 코더에 의한 수동 어셈블리 미세 조정"은 10 년 이상 컴파일러 최적화보다 더 나은 결과를 생성하지 못했습니다. 사실과 인간 연주 어셈블리 보통 ... 어떤 최적화 떨어진 나사
paercebal

좋아, "정적 최적화"가 아니라 "컴파일러 최적화"라는 잘못된 용어를 사용하고 있다는 것을 알았습니다. 적어도 게임 업계에서는 최근에 PS2와 마찬가지로 콘솔에있는 특정 칩에 대해 "최적화"하기 위해 여전히 손으로 코딩 한 어셈블리를 사용하고있었습니다. 이러한 새로운 칩의 크로스 컴파일러는 아직 x86 아키텍처만큼 정교하지 않습니다. 위의 원래 질문으로 돌아가서 : JIT는 최적화 전에 측정 할 수 있다는 이점이 있습니다. 이는 Good Thing (TM)입니다
billjamesdev 2011

대부분의 프로덕션 GC는 C / C ++가 자르지 않기 때문에 손으로 작성한 어셈블러도 사용합니다.
JD

6

일반적으로 귀하의 프로그램은 알고리즘언어 보다 응용 프로그램의 속도에 훨씬 더 중요합니다 . C ++를 포함한 모든 언어로 잘못된 알고리즘을 구현할 수 있습니다. 이를 염두에두고 일반적으로 더 효율적인 알고리즘을 구현하는 데 도움이되는 언어로 실행되는 코드를 더 빠르게 작성할 수 있습니다.

높은 수준의 언어는 효율적으로 사전 구축 된 많은 데이터 구조에 더 쉽게 액세스 할 수 있도록하고 비효율적 인 코드를 방지하는 데 도움이되는 권장 사항을 제공함으로써이 작업을 매우 잘 수행합니다. 물론 때로는 정말 느린 코드를 쉽게 작성할 수 있으므로 여전히 플랫폼을 알아야합니다.

또한 C ++는 STL 컨테이너, 자동 포인터 등과 같은 "새로운"(따옴표 참고) 기능을 따라 잡고 있습니다. 예를 들어 부스트 라이브러리를 참조하십시오. 일부 작업을 수행하는 가장 빠른 방법은 일반적으로 원하는대로 구현할 수있는 언어로 작성된 라이브러리를 호출 할 수 있도록 허용하지만 상위 수준 언어에서는 금지 된 포인터 산술과 같은 기술이 필요하다는 것을 종종 발견 할 수 있습니다. .

가장 중요한 것은 사용중인 언어, 관련 API, 수행 할 수있는 작업 및 제한 사항을 아는 것입니다.


5

나도 모르겠다 ... 내 자바 프로그램은 항상 느리다. :-) 나는 C # 프로그램이 특히 느리다는 것을 결코 눈치 채지 못했습니다.


4

여기에 또 다른 흥미로운 벤치 마크가 있으며, 자신의 컴퓨터에서 직접 시도해 볼 수 있습니다.

ASM, VC ++, C #, Silverlight, Java 애플릿, Javascript, Flash (AS3)를 비교합니다.

Roozz 플러그인 속도 데모

자바 스크립트의 속도는 실행중인 브라우저에 따라 크게 다릅니다. 이러한 플러그인은 호스팅 브라우저와 동일한 프로세스에서 실행되기 때문에 Flash 및 Silverlight에서도 마찬가지입니다. 그러나 Roozz 플러그인은 자체 프로세스에서 실행되는 표준 .exe 파일을 실행하므로 속도는 호스팅 브라우저의 영향을받지 않습니다.


4

"보다 나은 성능 .."을 정의해야합니다. 글쎄요, 당신은 속도에 대해 물었지만 그것이 중요한 모든 것은 아닙니다.

  • 가상 머신이 더 많은 런타임 오버 헤드를 수행합니까? 예!
  • 그들은 더 많은 작업 기억을 먹나요? 예!
  • 시작 비용이 더 높습니까 (런타임 초기화 및 JIT 컴파일러)? 예!
  • 거대한 라이브러리를 설치해야합니까? 예!

등, 편향, 예;)

C # 및 Java를 사용하면 얻는 것에 대한 대가를 지불합니다 (더 빠른 코딩, 자동 메모리 관리, 대용량 라이브러리 등). 그러나 세부 사항에 대해 흥정 할 여지가 많지 않습니다. 전체 패키지를 가져 오거나 아무것도 가져 가지 않습니다.

이러한 언어가 일부 코드를 최적화하여 컴파일 된 코드보다 빠르게 실행할 수 있다고해도 전체 접근 방식은 (IMHO) 비효율적입니다. 트럭을 타고 직장까지 매일 5 마일을 운전한다고 상상해보십시오! 편안하고, 기분이 좋고, 안전하며 (극단 크럼 플 존), 잠시 주유를 밟으면 일반 차량만큼 빠를 것입니다! 우리 모두가 출근 할 트럭이없는 이유는 무엇입니까? ;)

C ++에서 당신은 당신이 지불하는 것을 더 많이, 더 적게 얻지 않습니다.

Bjarne Stroustrup 인용 : "C ++는 쓰레기를 거의 생성하지 않기 때문에 내가 가장 좋아하는 가비지 수집 언어입니다." 링크 텍스트


글쎄, 나는 그가 그 단점에 대해 좋은 생각을 가지고 있다고 생각한다. 그는 또한 말했다 : "C는 발에 자신을 쏠 수있게
해주고

"거대한 라이브러리를 설치해야합니까?"Java는 제가 믿는 프로젝트 퍼즐로이 문제를 해결하고 있습니다.
toc777 2011 년

"C ++에서 당신은 당신이 지불하는 것을 더 많이, 더 적게 얻지 않습니다." 카운터 예 : 기존 세트를 재사용하기 위해 추가중인 요소가 이미있는 경우 재귀에서 멀리 점프하는 예외를 사용하는 OCaml 및 C ++ (GNU GCC)의 RB 트리 구현을 벤치마킹했습니다. OCaml은 스택이 풀릴 때 소멸자를 확인하는 데 비용을 지불하지 않기 때문에 C ++보다 최대 6 배 더 빠릅니다.
JD

3
@Jon : 그러나 어떤 시점에서 (나중에?) 어쨌든 객체를 파괴해야합니다 (적어도 메모리를 해제해야합니다). 또한 예외는 예외적 인 경우에 대한 것입니다. 적어도 C ++에서는 규칙을 준수해야합니다. C ++ 예외는 예외가 발생할 때 무거울 수 있습니다.
Frunsi 2011 년

@Jon : times셸에서 벤치 마크를 반복 해보십시오 . 따라서 단일 측면이 아닌 전체 프로그램을 확인합니다. 결과가 비슷합니까?
Frunsi 2011 년

3

Java 또는 C # 컴파일러에서 생성 된 실행 코드는 해석되지 않으며 "JIT (just in time)"(JIT) 네이티브 코드로 컴파일됩니다. 따라서 Java / C # 프로그램의 첫 번째 코드는 실행 중에 발생합니다. "런타임 컴파일러"(일명 JIT 컴파일러)가 바이트 코드 (Java) 또는 IL 코드 (C #)를 기본 기계 명령어로 변환하므로 약간의 오버 헤드가 발생합니다. 그러나 애플리케이션이 계속 실행되는 동안 다음에 해당 코드가 발견되면 네이티브 코드가 즉시 실행됩니다. 이것은 일부 Java / C # 프로그램이 처음에는 느리지 만 실행 시간이 길수록 성능이 더 좋아지는 방식을 설명합니다. 좋은 예는 ASP.Net 웹 사이트입니다. 웹 사이트에 처음으로 액세스하면 JIT 컴파일러에 의해 C # 코드가 네이티브 코드로 컴파일되므로 속도가 약간 느려질 수 있습니다.


3

귀하가 요청한 특정 질문에 대한 몇 가지 좋은 답변입니다. 뒤로 물러서서 더 큰 그림을보고 싶습니다.

작성하는 소프트웨어의 속도에 대한 사용자의 인식은 코드 생성이 얼마나 잘 최적화되었는지뿐만 아니라 다른 많은 요인의 영향을받습니다. 여기 몇 가지 예가 있어요.

  • 수동 메모리 관리는 올바르게 수행하기 어렵고 (누수 없음) 효율적으로 수행하기 훨씬 더 어렵습니다. 일반적으로 GC를 사용하면 메모리를 잘 관리하는 프로그램이 생성 될 가능성이 높습니다. GC를 능가하기 위해 매우 열심히 일하고 소프트웨어 제공을 연기 할 의향이 있습니까?

  • 내 C #은 내 C ++보다 읽고 이해하기 쉽습니다. 또한 내 C # 코드가 올바르게 작동하고 있음을 확신 할 수있는 더 많은 방법이 있습니다. 즉, 버그를 유발할 위험을 줄이면서 알고리즘을 최적화 할 수 있습니다 (그리고 사용자는 빠르게 작동하더라도 충돌하는 소프트웨어를 좋아하지 않습니다!).

  • C ++보다 C #에서 소프트웨어를 더 빨리 만들 수 있습니다. 이를 통해 성능 작업에 필요한 시간을 확보하고 제 소프트웨어를 적시에 제공 할 수 있습니다.

  • C ++보다 C #에서 좋은 UI를 작성하는 것이 더 쉽기 때문에 UI가 응답하는 동안 작업을 백그라운드로 푸시하거나 프로그램이 잠시 차단해야 할 때 진행률 또는 히어 비트 UI를 제공 할 가능성이 더 큽니다. 이것은 아무것도 더 빨리 만들지는 않지만 사용자가 기다리는 것에 대해 더 행복하게 만듭니다.

내가 C #에 대해 말한 모든 것은 아마도 자바의 경우 사실 일 것입니다. 확실히 말할 경험이 없습니다.


3

C ++를 배우는 Java / C # 프로그래머라면 Java / C # 측면에서 계속 생각하고 그대로 C ++ 구문으로 번역하고 싶은 유혹을받을 것입니다. 이 경우 이전에 언급 한 네이티브 코드와 해석 / JIT의 이점 만 얻을 수 있습니다. C ++ 대 Java / C #에서 가장 큰 성능 향상을 얻으려면 C ++로 생각하고 특히 C ++의 장점을 활용하기위한 코드를 설계하는 방법을 배워야합니다.

Edsger Dijkstra 를 의역하면 : [당신의 모국어]는 회복을 넘어 마음을 훼손합니다. Jeff Atwood 를 다른 말로 바꾸
려면 : 새로운 언어로 [당신의 모국어]를 쓸 수 있습니다.


1
나는 "어떤 언어로든 FORTRAN을 쓸 수있다"는 말이 Jeff의 경력보다 앞서 있다고 생각합니다.
David Thornley

3

가장 중요한 JIT 최적화 중 하나는 메서드 인라인입니다. Java는 런타임 정확성을 보장 할 수있는 경우 가상 메소드를 인라인 할 수도 있습니다. 이러한 종류의 최적화는 일반적으로 전체 프로그램 분석이 필요하기 때문에 표준 정적 컴파일러에서 수행 할 수 없습니다. 이는 별도의 컴파일로 인해 어렵습니다 (반대로 JIT에는 사용할 수있는 모든 프로그램이 있음). 메서드 인라인은 다른 최적화를 개선하여 최적화 할 더 큰 코드 블록을 제공합니다.

Java / C #의 표준 메모리 할당도 더 빠르며 할당 해제 (GC)는 그다지 느리지 않고 덜 결정적입니다.


참고 freedelete결정하거나 및 GC를 할당하지 않음으로써 확정 될 수 없다.
JD

3

가상 머신 언어는 컴파일 된 언어를 능가하지는 않지만 (적어도) 다음과 같은 이유 때문에 중요하지 않을 정도로 충분히 가까워 질 수 있습니다 (C #을 한 번도 해본 적이 없기 때문에 여기에서 Java에 대해 말하고 있습니다).

1 / Java Runtime Environment는 일반적으로 자주 실행되는 코드 조각을 감지하고 해당 섹션의 JIT (Just-In-Time) 컴파일을 수행하여 향후 전체 컴파일 속도로 실행할 수 있습니다.

2 / 자바 라이브러리의 방대한 부분이 컴파일되어 라이브러리 함수를 호출 할 때 해석되지 않고 컴파일 된 코드를 실행하게됩니다. OpenJDK를 다운로드하여 코드 (C)를 볼 수 있습니다.

3 / 방대한 계산을하지 않는 한 프로그램이 실행되는 대부분의 시간은 매우 느린 (상대적으로 말하는) 사람의 입력을 기다리고 있습니다.

4 / 클래스를로드 할 때 Java 바이트 코드의 유효성 검사를 많이 수행하므로 런타임 검사의 일반적인 오버 헤드가 크게 줄어 듭니다.

5 / 최악의 경우 성능 집약적 인 코드를 컴파일 된 모듈로 추출하고 Java (JNI 참조)에서 호출하여 최대 속도로 실행할 수 있습니다.

요약하면, 자바 바이트 코드는 결코 네이티브 기계어를 능가하지는 않지만이를 완화 할 수있는 방법이 있습니다. Java의 가장 큰 장점은 거대한 표준 라이브러리와 크로스 플랫폼 특성입니다.


1
Re item 2, "2 / 자바 라이브러리의 방대한 부분이 컴파일되어 라이브러리 함수를 호출 할 때 해석되지 않고 컴파일 된 코드를 실행하게됩니다.": 이에 대한 인용이 있습니까? 실제로 설명하신대로라면 디버거에서 네이티브 코드가 많이 나올 것으로 예상되지만 그렇지 않습니다.
cero

Re : cero 디버거는 종종 덜 효율적이지만 더 표현적인 경로를 사용하므로 성능과 관련된 모든 것에 대한 좋은 마커가 아닙니다.
Guvante

2
This HUGH 라이브러리에는 또 다른 큰 성능 향상이 있습니다. 라이브러리 코드는 많은 프로그래머가 독자적으로 작성하는 것 (제한된 시간과 전문 지식이 부족한 경우)과 Java에서 작성하는 것보다 더 잘 작성 될 수 있습니다. 여러 가지 이유로 프로그래머는 자주 사용합니다. 도서관.
Liran Orevi 2009

3

Orion Adrian , C ++에 대해서도 많이 말할 수 있기 때문에 귀하의 발언이 얼마나 근거가 없는지 확인하기 위해 귀하의 게시물을 뒤집어 보겠습니다. Java / C # 컴파일러가 빈 함수를 최적화한다고 말하면 실제로는 그렇지 않은 것처럼 들립니다. 나의 최적화 전문가 합니다. 왜냐하면 a) 진짜 프로그램이 정말 나쁜 레거시 코드를 제외하고는 왜 빈 함수를 포함해야하는지, b) 정말 그렇지 않기 때문입니다. 블랙 및 블리딩 엣지 최적화.

그 문구와는 별개로 포인터에 대해 노골적으로 말했지만 Java 및 C #의 객체는 기본적으로 C ++ 포인터처럼 작동하지 않습니까? 겹치지 않을 수 있습니까? null이 아닐 수 있습니까? C (및 대부분의 C ++ 구현)에는 restrict 키워드가 있고 둘 다 값 유형이 있고 C ++에는 널이 아닌 값을 보장하는 값에 대한 참조가 있습니다. Java 및 C #은 무엇을 제공합니까?

>>>>>>>>>>

일반적으로 C 및 C ++는 AOT 컴파일러 (배포 전에 코드를 컴파일하는 컴파일러)가 높은 메모리의 많은 코어 빌드 서버에서 한 번에 한 번에 C # 컴파일 된 프로그램을 최적화 할 수 있기 때문에 빠르거나 빠를 수 있습니다. 그렇게 할 시간이 많기 때문에 할 수 없습니다. 컴파일러는 시스템이 Intel인지 AMD인지 확인할 수 있습니다. Pentium 4, Core Solo 또는 Core Duo; 또는 SSE4 등을 지원하고 컴파일러가 런타임 디스패치를 ​​지원하지 않는 경우 소수의 특수 바이너리를 배포하여 직접 해결할 수 있습니다.

AC # 프로그램은 일반적으로는 모든 시스템에서 잘 친절하게 실행하지만 단일 구성 (예 : 프로세서, 명령어 세트, 기타 하드웨어)이 될 수있는만큼 최적화되지 않도록 그것을 실행에 컴파일, 그리고 그것을 해야한다 시간을 보내고 먼저. 루프 분열, 루프 반전, 자동 벡터화, 전체 프로그램 최적화, 템플릿 확장, IPO 등과 같은 기능은 최종 사용자를 괴롭히지 않는 방식으로 완전히 해결하기가 매우 어렵습니다.

또한 특정 언어 기능을 사용하면 C ++ 또는 C의 컴파일러가 Java / C # 컴파일러가 수행하기에 안전하지 않은 특정 부분을 최적화 할 수 있도록 코드에 대한 가정을 할 수 있습니다. 제네릭의 전체 유형 ID 또는 보장 된 프로그램 흐름에 액세스 할 수없는 경우 안전하지 않은 최적화가 많이 있습니다.

또한 C ++ 및 C는 한 번의 레지스터 증분으로 한 번에 많은 스택 할당을 수행하므로 가비지 수집기와 코드 간의 추상화 계층에 대해 Java 및 C # 할당보다 확실히 더 효율적입니다.

이제이 다음 지점에서 Java에 대해 말할 수는 없지만, 예를 들어 C ++ 컴파일러는 메서드의 본문이 비어 있음을 알 때 실제로 메서드와 메서드 호출을 제거하고 일반적인 하위 표현식을 제거하고 시도하고 다시 시도 할 수 있음을 알고 있습니다. 최적의 레지스터 사용을 찾기 위해 경계 검사를 시행하지 않고 루프와 내부 루프를 자동 벡터화하고 내부에서 외부로 반전하고 조건을 루프 밖으로 이동하고 루프를 분할 및 분할 해제합니다. C 방식으로 수행하는 것처럼 std :: vector를 기본 제로 오버 헤드 배열로 확장합니다. 절차 간 최적화를 수행합니다. 호출자 사이트에서 직접 반환 값을 구성합니다. 표현을 접고 전파합니다. 캐시 친화적 인 방식으로 데이터를 재정렬합니다. 점프 스레딩을 수행합니다. 런타임 오버 헤드없이 컴파일 타임 레이 트레이서를 작성할 수 있습니다. 그것은 매우 비싼 그래프 기반 최적화를 만들 것입니다. 특정 코드를 구문 적으로는 완전히 같지 않지만 의미 적으로는 동등한 코드로 대체하면 강도 감소를 수행 할 것입니다 (이전 "xor foo, foo"는 이러한 종류의 오래된 최적화이지만 가장 간단합니다). 친절하게 물어 보면 IEEE 부동 소수점 표준을 생략하고 부동 소수점 피연산자 재정렬과 같은 더 많은 최적화를 활성화 할 수 있습니다. 코드를 마사지하고 대량 학살 한 후에는 전체 프로세스를 반복 할 수 있습니다. 왜냐하면 특정 최적화는 더 확실한 최적화를위한 토대를 마련하기 때문입니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다. 특정 코드를 구문 적으로는 완전히 같지 않지만 의미 적으로는 동등한 코드로 대체하는 경우 (이전 "xor foo, foo"는 이러한 종류의 오래된 최적화이지만 가장 단순합니다). 친절하게 물어 보면 IEEE 부동 소수점 표준을 생략하고 부동 소수점 피연산자 재정렬과 같은 더 많은 최적화를 활성화 할 수 있습니다. 코드를 마사지하고 대량 학살 한 후에는 전체 프로세스를 반복 할 수 있습니다. 왜냐하면 특정 최적화는 더 확실한 최적화를위한 토대를 마련하기 때문입니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다. 특정 코드를 구문 적으로는 완전히 같지 않지만 의미 적으로는 동등한 코드로 대체하는 경우 (이전 "xor foo, foo"는 이러한 종류의 오래된 최적화이지만 가장 단순합니다). 친절하게 물어 보면 IEEE 부동 소수점 표준을 생략하고 부동 소수점 피연산자 재정렬과 같은 더 많은 최적화를 활성화 할 수 있습니다. 코드를 마사지하고 대량 학살 한 후에는 전체 프로세스를 반복 할 수 있습니다. 왜냐하면 특정 최적화는 더 확실한 최적화를위한 토대를 마련하기 때문입니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다. 친절하게 물어 보면 IEEE 부동 소수점 표준을 생략하고 부동 소수점 피연산자 재정렬과 같은 더 많은 최적화를 활성화 할 수 있습니다. 코드를 마사지하고 대량 학살 한 후에는 전체 프로세스를 반복 할 수 있습니다. 왜냐하면 특정 최적화는 더 확실한 최적화를위한 토대를 마련하기 때문입니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다. 친절하게 물어 보면 IEEE 부동 소수점 표준을 생략하고 부동 소수점 피연산자 재정렬과 같은 더 많은 최적화를 활성화 할 수 있습니다. 코드를 마사지하고 대량 학살 한 후에는 전체 프로세스를 반복 할 수 있습니다. 왜냐하면 특정 최적화는 더 확실한 최적화를위한 토대를 마련하기 때문입니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다. 또한 셔플 된 매개 변수로 재 시도하고 다른 변형이 내부 순위에서 점수를 매기는 방식을 볼 수도 있습니다. 그리고 코드 전체에서 이러한 종류의 논리를 사용합니다.

보시다시피 특정 C ++ 또는 C 구현이 더 빠른 이유는 많습니다.

이 모든 것이 말했듯이, C #으로 할 수있는 모든 작업, 특히 숫자 처리, 실시간 및 금속에 가까운 영역에서 할 수있는 모든 작업을 C ++로 많이 최적화 할 수 있습니다. 먼 길을 가기 위해 단일 포인터를 만질 필요조차 없습니다.

그래서 당신이 쓰는 것에 따라 나는 둘 중 하나와 함께 갈 것입니다. 그러나 하드웨어에 의존하지 않는 무언가 (드라이버, 비디오 게임 등)를 작성하는 경우 C #의 성능에 대해 걱정하지 않을 것입니다 (다시 Java에 대해서는 말할 수 없음). 잘 될 것입니다.

<<<<<<<<<<

일반적으로 특정 일반화 된 주장은 특정 게시물에서 멋지게 들릴 수 있지만 일반적으로 확실하게 신뢰할 수는 없습니다.

어쨌든, 평화를 위해 : AOTJIT 와 마찬가지로 훌륭 합니다. 유일한 정답은 다음과 같습니다. 그리고 진짜 똑똑한 사람들은 어쨌든 두 세계의 장점을 모두 사용할 수 있다는 것을 알고 있습니다.


2

Java 인터프리터가 컴파일러가 작성중인 C ++ 코드에 대해 생성하는 기계어 코드보다 실제로 더 잘 최적화 된 기계어 코드를 생성하는 경우에만 C ++ 코드가 Java 및 해석 비용보다 느린 지점까지 발생합니다.

그러나 실제로 일어날 확률은 매우 낮습니다. Java에 잘 작성된 라이브러리가 있고 자신의 잘못 작성된 C ++ 라이브러리가있는 경우를 제외하고는 그렇습니다.


또한 특정 언어 가중치도 있다고 믿습니다. 더 낮은 수준에서 작업 할 때 추상화가 덜한 더 빠른 프로그램을 개발하게 될 것입니다. 이것은 바이트 코드 실행 자체에 대한 요점과 관련이 없습니다.
Brian R. Bondy

2

실제로 C #은 Java와 같은 가상 머신에서 실제로 실행되지 않습니다. IL은 완전히 네이티브 코드이며 네이티브 코드와 동일한 속도로 실행되는 어셈블리 언어로 컴파일됩니다. JIT 비용을 완전히 제거한 .NET 애플리케이션을 사전 JIT 한 다음 완전히 네이티브 코드를 실행할 수 있습니다.

.NET의 속도 저하는 .NET 코드가 느리기 때문이 아니라 가비지 수집, 참조 확인, 전체 스택 프레임 저장 등과 같은 작업을 수행하기 위해이면에서 훨씬 더 많은 작업을 수행하기 때문입니다. 이것은 다음과 같은 경우에 매우 강력하고 도움이 될 수 있습니다. 응용 프로그램을 구축하지만 비용이 발생합니다. C ++ 프로그램에서도 이러한 모든 작업을 수행 할 수 있습니다 (대부분의 핵심 .NET 기능은 실제로 ROTOR에서 볼 수있는 .NET 코드입니다). 그러나 동일한 기능을 직접 작성했다면 .NET 런타임이 최적화되고 미세 조정 되었기 때문에 프로그램 속도가 훨씬 느려질 것입니다.

즉, 관리 코드의 강점 중 하나는 완전히 검증 할 수 있다는 것입니다. 코드가 다른 프로세스의 메모리에 액세스하지 않거나 실행하기 전에 작업을 해제하지 않는지 확인할 수 있습니다. Microsoft는 100 % 관리되는 환경이 관리되는 프로그램에 더 이상 필요하지 않은 보안 기능을 해제하는 데이 확인을 활용하여 실제로 최신 운영 체제보다 훨씬 빠르게 수행 할 수 있음을 놀랍게도 보여준 완전 관리 형 운영 체제의 연구 프로토 타입을 보유하고 있습니다. (어떤 경우에는 10x처럼 이야기하고 있습니다). SE 라디오에는이 프로젝트에 대해 이야기하는 훌륭한 에피소드가 있습니다.


1

어떤 경우에는 관리 코드가 실제로 네이티브 코드보다 빠를 수 있습니다 . 예를 들어, "mark-and-sweep"가비지 수집 알고리즘을 사용하면 JRE 또는 CLR과 같은 환경에서 대부분의 C / C ++ 힙 개체가 한 번에 해제되는 단일 패스에서 많은 수의 단기 (일반적으로) 개체를 해제 할 수 있습니다. 시간.

에서 위키 피 디아 :

많은 실제 목적을 위해 가비지 수집 언어로 구현 된 할당 / 할당 해제 집약적 인 알고리즘은 실제로 수동 힙 할당을 사용하는 동등한 알고리즘보다 빠를 수 있습니다. 이에 대한 주된 이유는 가비지 수집기가 런타임 시스템이 잠재적으로 유리한 방식으로 할당 및 할당 해제 작업을 분할 할 수 있도록하기 때문입니다.

즉, 저는 많은 C #과 많은 C ++를 작성했으며 많은 벤치 마크를 실행했습니다. (1) 당신이 몇 가지 코드를 가지고가는 경우에 당신은 C 포트는 ++ 네이티브 코드는 C #으로 작성했다고 : 내 경험에 의하면, C ++는 두 가지 방법으로 C #을보다 빠르게 많은입니다 경향은 가 더 빠른 이 있습니다. 얼마나 빨리요? 음, 매우 다양하지만 100 % 속도 향상을 보는 것은 드문 일이 아닙니다. (2) 경우에 따라 가비지 수집은 관리되는 응용 프로그램의 속도 를 크게 저하 시킬 수 있습니다 . .NET CLR은 대용량 힙 (예 :> 2GB)으로 끔찍한 작업을 수행하며 중간 수명의 개체가 거의 없거나 전혀없는 애플리케이션에서도 GC에서 많은 시간을 소비 할 수 있습니다.

물론 내가 경험 한 대부분의 경우 관리되는 언어는 충분히 빠르며 C ++의 추가 성능에 대한 유지 관리 및 코딩 절충은 단순히 좋은 것이 아닙니다.


1
문제는 웹 서버와 같이 오래 실행되는 프로세스의 경우 시간이 지남에 따라 메모리가 너무 조각화되어 (C ++로 작성된 프로그램에서) 가비지 수집과 유사한 것을 구현해야 (또는 자주 다시 시작해야한다는 것입니다. IIS 참조) ).
Tony BenBrahim

3
나는 영원히 실행되는 것을 의미하는 큰 유닉스 프로그램에서 그것을 보지 못했습니다. 그것들은 C로 작성되는 경향이 있으며, 이는 C ++보다 메모리 관리에있어서 더 나쁩니다.
David Thornley

물론 문제는 관리되는 코드와 관리되지 않는 코드의 프로그램 구현을 비교하는지 아니면 언어의 이론적 최고 성능을 비교하는지 여부입니다. 분명히 관리되지 않는 코드는 최소한 관리되는 것만 큼 빠를 수 있습니다 . 최악의 경우 관리되는 코드와 똑같은 작업을 수행하는 관리되지 않는 프로그램을 작성할 수 있습니다. 그러나 대부분의 성능 문제는 마이크로가 아니라 알고리즘입니다. 또한 관리 코드와 비 관리 코드를 같은 방식으로 최적화하지 않으므로 "C #의 C ++"는 일반적으로 제대로 작동하지 않습니다.
kyoryu

2
C / C ++ 에서는 스택에 수명이 짧은 개체를 할당 할 있으며 적절할 때 수행합니다. 관리 코드에서는 할 없으며 선택의 여지가 없습니다. 또한, C에 / C ++에서 당신이 할 수 인접하게 영역에서 개체의 목록을 할당 (새 푸 [100]), 당신은 할 수 없습니다 관리되는 코드이다. 따라서 귀하의 비교는 유효하지 않습니다. 글쎄,이 선택의 힘은 개발자들에게 부담을 주지만, 이런 식으로 그들은 그들이 살고있는 세상을 아는 법을 배웁니다 (메모리 ......).
Frunsi 2009

@frunsi : "C / C ++에서는 연속 영역 (new Foo [100])에 개체 목록을 할당 할 수 있지만 관리 코드에서는 할당 할 수 없습니다." 그것은 틀 렸습니다. 로컬 값 유형은 스택 할당되며 C #에서 스택 할당 배열을 스택 할 수도 있습니다. 안정된 상태에서 완전히 할당되지 않는 C #으로 작성된 프로덕션 시스템도 있습니다.
JD


1

실제로 Sun의 HotSpot JVM은 "혼합 모드"실행을 사용합니다. 특정 코드 블록 (메서드, 루프, try-catch 블록 등)이 많이 실행될 것이라고 결정할 때까지 (보통 일종의 카운터를 통해) 메서드의 바이트 코드를 해석 한 다음 JIT가 컴파일합니다. JIT가 메소드를 컴파일하는 데 필요한 시간은 드물게 실행되는 메소드 인 경우 메소드가 해석되는 경우보다 종종 더 오래 걸립니다. JVM이 거의 실행되지 않는 코드를 JITing하는 데 시간을 낭비하지 않기 때문에 "혼합 모드"의 경우 일반적으로 성능이 더 높습니다. C # 및 .NET은이를 수행하지 않습니다. .NET JIT는 종종 시간을 낭비하는 모든 것을 처리합니다.


1

HP Labs의 Dynamo 에 대해 읽어보십시오.PA-8000에서 실행되고 종종 프로그램을 원래보다 빠르게 실행하는 PA-8000 용 인터프리터 인 . 그렇다면 전혀 놀라운 일이 아닙니다!

"중간 단계"라고 생각하지 마십시오. 프로그램을 실행하는 데는 이미 다른 많은 단계가 포함됩니다.

다음과 같은 경우가 많습니다.

  • 프로그램에는 핫스팟이 있으므로 실행해야하는 코드 본문의 95 %를 느리게 실행하더라도 핫스팟 5 %에서 더 빠르면 여전히 성능 경쟁력이 있습니다.

  • HLL은 C / C ++와 같은 LLL보다 귀하의 의도에 대해 더 많이 알고 있으므로 더 최적화 된 코드를 생성 할 수 있습니다 (OCaml에는 훨씬 더 많은 것이 있으며 실제로는 훨씬 더 빠름)

  • JIT 컴파일러에는 정적 컴파일러가 제공하지 않는 많은 정보가 있습니다 (예 : 이번에 가지고있는 실제 데이터).

  • JIT 컴파일러는 기존 링커가 실제로 수행 할 수없는 최적화를 런타임에 수행 할 수 있습니다 (예 : 일반적인 경우가 플랫이되도록 분기 순서 변경 또는 라이브러리 호출 인라인)

대체로 C / C ++는 성능 측면에서 상당히 형편없는 언어입니다. 데이터 유형에 대한 정보가 비교적 적고, 데이터에 대한 정보가 없으며, 런타임 최적화에 많은 것을 허용하는 동적 런타임이 없습니다.


1

Java 또는 CLR이 C ++보다 빠르면 짧은 버스트가 발생할 수 있지만 전체적으로 응용 프로그램 수명 동안 성능이 더 나쁩니다. 이에 대한 일부 결과는 www.codeproject.com/KB/dotnet/RuntimePerformance.aspx를 참조하십시오.



1

내 이해는 C / C ++가 특정 기계 아키텍처에서 실행되는 네이티브 코드를 생성한다는 것입니다. 반대로 Java 및 C #과 같은 언어는 네이티브 아키텍처를 추상화하는 가상 머신 위에서 실행됩니다. 논리적으로이 중간 단계 때문에 Java 또는 C #이 C ++의 속도와 일치하는 것이 불가능 해 보이지만 최신 컴파일러 ( "핫스팟")가이 속도를 달성하거나 초과 할 수 있다고 들었습니다.

그것은 비논리적입니다. 중간 표현의 사용은 본질적으로 성능을 저하시키지 않습니다. 예를 들어, llvm-gcc는 LLVM IR (가상 무한 레지스터 머신)을 통해 C 및 C ++를 네이티브 코드로 컴파일하고 우수한 성능 (종종 GCC를 능가)을 달성합니다.

아마도 이것은 언어 질문보다 컴파일러 질문에 가깝지만, 누구나 이러한 가상 머신 언어 중 하나가 모국어보다 더 나은 성능을 발휘할 수있는 방법을 일반 영어로 설명 할 수 있습니까?

여기 몇 가지 예가 있어요.

  • JIT 컴파일이 포함 된 가상 머신은 런타임 코드 생성 (예 : System.Reflection.Emit.NET)을 용이하게 하므로 생성 된 코드를 C # 및 F #과 같은 언어로 즉석에서 컴파일 할 수 있지만 C 또는 C ++로 비교적 느린 인터프리터를 작성해야합니다. 예를 들어 정규 표현식을 구현합니다.

  • 가상 머신의 일부 (예 : 쓰기 장벽 및 할당 자)는 C와 C ++가 충분히 빠른 코드를 생성하지 않기 때문에 종종 직접 코딩 된 어셈블러로 작성됩니다. 프로그램이 시스템의 이러한 부분을 강조하면 C 또는 C ++로 작성할 수있는 모든 것을 능가 할 수 있습니다.

  • 네이티브 코드를 동적으로 연결하려면 성능을 저해하고 전체 프로그램 최적화를 제거 할 수있는 ABI를 준수해야합니다.

나는 또한 비생산적으로 양극화 된 견해를 제시하는 paercebal의 위의 높은 찬성 답변 (누군가가 그의 답변에 대한 내 의견을 계속 삭제하기 때문에)에 대한 몇 가지 문제를 해결하고 싶습니다.

코드 처리는 컴파일 시간에 수행됩니다.

따라서 템플릿 메타 프로그래밍은 컴파일 타임에 프로그램을 사용할 수있는 경우에만 작동합니다. 예를 들어 런타임 코드 생성이 불가능하기 때문에 바닐라 C ++로 경쟁력있는 정규 표현식 라이브러리를 작성하는 것이 불가능합니다. 메타 프로그래밍).

... 유형으로 재생하는 것은 컴파일 타임에 수행됩니다 ... Java 또는 C #의 동등한 작업은 작성하기가 힘들며 컴파일 타임에 유형이 알려진 경우에도 런타임에 항상 느리고 해결됩니다.

C #에서는 참조 형식에만 해당되며 값 형식에는 해당되지 않습니다.

JIT 최적화에 상관없이 메모리에 대한 직접 포인터 액세스만큼 빠른 것은 없습니다. 메모리에 연속 된 데이터가있는 경우 C ++ 포인터 (예 : C 포인터 ... Caesar에게 기한을 부여하겠습니다)를 통해 데이터에 액세스하면 시간이 더 빨라집니다. Java / C #보다.

사람들은 포인터가 앨리어싱 관련 최적화를 방해하기 때문에 SciMark2 벤치 마크의 SOR 테스트에서 Java가 C ++를 능가하는 것을 관찰했습니다 .

또한 .NET은 링크 후 동적으로 링크 된 라이브러리에서 제네릭의 유형 특수화를 수행하지만 C ++는 링크하기 전에 템플릿을 확인해야하기 때문에 불가능합니다. 제네릭이 템플릿에 비해 갖는 가장 큰 장점은 이해할 수있는 오류 메시지입니다.


0

다른 사람들이 말한 것 외에도 .NET과 Java가 메모리 할당에 더 좋습니다. 예를 들어, C ++는 할 수 없지만 조각화 될 때 메모리를 압축 할 수 있습니다 (기본적으로, 영리한 가비지 수집기를 사용하는 경우 가능합니다).


또는 더 나은 C ++ 할당 자 및 / 또는 개체 풀을 사용하는 경우. 이것은 C ++ 관점에서 볼 때 마술과는 거리가 멀고 "힙 할당"이 스택 할당만큼 빠르도록 요약 할 수 있습니다.
paercebal

항상 모든 것을 힙에 할당한다면 .NET과 Java는 C / C ++보다 더 나은 성능을 발휘할 수 있습니다. 그러나 C / C ++에서는이 작업을 수행하지 않습니다.
Frunsi 2009

0

많은 속도가 필요한 모든 것에 대해 JVM은 C ++ 구현을 호출하기 때문에 대부분의 OS 관련 사항에 대해 JVM이 얼마나 좋은지보다 라이브러리가 얼마나 좋은지에 대한 질문입니다. 가비지 수집은 메모리를 절반으로 줄이지 만 더 멋진 STL 및 Boost 기능 중 일부를 사용하면 동일한 효과가 발생하지만 버그 가능성이 여러 배가됩니다.

많은 클래스가있는 대규모 프로젝트에서 C ++ 라이브러리와 많은 고급 기능을 사용하는 경우 JVM을 사용하는 것보다 느려질 수 있습니다. 훨씬 더 많은 오류가 발생하기 쉽습니다.

그러나 C ++의 이점은 스스로 최적화 할 수 있다는 것입니다. 그렇지 않으면 컴파일러 / jvm이하는 일에 갇혀 있습니다. 자체 컨테이너를 만들고, 정렬 된 자체 메모리 관리를 작성하고, SIMD를 사용하고, 여기 저기 어셈블리에 드롭하면 대부분의 C ++ 컴파일러가 자체적으로 수행하는 작업보다 최소 2 ~ 4 배의 속도를 높일 수 있습니다. 일부 작업의 경우 16x-32x. 더 나은 알고리즘을 사용하고 병렬화하면 동일한 알고리즘을 사용하는 것입니다. 증가는 일반적으로 사용되는 방법보다 훨씬 더 빠르고 때로는 수천 배 더 빠를 수 있습니다.


0

나는 그것을 몇 가지 다른 관점에서 본다.

  1. 무한한 시간과 리소스가 주어지면 관리 코드 또는 비 관리 코드가 더 빠를까요? 분명히 대답은 관리되지 않는 코드가 항상 최소한이 측면에서 관리 코드를 묶을 수 있다는 것입니다. 최악의 경우 관리 코드 솔루션을 하드 코딩하면됩니다.
  2. 한 언어로 된 프로그램을 다른 언어로 직접 번역하면 성능이 얼마나 나빠질까요? 아마 많은에 대한 어떤 두 언어. 대부분의 언어는 다른 최적화가 필요하고 다른 문제가 있습니다. 마이크로 퍼포먼스는 종종 이러한 세부 사항을 아는 데 중요합니다.
  3. 한정된 시간과 자원을 감안할 때 두 언어 중 어느 것이 더 나은 결과를 산출합니까? 이것은 가장 흥미로운 질문입니다. 관리되는 언어는 약간 느린 코드를 생성 할 수 있지만 (해당 언어에 대해 합리적으로 작성된 프로그램이 제공되면) 해당 버전이 더 빨리 완료되어 최적화에 더 많은 시간을 할애 할 수 있습니다.

0

매우 짧은 대답 : 고정 된 예산을 감안할 때 C ++ 애플리케이션보다 더 나은 성능의 자바 애플리케이션을 얻을 수 있습니다 (ROI 고려 사항) 또한 자바 플랫폼에는 더 좋은 프로파일 러가있어 핫스팟을 더 빨리 찾아 낼 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.