왜 C가 그렇게 빠르며 다른 언어가 그렇게 빠르거나 빠르지 않습니까?
StackOverflow 팟 캐스트를 들으면서 b은 "실제 프로그래머"가 C로 작성하고 C가 "머신에 가깝기 때문에"훨씬 빠릅니다. 다른 게시물에 대한 이전 주장을 남겨두고 다른 언어보다 더 빠를 수있는 C의 특별한 점은 무엇입니까? 또는 다른 방법으로 말하면 다른 언어가 C만큼 빨리 실행되는 바이너리로 컴파일 할 수 없도록하는 것은 무엇입니까?
C에 대해 특별한 점은 많지 않습니다. 이것이 빠른 이유 중 하나입니다.
가비지 수집 , 동적 입력 및 기타 기능을 지원하는 최신 언어로 프로그래머가 프로그램을보다 쉽게 작성할 수 있습니다.
캐치에는 응용 프로그램의 성능을 저하시키는 추가 처리 오버 헤드가 있습니다. C에는 그중 하나가 없으므로 오버 헤드가 없다는 것을 의미하지만 프로그래머는 메모리 누수 를 방지하기 위해 메모리 를 할당하고 여유 공간을 확보 해야하며 변수의 정적 입력을 처리해야합니다.
즉, Java ( Java Virtual Machine 사용 ) 및 .NET (Common Language Runtime 사용)과 같은 많은 언어와 플랫폼 은 기본 기계 코드를 생성하는 JIT (Just-In-Time) 컴파일 과 같은 출현으로 수년 동안 성능이 향상되었습니다. 더 높은 성능을 달성하기 위해 바이트 코드.
C 디자이너가 만든 거래가 있습니다. 즉, 그들은 안전보다 속도를 높이기로 결정했습니다. C는하지 않습니다
- 배열 인덱스 범위 확인
- 초기화되지 않은 변수 값 확인
- 메모리 누수 확인
- 널 포인터 역 참조 확인
Java로 배열에 색인을 생성하면 가상 시스템에서 일부 메소드 호출, 바운드 검사 및 기타 온 전성 검사가 필요합니다. 그것은 유효하고 절대적 으로 좋습니다. 왜냐하면 그것이 예정된 곳에 안전을 추가하기 때문입니다. 그러나 C에서는 아주 사소한 것조차 안전하지 않습니다. 예를 들어 C에서는 복사 할 영역이 겹치는 지 확인하기 위해 memcpy가 필요하지 않습니다. 그것은 것 없는 큰 비즈니스 응용 프로그램을 프로그래밍하는 언어로 설계.
그러나 이러한 디자인 결정은 C 언어의 버그 가 아닙니다 . 컴파일러와 라이브러리 작성자가 컴퓨터에서 모든 성능을 얻을 수 있도록 설계되어 있습니다. 다음은 C 이론 문서에서 설명 하는 C 의 정신입니다 .
C 코드는 이식 할 수 없습니다. 프로그래머가 실제로 이식 가능한 프로그램을 작성할 수있는 기회를 제공하기 위해 노력했지만위원회는 프로그래머를 이식 가능하게 작성하여 C를``고수준 어셈블러 ''로 사용하는 것을 배제하기를 원하지 않았습니다. 코드는 C의 장점 중 하나입니다.
C의 정신을 유지하십시오. 위원회 는 C 의 전통적인 정신을 보존하기위한 주요 목표로 유지했습니다. C의 정신에는 여러 가지 측면이 있지만, 본질은 C 언어의 기반이되는 기본 원칙에 대한 공동체의 정서입니다. C의 정신의 일부 측면은 다음과 같은 문구로 요약 될 수 있습니다.
- 프로그래머를 신뢰하십시오.
- 프로그래머가 수행해야 할 작업을 방해하지 마십시오.
- 언어를 작고 단순하게 유지하십시오.
- 작업을 수행하는 한 가지 방법 만 제공하십시오.
- 휴대 성이 보장되지 않더라도 빨리 만드십시오.
마지막 잠언에는 약간의 설명이 필요합니다. 효율적인 코드 생성 가능성은 C의 가장 중요한 강점 중 하나입니다. 매우 간단한 작업으로 보이는 코드 폭발이 발생하지 않도록하기 위해 많은 작업이 대상 시스템의 하드웨어가 아닌 일반적인 추상 규칙. 기계가하는 것과 함께 살려는 이러한 의지의 예는 표현식에 사용하기 위해 char 객체의 확장을 결정하는 규칙에서 볼 수 있습니다. 대상 머신에서 효율적입니다.
한 달 동안 C에서 0.05 초로 실행되는 것을 빌드하고 Java에서 동일한 것을 작성하는 데 하루를 보내고 0.10 초 안에 실행하면 C가 더 빠릅니까?
그러나 귀하의 질문에 대답하기 위해, 잘 작성된 C 코드는 일반적으로 다른 언어로 작성된 잘 작성된 코드보다 빠르게 실행됩니다. C 코드 "잘 작성"의 일부에는 기계 근처에서 수동 최적화를 수행하는 것이 포함되기 때문입니다.
컴파일러는 실제로 매우 영리하지만, 여전히 손에 의한 알고리즘과 경쟁하는 코드를 창의적으로 만들 수는 없습니다 ( "손"이 훌륭한 C 프로그래머에 속한다고 가정 ).
편집하다:
많은 의견이 "C로 작성하고 최적화에 대해서는 생각하지 않습니다."라는 문구를 따릅니다.
델파이에서는 이것을 쓸 수 있습니다 :
function RemoveAllAFromB(a, b: string): string;
var
before, after :string;
begin
Result := b;
if 0 < Pos(a,b) then begin
before := Copy(b,1,Pos(a,b)-Length(a));
after := Copy(b,Pos(a,b)+Length(a),Length(b));
Result := before + after;
Result := RemoveAllAFromB(a,Result); //recursive
end;
end;
그리고 CI에서 이것을 작성하십시오 :
char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
for (j = 0; j < len2; j++) {
if (s1[i] == s2[j]) {
break;
}
}
if (j == len2) { /* s1[i] is not found in s2 */
*result = s1[i];
result++; /* assuming your result array is long enough */
}
}
그러나 C 버전에는 얼마나 많은 최적화가 있습니까? 우리는 델파이 버전에서 생각하지 않는 구현에 대해 많은 결정을합니다. 문자열은 어떻게 구현됩니까? 델파이에서는 보이지 않습니다. C에서는 ASCII 정수 배열에 대한 포인터가 될 것이라고 결정했습니다.이 문자는 char이라고합니다. C에서는 한 번에 하나씩 문자 존재를 테스트합니다. 델파이에서는 Pos를 사용합니다.
그리고 이것은 단지 작은 예입니다. 큰 프로그램에서 C 프로그래머는 몇 줄의 코드로 이러한 종류의 낮은 수준의 결정을 내려야합니다. 수작업으로 제작 된 수작업으로 최적화 된 실행 파일을 추가합니다.
나는 그것을 보지 못 했으므로 말할 것입니다 : C는 거의 모든 것이 C로 작성되기 때문에 더 빠릅니다 .
Java는 C로, Python은 C (또는 Java 또는 .NET 등), Perl 등으로 빌드됩니다. OS는 C로 작성되고 가상 머신은 C로 작성되고 컴파일러는 C로 작성됩니다. 인터프리터는 C로 작성됩니다. 일부는 여전히 어셈블리 언어로 작성되며, 속도가 훨씬 빠릅니다. 점점 더 많은 것들이 다른 것으로 작성되고 있으며, 그 자체가 C로 작성되었습니다.
어셈블리가 아닌 다른 언어로 작성하는 각 명령문은 일반적으로 C의 여러 명령문으로 구현되며 기본 머신 코드로 컴파일됩니다. C보다 더 높은 수준의 추상화를 얻기 위해 다른 언어가 존재하는 경향이 있기 때문에 C에 필요한 추가 설명은 안전성 추가, 복잡성 추가 및 오류 처리에 중점을 두는 경향이 있습니다. 그것들은 종종 좋은 것이지만, 비용이 있으며, 그 이름은 속도 와 크기 입니다.
개인적으로, 나는 가용 한 스펙트럼의 대부분에 걸쳐 문자 그대로 수십 개의 언어로 작성했으며 개인적으로 당신이 암시하는 마술을 찾았습니다.
케이크도 먹고 먹을 수 있습니까? 내가 좋아하는 언어로 높은 수준의 추상화를 사용하여 연주하고 어떻게 C의 핵심에 빠뜨릴 수 있습니까?
몇 년의 연구 끝에 제 대답은 Python (C)입니다. 당신은 그것을보고 싶어 할 수 있습니다. 그건 그렇고, 파이썬에서 어셈블리로 드롭 다운 할 수도 있습니다 (특별 라이브러리의 약간의 도움으로).
반면에 잘못된 코드는 모든 언어로 작성할 수 있습니다 . 따라서 C (또는 어셈블리) 코드는 자동으로 더 빠르지 않습니다 . 마찬가지로 일부 최적화 트릭은 고급 언어 코드의 일부 를 원시 C의 성능 수준에 가깝게 만들 수 있습니다. 그러나 대부분의 응용 프로그램에서 프로그램은 대부분의 시간을 사람이나 하드웨어를 기다리는 데 소비하므로 차이는 중요하지 않습니다.
즐겨.
거기에는 많은 질문이 있습니다. 대부분 대답 할 자격이없는 질문입니다. 그러나이 마지막 것에는 :
다른 언어가 C만큼 빨리 실행되는 바이너리로 컴파일 할 수 없도록하는 것은 무엇입니까?
한마디로 추상화.
C는 기계어에서 한 단계 또는 두 단계의 추상화입니다. Java 및 .Net 언어는 어셈블러에서 최소 3 단계 추상화 수준에 있습니다. 파이썬과 루비에 대해 잘 모르겠습니다.
일반적으로 프로그래머 장난감 (복잡한 데이터 유형 등)이 많을수록 기계 언어에서 멀어지고 더 많은 번역을 수행해야합니다.
나는 여기 저기 있지만 기본 요점입니다.
업데이트 -------이 게시물에 대한 자세한 설명이 있습니다.
C의 비용 모델이 투명 하기 때문에 C가 빠르지는 않습니다 . C 프로그램이 느리면 많은 문을 실행함으로써 명백한 방식으로 느려집니다. C의 작업 비용과 비교하여 객체 (특히 리플렉션) 또는 문자열에 대한 높은 수준의 작업은 명확하지 않은 비용을 가질 수 있습니다.
일반적으로 C만큼 빠른 바이너리로 컴파일되는 두 가지 언어는 표준 ML ( MLton 컴파일러 사용) 및 Objective Caml 입니다. 벤치 마크 게임 을 확인하면 바이너리 트리와 같은 일부 벤치 마크의 경우 OCaml 버전이 C보다 빠릅니다 (MLton 항목을 찾지 못했습니다). 그러나 총격을 너무 심각하게 생각하지 마십시오. 그것은 게임이 말했듯이 결과는 종종 사람들이 코드를 조정하는 데 얼마나 많은 노력을 기울 였는지 반영합니다.
C가 항상 빠르지는 않습니다.
C는 예를 들어 Modern Fortran보다 느립니다.
C는 종종 Java보다 느립니다. (특히 JIT 컴파일러가 코드를 살펴본 후)
C를 사용하면 포인터 앨리어싱이 가능해 지므로 일부 최적화가 불가능합니다. 특히 여러 실행 단위가있는 경우 데이터 가져 오기가 중단됩니다. 아야
포인터 산술이 작동한다고 가정하면 실제로 일부 CPU 제품군에서 부풀린 성능이 느려집니다 (특히 PIC!) 세그먼트 x86에서 큰 것을 빨아 들였습니다.
기본적으로 벡터 장치 또는 병렬화 컴파일러를 사용하면 C 악취와 최신 Fortran이 더 빨리 실행됩니다.
썽킹 (즉시 실행 파일 수정)과 같은 C 프로그래머 트릭으로 인해 CPU 프리 페치가 중단됩니다.
당신은 드리프트를 얻을?
그리고 우리의 좋은 친구 x86은 요즘 실제 CPU 아키텍처와 거의 관계가없는 명령어 세트를 실행합니다. 섀도우 레지스터,로드 저장소 최적화 프로그램은 모두 CPU에 있습니다. 따라서 C는 가상 금속에 가깝습니다. 진짜 금속, 인텔은 당신을 보지 못하게합니다. (역사적으로 VLIW CPU는 약간의 버스트이므로 아마도 그렇게 나쁘지 않을 것입니다.)
고성능 DSP (아마도 TI DSP?)에서 C로 프로그래밍하는 경우 컴파일러는 여러 병렬 실행 장치에서 C를 풀기 위해 까다로운 작업을 수행해야합니다. 이 경우 C는 금속에 가깝지 않지만 컴파일러에 가깝기 때문에 전체 프로그램 최적화가 수행됩니다. 기묘한.
마지막으로 일부 CPU (www.ajile.com)는 하드웨어에서 Java 바이트 코드를 실행합니다. C는 PITA가 해당 CPU에서 사용할 것입니다.
다른 언어가 C만큼 빨리 실행되는 바이너리로 컴파일 할 수 없도록하는 것은 무엇입니까?
아무것도. Java 또는 .NET 언어와 같은 현대 언어는 성능보다는 프로그래머 생산성에 더 중점을 둡니다. 하드웨어는 요즘 저렴합니다. 또한 중간 표현으로 컴파일하면 보안, 이식성 등과 같은 많은 보너스가 제공됩니다. .NET CLR은 다른 하드웨어를 활용할 수 있습니다. 예를 들어 SSE 명령어 세트를 사용하기 위해 프로그램을 수동으로 최적화 / 재 컴파일 할 필요가 없습니다.
주요 요인은 정적으로 형식화 된 언어이며 기계 코드로 컴파일된다는 것입니다. 또한 저수준 언어이기 때문에 일반적으로 말하지 않은 것은 없습니다.
이것들은 생각 나는 다른 요소들입니다.
- 변수는 자동으로 초기화되지 않습니다
- 배열에 대한 경계 검사가 없습니다.
- 검사되지 않은 포인터 조작
- 정수 오버 플로우 검사 없음
- 정적 타입 변수
- 함수 호출은 정적입니다 (함수 포인터를 사용하지 않는 한)
- 컴파일러 작성자는 최적화 코드를 개선하는 데 많은 시간을 보냈습니다. 또한 사람들은 최상의 성능을 얻기 위해 C로 프로그래밍하므로 코드를 최적화해야합니다.
- 언어 사양의 일부는 구현 정의되어 있으므로 컴파일러는 가장 최적의 방법으로 자유롭게 작업을 수행 할 수 있습니다
대부분의 정적 유형 언어는 C보다 빠르거나 빠르게 컴파일 할 수 있습니다. 특히 포인터 별칭으로 인해 C가 할 수 없다고 가정 할 수있는 경우 특히 그렇습니다.
어셈블리 언어도 언어라는 것을 잊어 버린 것 같습니다 :)
그러나 진지하게, C 프로그램은 프로그래머가 자신이하는 일을 알고있을 때만 더 빠릅니다. 동일한 작업을 수행하는 다른 언어로 작성된 프로그램보다 느리게 실행되는 C 프로그램을 쉽게 작성할 수 있습니다.
C가 더 빠른 이유는 C가 이런 식으로 설계 되었기 때문입니다. 컴파일러가 코드를 최적화하는 데 도움이되는 많은 "낮은 수준"작업을 수행 할 수 있습니다. 또는 프로그래머가 코드를 최적화 할 책임이 있습니다. 그러나 종종 까다 롭고 오류가 발생하기 쉽습니다.
이미 언급 한 다른 언어와 같이 다른 언어는 프로그래머의 생산성에 더 중점을 둡니다. 프로그래머 시간은 기계 시간보다 훨씬 비싸다고 믿어집니다 (구시대에도). 따라서 프로그래머가 프로그램 실행 시간 대신 프로그램을 작성하고 디버깅하는 데 소요되는 시간을 최소화하는 것이 좋습니다. 그렇게하려면 많은 것들이 자동화되기 때문에 프로그램을 더 빨리 만들기 위해 할 수있는 일을 조금 희생해야합니다.
C ++은 평균적으로 더 빠릅니다 (처음에는 약간의 차이가 있지만 C의 상위 집합이기 때문에). 그러나 특정 벤치 마크의 경우 종종 더 빠른 다른 언어가 있습니다.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/
fannjuch-redux
스칼라에서 가장 빠른
n-body
그리고 fasta
빠른 에이다에 있었다.
spectral-norm
포트란에서 가장 빠릅니다.
reverse-complement
, mandelbrot
및 pidigits
ATS에서 가장 빠른했다.
regex-dna
JavaScript에서 가장 빠릅니다.
chameneou-redux
가장 빠른 것은 Java 7입니다.
thread-ring
Haskell에서 가장 빠릅니다.
나머지 벤치 마크는 C 또는 C ++에서 가장 빠릅니다.
나는 많은 사람들이 그것을 긴 바람으로 말했지만,
C는 덜하기 때문에 더 빠릅니다.
이러한 답변 중 많은 부분이 C가 더 빠르거나 그렇지 않은 이유에 대한 정당한 이유를 제시합니다 (일반 또는 특정 시나리오). 다음과 같은 사실은 부인할 수 없습니다.
- 다른 많은 언어들은 우리가 당연한 것으로 생각하는 자동 기능을 제공합니다. 예를 들어, 경계 검사, 런타임 유형 검사 및 자동 메모리 관리는 무료로 제공되지 않습니다. 이러한 기능과 관련된 비용 은 적어도 일부 있으며, 이러한 기능을 사용하는 코드를 작성하는 동안 생각하지 않거나 심지어 실현하지 못할 수도 있습니다.
- 소스에서 머신으로의 단계는 종종 C 에서처럼 다른 언어로 직접적이지 않습니다.
- OTOH는 컴파일 된 C 코드가 다른 언어로 작성된 다른 코드보다 빠르게 실행된다고 말하는 것은 항상 사실이 아닌 일반화입니다. 반대의 예는 쉽게 찾을 수 있습니다.
그럼에도 불구하고, 나는 다른 요소보다 C와 다른 많은 언어의 비교 성능에 더 크게 영향을 미친다는 것을 알았습니다. 재치 :
다른 언어는 종종 더 느리게 실행되는 코드를 작성하기가 더 쉽습니다. 종종 언어의 디자인 철학에 의해 장려되기도합니다. Corollary : C 프로그래머는 불필요한 작업을 수행하지 않는 코드를 작성할 가능성이 높습니다.
예를 들어, 단일 기본 창이 작성되는 간단한 Windows 프로그램을 고려하십시오. AC 버전은에 WNDCLASS[EX]
전달 될 구조를 채운 RegisterClass[Ex]
다음 CreateWindow[Ex]
메시지 루프 를 호출 하고 입력합니다. 매우 간단하고 축약 된 코드는 다음과 같습니다.
WNDCLASS wc;
MSG msg;
wc.style = 0;
wc.lpfnWndProc = &WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWndCls";
RegisterClass(&wc);
CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
C #의 동등한 프로그램은 한 줄의 코드 일 수 있습니다.
Application.Run(new Form());
이 한 줄의 코드는 거의 20 줄의 C 코드가 수행했던 모든 기능을 제공하며 오류 확인과 같은 몇 가지 기능을 추가합니다. 풍부하고 완전한 라이브러리 (일반적인 C 프로젝트에 사용 된 라이브러리와 비교)는 우리를 위해 많은 노력을 기울여 우리에게 짧아 보이지만 뒤에서 많은 단계를 포함하는 더 많은 코드 스 니펫을 작성할 시간을 자유롭게했습니다.
그러나 쉽고 빠른 코드 팽창을 가능하게하는 풍부한 라이브러리는 실제로 내 요점이 아닙니다. 우리의 작은 원 라이너가 실제로 실행될 때 실제로 일어나는 일을 검사하기 시작할 때 내 요점이 더 분명합니다. 언젠가는 재미를 위해 Visual Studio 2008 이상에서 .NET 소스 액세스 를 활성화 하고 위의 간단한 한 줄로 들어가십시오. 당신이 보게 될 재미있는 작은 보석 중 하나는 다음에 대한 getter의 주석입니다 Control.CreateParams
.
// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
//
if (createParams == null) {
createParams = new CreateParams();
}
열 번 . A의 저장 무슨의 합과 거의 비슷 정보 WNDCLASSEX
구조와 무엇에 전달 있어요 CreateWindowEx
로부터 검색되는 Control
클래스 열 시간 전에 그것이에 저장된 WNDCLASSEX
구조에 전달 RegisterClassEx
하고 CreateWindowEx
.
이 기본적인 작업을 수행하기 위해 실행되는 명령의 수는 C보다 C에서 2 ~ 3 배 더 많습니다.이 중 일부는 기능이 풍부한 라이브러리를 사용하기 때문입니다. 우리가 필요로하는 것을 정확하게 수행하는 단순한 C 코드. 그러나 그 중 일부는 .NET 프레임 워크의 모듈화 된 객체 지향적 특성이 종종 절차 적 접근 방식으로 피할 수있는 많은 반복 실행에 적합하다는 사실에 기인합니다.
C # 또는 .NET 프레임 워크를 선택하려고하지 않습니다. 또한 모듈화, 일반화, 라이브러리 / 언어 기능, OOP 등은 나쁜 것 입니다. 나는 C에서, C ++에서, 그리고 가장 최근에는 C #에서 개발의 대부분을 수행했다. 마찬가지로 C 이전에는 주로 어셈블리를 사용했습니다. 그리고 각 단계가 "더 높은"언어로 진행됨에 따라, 더 짧은 시간 내에 더 나은, 유지 보수가 가능한,보다 강력한 프로그램을 작성합니다. 그러나 그들은 조금 더 느리게 실행하는 경향이 있습니다.
Java를 제외하고 다른 컴파일러보다 C 컴파일러에 더 많은 노력을 기울 였다는 사실은 아무도 언급하지 않았다.
C는 거의 모든 다른 언어보다 이미 언급 된 여러 가지 이유로 극도로 최적화 할 수 있습니다. 따라서 다른 언어 컴파일러에 동일한 노력을 기울이면 C가 여전히 나올 것입니다.
노력보다 C보다 더 잘 최적화 할 수있는 후보 언어가 적어도 하나 있다고 생각하므로 더 빠른 이진을 생성하는 구현을 볼 수 있습니다. 제작자가 C보다 더 최적화 할 수있는 언어를 만들려고 노력했기 때문에 디지털 화성 D를 생각하고 있습니다.이 가능성이있는 다른 언어가있을 수 있습니다. 그러나 어떤 언어라도 컴파일러가 최고 C 컴파일러보다 몇 퍼센트 이상 빠를 것이라고 상상할 수 없습니다. 나는 틀리고 싶다.
실제 "낮은 교수형 과일"은 인간이 최적화하기 쉬운 언어로되어 있다고 생각합니다. 숙련 된 프로그래머는 모든 언어를 더 빠르게 만들 수 있습니다. 그러나 때로는 그렇게하기 위해 어리석은 일을하거나 부 자연스러운 구성을 사용해야합니다. 항상 노력을 기울일 것이지만, 좋은 언어는 프로그램 작성 방법을 정확하게 고집하지 않고도 비교적 빠른 코드를 생성해야합니다.
최악의 경우 코드가 빠르다는 점도 중요합니다 (적어도 나에게는). 웹에는 Java가 C보다 빠르거나 빠르다는 수많은 "증거"가 있지만 이는 체리 따기 예제를 기반으로합니다. 나는 C의 열렬한 팬은 아니지만 C로 쓰는 것은 잘 작동한다는 것을 알고 있습니다. Java를 사용하면 속도의 15 %, 보통 25 % 내에서 "아마도"실행되지만 경우에 따라 훨씬 더 나빠질 수 있습니다. 속도가 빠르거나 몇 퍼센트 이내 인 경우는 대개 어쨌든 C에 크게 최적화 된 라이브러리 코드에서 대부분의 시간을 소비하기 때문입니다.
대부분의 경우 모든 C 명령어는 매우 적은 어셈블러 명령어에 해당합니다. 기본적으로 더 높은 수준의 기계 코드를 작성하므로 프로세서가 수행하는 거의 모든 것을 제어 할 수 있습니다. C ++과 같은 다른 많은 컴파일 된 언어에는 생각보다 훨씬 더 많은 코드로 변환 할 수있는 많은 간단한 명령어가 있습니다 (가상 함수, 복사 생성자 등). Java 또는 Ruby와 같은 해석되는 언어에는 다른 계층이 있습니다. 가상 머신 또는 인터프리터
이것은 실제로 약간의 허위 사실입니다. C 프로그램이 더 빠르다는 것은 사실이지만 특히 C 프로그래머가 그다지 능숙하지 않은 경우에는 항상 그런 것은 아닙니다.
사람들이 잊어 버리는 큰 눈부신 구멍은 프로그램이 GUI 프로그램의 사용자 입력과 같은 일종의 IO를 차단해야 할 때입니다. 이러한 경우 데이터를 처리 할 수있는 속도가 아니라 데이터가 들어오는 속도에 의해 제한되므로 사용하는 언어는 중요하지 않습니다. 이 경우 C, Java, C # 또는 심지어 Perl을 사용하더라도 중요하지 않습니다. 데이터가 들어오는 것보다 더 빨리 갈 수는 없습니다.
다른 중요한 것은 가비지 수집을 사용하고 적절한 포인터를 사용하지 않으면 가상 컴퓨터가 다른 언어로는 사용할 수없는 여러 가지 최적화를 수행 할 수 있다는 것입니다. 예를 들어, JVM은 조각 모음을 위해 힙에서 오브젝트를 이동시킬 수 있습니다. 따라서 다음 인덱스를 테이블에서 찾아 보지 않고 간단히 사용할 수 있으므로 향후 할당 속도가 훨씬 빨라집니다. 최신 JVM도 실제로 메모리 할당을 해제 할 필요가 없습니다. 대신, 그들은 GC를 할 때 라이브 객체를 움직이고 죽은 객체에서 사용한 메모리는 본질적으로 무료로 복구됩니다.
이것은 또한 C에 대한 흥미로운 점을 제시하고 C ++에서는 훨씬 더 중요합니다. "필요하지 않은 경우 비용을 지불하지 않는다"는 설계 철학이 있습니다. 문제는 당신이 원한다면 코를 통해 돈을 지불하게된다는 것입니다. 예를 들어 Java의 vtable 구현은 C ++ 구현보다 훨씬 나은 경향이 있으므로 가상 함수 호출이 훨씬 빠릅니다. 반면에 Java에서 가상 기능을 사용하는 것 외에는 선택의 여지가 없으며 여전히 비용이 많이 들지만 많은 가상 기능을 사용하는 프로그램에서는 비용이 절감됩니다.
도구와 라이브러리만큼 언어에 관한 것이 아닙니다. C에 사용 가능한 라이브러리 및 컴파일러는 최신 언어보다 훨씬 오래되었습니다. 이것이 느려질 것이라고 생각할 수도 있지만 반대입니다.
이 라이브러리는 처리 능력과 메모리가 중요한 시점에 작성되었습니다. 그들은 일을하기 위해 매우 효율적 으로 작성되어야 했습니다. C 컴파일러 개발자는 다른 프로세서에 대한 모든 종류의 영리한 최적화 작업에 오랜 시간을 보냈습니다. C의 성숙도와 폭 넓은 채택으로 인해 같은 연령의 다른 언어에 비해 큰 이점이 있습니다. 또한 C만큼 필요한 원시 성능을 강조하지 않는 최신 도구보다 C에 속도 이점을 제공합니다.
The lack of abstraction is what makes C faster. If you write an output statement you know exactly what is happening. If you write an output statement in java it is getting compiled to a class file which then gets run on a virtual machine introducing a layor of abstraction. The lack of object oriented features as a part of the language also increases it's speed do to less code being generated. If you use C as an object oriented language then you are doing all the coding for things such as classes, inharitence, etc. This means rather then make something generalized enough for everyone with the amount of code and the performance penelty that requires you only write what you need to get the job done.
Amazing to see the old "C/C++ must be faster than Java because Java is interpreted" myth is still alive and kicking. There are articles going back a few years, as well as more recent ones, that explain with concepts or measurements why this simply isn't always the case.
Current virtual machine implementations (and not just the JVM, by the way) can take advantage of information gathered during program execution to dynamically tune the code as it runs, using a variety of techniques:
- rendering frequent methods to machine code,
- inlining small methods,
- adjustment of locking
and a variety of other adjustments based on knowing what the code is actually doing, and on the actual characteristics of the environment in which it's running.
The fastest running code would be carefully hand crafted machine code. Assembler will be almost as good. Both are very low level and it takes a lot of writing code to do things. C is a little above assembler. You still have the ability to control things at a very low level in the actual machine, but there is enough abstraction make writing it faster and easier then assembler. Other languages such as C# and JAVA are even more abstract. While Assembler and machine code are called low level languages, C# and JAVA (and many others) are called high level languages. C is sometimes called a middle level language.
Back in the good ole days, there were just two types of languages: compiled and interpreted.
Compiled languages utilized a "compiler" to read the language syntax and convert it into identical assembly language code, which could than just directly on the CPU. Interpreted languages used a couple of different schemes, but essentially the language syntax was converted into an intermediate form, and then run in a "interpreter", an environment for executing the code.
Thus, in a sense, there was another "layer" -- the interpreter -- between the code and the machine. And, as always the case in a computer, more means more resources get used. Interpreters were slower, because they had to perform more operations.
More recently, we've seen more hybrid languages like Java, that employ both a compiler and an interpreter to make them work. It's complicated, but a JVM is faster, more sophisticated and way more optimized than the old interpreters, so it stands a much better change of performing (over time) closer to just straight compiled code. Of course, the newer compilers also have more fancy optimizing tricks so they tend to generate way better code than they used to as well. But most optimizations, most often (although not always) make some type of trade-off such that they are not always faster in all circumstances. Like everything else, nothing comes for free, so the optimizers must get their boast from somewhere (although often times it using compile-time CPU to save runtime CPU).
Getting back to C, it is a simple language, that can be compiled into fairly optimized assembly and then run directly on the target machine. In C, if you increment an integer, it's more than likely that it is only one assembler step in the CPU, in Java however, it could end up being a lot more than that (and could include a bit of garbage collection as well :-) C offers you an abstraction that is way closer to the machine (assembler is the closest), but you end up having to do way more work to get it going and it is not as protected, easy to use or error friendly. Most other languages give you a higher abstraction and take care of more of the underlying details for you, but in exchange for their advanced functionality they require more resources to run. As you generalize some solutions, you have to handle a broader range of computing, which often requires more resources.
Paul.
Don't take someones word for it, look at the dissassembly for both C and your language-of-choice in any performance critical part of your code. I think you can just look in the disassembly window at runtime in Visual Studio to see disassembled .Net. Should be possible if tricky for Java using windbg, though if you do it with .Net many of the issues would be the same.
I don't like to write in C if I don't need to, but I think many of the claims made in these answers that tout the speed of languages other than C can be put aside by simply disassembling the same routine in C and in your higher level language of choice, especially if lots of data is involved as is common in performance critical applications. Fortran may be an exception in its area of expertise, don't know. Is it higher level than C?
First time I did compared JITed code with native code resolved any and all questions whether .Net code could run comparably to C code. The extra level of abstraction and all the safety checks come with a significant cost. Same costs would probably apply to Java, but don't take my word for it, try it on something where performance is critical. (Anyone know enough about JITed Java to locate a compiled procedure in memory? It should certainly be possible)
I have found an Answer on link about why some languages are faster and some are slower, I hope this will clear more about why C or C++ is faster than others, There are some other languages also that is faster than C, but we can not use all of them. Some explaination -
One of the big reasons that Fortran remains important is because it's fast: number crunching routines written in Fortran tend to be quicker than equivalent routines written in most other languages. The languages that are competing with Fortran in this space—C and C++—are used because they're competitive with this performance.
This raises the question: why? What is it about C++ and Fortran that make them fast, and why do they outperform other popular languages, such as Java or Python?
Interpreting versus compiling There are many ways to categorize and define programming languages, according to the style of programming they encourage and features they offer. When looking at performance, the biggest single distinction is between interpreted languages and compiled ones.
The divide is not hard; rather, there's a spectrum. At one end, we have traditional compiled languages, a group that includes Fortran, C, and C++. In these languages, there is a discrete compilation stage that translates the source code of a program into an executable form that the processor can use.
This compilation process has several steps. The source code is analyzed and parsed. Basic coding mistakes such as typos and spelling errors can be detected at this point. The parsed code is used to generate an in-memory representation, which too can be used to detect mistakes—this time, semantic mistakes, such as calling functions that don't exist, or trying to perform arithmetic operations on strings of text.
This in-memory representation is then used to drive a code generator, the part that produces executable code. Code optimization, to improve the performance of the generated code, is performed at various times within this process: high-level optimizations can be performed on the code representation, and lower-level optimizations are used on the output of the code generator.
Actually executing the code happens later. The entire compilation process is simply used to create something that can be executed.
At the opposite end, we have interpreters. The interpreters will include a parsing stage similar to that of the compiler, but this is then used to drive direct execution, with the program being run immediately.
The simplest interpreter has within it executable code corresponding to the various features the language supports—so it will have functions for adding numbers, joining strings, whatever else a given language has. As it parses the code, it will look up the corresponding function and execute it. Variables created in the program will be kept in some kind of lookup table that maps their names to their data.
The most extreme example of the interpreter style is something like a batch file or shell script. In these languages, the executable code is often not even built into the interpreter itself, but rather separate, standalone programs.
So why does this make a difference to performance? In general, each layer of indirection reduces performance. For example, the fastest way to add two numbers is to have both of those numbers in registers in the processor, and to use the processor's add instruction. That's what compiled programs can do; they can put variables into registers and take advantage of processor instructions. But in interpreted programs, that same addition might require two lookups in a table of variables to fetch the values to add, then calling a function to perform the addition. That function may very well use the same processor instruction as the compiled program uses to perform the actual addition, but all the extra work before the instruction can actually be used makes things slower.
If you want to know more please check the Source
Some C++ algorithms are faster than C, and some implementations of algorithms or design patterns in other languages can be faster than C.
When people say that C is fast, and then move on to talking about some other language, they are generally using C's performance as a benchmark.
With modern optimizing compilers, it's highly unlikely that a pure C program is going to be all that much faster than compiled .net code, if at all. With the productivity enhancement that frameworks like .net provide the developer, you can do things in a day that used to take weeks or months in regular C. Coupled with the cheap cost of hardware compared to a developer's salary, it's just WAY cheaper to write the stuff in a high-level language and throw hardware at any slowness.
The reason Jeff and Joel talk about C being the "real programmer" language is because there is no hand-holding in C. You must allocate your own memory, deallocate that memory, do your own bounds-checking, etc. There's no such thing as new object(); There's no garbage collection, classes, OOP, entity frameworks, LINQ, properties, attributes, fields, or anything like that. You have to know things like pointer arithmetic and how to dereference a pointer. And, for that matter, know and understand what a pointer is. You have to know what a stack frame is and what the instruction pointer is. You have to know the memory model of the CPU architecture you're working on. There is a lot of implicit understanding of the architecture of a microcomputer (usually the microcomputer you're working on) when programming in C that simply is not present nor necessary when programming in something like C# or Java. All of that information has been off-loaded to the compiler (or VM) programmer.
1) As others have said, C does less for you. No initializing variables, no array bounds checking, no memory management, etc. Those features in other languages cost memory and CPU cycles that C doesn't spend.
2) Answers saying that C is less abstracted and therefore faster are only half correct I think. Technically speaking, if you had a "sufficiently advanced compiler" for language X, then language X could approach or equal the speed of C. The difference with C is that since it maps so obviously (if you've taken an architecture course) and directly to assembly language that even a naive compiler can do a decent job. For something like Python, you need a very advanced compiler to predict the probable types of objects and generate machine code on the fly -- C's semantics are simple enough that a simple compiler can do well.
It's the difference between automatic and manual, higher level languages are abstractions thus automated. C/C++ are manually controlled and handled, even error checking code is sometimes a manual labor.
C and C++ are also compiled languages which means none of that run everywhere business, these languages have to be fine tuned for the hardware you work with thus adding an extra layer of gotcha. Though this is slightly fazing out now as C/C++ compilers are becoming more common across all platforms. You can do cross compilations between platforms. It's still not a run everywhere situation, your basically instructing compiler A to compile against compiler B same code different architecture.
Bottom line C languages are not meant to be easy to understand or reason, this is also why their referred to as systems languages. They came out before all this high level abstraction nonsense. This is also why they are not used for front end web programming. Their just not suited to the task, their mean to solve complex problems that can't be resolved with conventional language tooling.
This is why you get crazy stuff like (micro-architectures, drivers, quantum physics, AAA Games, operating systems) there are things C and C++ are just well suited for. Speed and number crunching being the chief areas.
Setting aside advanced optimization techniques such as hot-spot optimization, pre-compiled meta-algorithms, and various forms of parallelism, the fundamental speed of a language correlates strongly with the implicit behind-the-scenes complexity required to support the operations that would commonly be specified within inner loops.
Perhaps the most obvious is validity checking on indirect memory references -- such as checking pointers for null
and checking indexes against array boundaries. Most high-level languages perform these checks implicitly, but C does not. However, this is not necessarily a fundamental limitation of these other languages -- a sufficiently clever compiler may be capable of removing these checks from the inner loops of an algorithm through some form of loop-invariant code motion.
The more fundamental advantage of C (and to a similar extent the closely related C++) is a heavy reliance on stack-based memory allocation, which is inherently fast for allocation, deallocation, and access. In C (and C++) the primary call stack can be used for allocation of primitives, arrays, and aggregates (struct
/class
).
While C does offer the capability to dynamically allocate memory of arbitrary size and lifetime (using the so called 'heap'), doing so is avoided by default (the stack is used instead).
Tantalizingly, it is sometimes possible to replicate the C memory allocation strategy within the runtime environments of other programming languages. This has been demonstrated by asm.js, which allows code written in C or C++ to be translated into a subset of JavaScript and run safely in a web browser environment -- with near-native speed.
As somewhat of an aside, another area where C and C++ outshine most other languages for speed is the ability to seamlessly integrate with native machine instruction sets. A notable example of this is the (compiler and platform dependent) availability of SIMD intrinsics which support the construction of custom algorithms that take advantage of the now nearly ubiquitous parallel processing hardware -- while still utilizing the data allocation abstractions provided by the language (lower-level register allocation is managed by the compiler).
C is fast because it is Natively compiled, low-level language. But C is not the fastest. The Recursive Fibonacci Benchmark shows that Rust, Crystal, and Nim can be faster.
Even the difference between C and C++ can at times be great.
When you are allocating memory for an object, invoking constructors, aligning memory on word boundaries, etc. the program winds up going through a lot of overhead that is abstracted away from the programmer.
C forces you to take a look at each thing that your program is doing, generally at a very fine level of detail. This makes it harder (although not by any means impossible) to write code that does a lot of tasks that are unnecessary to the immediate goal at hand.
So where in, for instance a BASIC program you would use the INPUT keyword to read a string form STDIN and automatically allocate memory for its variable, in C the programmer will typically have already allocated memory and can control things like whether the program blocks for I/O or not, and if it stops reading input after it has the information it needs or continues reading characters to the end of the line.
C also performs a lot less error-checking than other languages, presuming the programmer knows what they're doing. So whereas in PHP if you declare a string $myStr = getInput();
and go on to reference $myStr[20]
, but the input was only 10 characters long, PHP will catch this and safely return to you a blank string. C assumes that you've either allocated enough memory to hold data past the end of the string or that you know what information comes after the string and are trying to reference that instead. These small factors have a huge impact on overhead in aggregate.
'IT story' 카테고리의 다른 글
NSUserDefaults-키가 있는지 확인하는 방법 (0) | 2020.05.07 |
---|---|
Ruby 배열에서 평균을 만들려면 어떻게합니까? (0) | 2020.05.07 |
PHP에서 이메일 주소를 확인하는 방법 (0) | 2020.05.07 |
fgets () 입력에서 후행 줄 바꿈 문자 제거 (0) | 2020.05.07 |
HTML로 다운로드 링크를 만들려면 어떻게해야합니까? (0) | 2020.05.07 |