C ++ / R과 같은 프로그래밍 언어로 작성된 일부 응용 프로그램이나 알고리즘은 동일한 컴퓨터에서 실행되는 Java / Node.js와 같은 것보다 더 빠르거나 빠르게 실행됩니다. 이것에 관한 몇 가지 질문이 있습니다.
- 왜 이런 일이 발생합니까?
- 프로그래밍 언어의 "속도"는 무엇입니까?
- 메모리 관리와 관련이 있습니까?
누군가 나를 위해 이것을 무너 뜨렸다면 정말 감사하겠습니다.
C ++ / R과 같은 프로그래밍 언어로 작성된 일부 응용 프로그램이나 알고리즘은 동일한 컴퓨터에서 실행되는 Java / Node.js와 같은 것보다 더 빠르거나 빠르게 실행됩니다. 이것에 관한 몇 가지 질문이 있습니다.
누군가 나를 위해 이것을 무너 뜨렸다면 정말 감사하겠습니다.
답변:
프로그래밍 언어 설계 및 구현에는 성능에 영향을 줄 수있는 많은 선택이 있습니다. 몇 가지만 언급하겠습니다.
모든 언어는 궁극적으로 머신 코드를 실행하여 실행해야합니다. C ++과 같은 "컴파일 된"언어는 컴파일 타임에 한 번만 구문 분석, 디코딩 및 머신 코드로 변환됩니다. "통역 된"언어는 직접 방식으로 구현되는 경우 런타임에 모든 단계에서 매번 디코딩됩니다. 즉, 우리가 문장을 실행할 때마다 인터프리터는 그것이 if-then-else인지 할당인지 등을 확인하고 그에 따라 행동해야합니다. 즉, 100 번 반복하면 동일한 코드를 100 번 디코딩하여 시간을 낭비하게됩니다. 다행스럽게도 통역사는 종종 JIT (Just-In-Time) 컴파일 시스템을 통해이를 최적화합니다. 더 정확하게는 "컴파일 된"또는 "해석 된"언어와 같은 것은 없습니다. 언어가 아닌 구현의 속성입니다.
다른 컴파일러 / 인터프리터는 다른 최적화를 수행합니다.
언어에 자동 메모리 관리 기능이 있으면 구현시 가비지 수집을 수행해야합니다. 이는 런타임 비용이 들지만 프로그래머는 오류가 발생하기 쉬운 작업에서 벗어날 수 있습니다.
언어가 기계에 더 가까워서 전문 프로그래머가 모든 것을 미세 최적화하고 CPU에서 더 많은 성능을 끌어낼 수 있습니다. 그러나 대부분의 프로그래머는 실제로 마이크로 최적화하지 않기 때문에 실제 프로그래머에게 실제로 유익한 지 여부는 논쟁의 여지가 있으며, 보통 프로그래머가하는 것보다 우수한 고급 언어를 컴파일러가 더 잘 최적화 할 수 있습니다. (그러나 때때로 기계에서 멀어지면 이점도있을 수 있습니다! 예를 들어, Haskell의 레벨은 매우 높지만 디자인 선택 덕분에 매우 가벼운 녹색 스레드가 가능합니다.)
정적 유형 검사는 최적화에 도움이 될 수 있습니다. 동적으로 형식화되고 해석되는 언어에서, 계산할 때마다 x - y
통역사는 종종 둘 다 x,y
숫자 인지 확인 하고 (예) 그렇지 않으면 예외를 발생시켜야합니다. 컴파일 타임에 유형을 이미 확인한 경우이 확인을 건너 뛸 수 있습니다.
일부 언어는 항상 런타임 오류를 제정신으로보고합니다. 요소가 20 개만 a[100]
있는 Java로 작성 a
하면 런타임 예외가 발생합니다. C에서, 그 프로그램이 충돌 메모리에 어떤 임의의 데이터를 덮어, 또는 수행 할 수 있다는 것을 의미 정의되지 않은 동작이 발생할 것이라고 절대적으로 아무것도 다른 사람을 (ISO C 표준은 어떠한 한계를 제기하지 않음). 이를 위해서는 런타임 검사가 필요하지만 프로그래머에게 훨씬 더 좋은 의미를 제공합니다.
그러나 언어를 평가할 때 성능이 전부는 아닙니다. 그것에 집착하지 마십시오. 모든 것을 미세 최적화하려고 시도하지만 비효율적 인 알고리즘 / 데이터 구조가 사용되고 있다는 것을 발견하지 못하는 것이 일반적인 함정입니다. 크 누스는 한때 "조기 최적화는 모든 악의 근원"이라고 말했다.
프로그램을 올바르게 작성하는 것이 얼마나 어려운지 과소 평가하지 마십시오 . 보다 인간 친화적 인 의미를 갖는 "느린"언어를 선택하는 것이 더 나은 경우가 많습니다. 또한 성능에 중요한 특정 부분이 있으면 다른 언어로 항상 구현할 수 있습니다. 참고로 2016 ICFP 프로그래밍 콘테스트 에서 우승자가 사용한 언어는 다음과 같습니다.
1 700327 Unagi Java,C++,C#,PHP,Haskell
2 268752 天羽々斬 C++, Ruby, Python, Haskell, Java, JavaScript
3 243456 Cult of the Bound Variable C++, Standard ML, Python
그들 중 누구도 단일 언어를 사용하지 않았습니다.
프로그래밍 언어의 "속도"는 무엇입니까?
프로그래밍 언어의 "속도"와 같은 것은 없습니다. 특정 환경 내에서 실행되는 특정 실행 엔진의 특정 구현의 특정 버전에 의해 실행되는 특정 프로그램에 의해 작성된 특정 프로그램의 속도 만이있다.
서로 다른 구현을 사용하여 동일한 컴퓨터에서 동일한 언어로 작성된 동일한 코드를 실행하면 성능이 크게 달라질 수 있습니다. 또는 동일한 구현의 다른 버전을 사용하는 경우도 있습니다. 예를 들어, 10 년 전 SpiderMonkey 버전을 사용하여 정확히 동일한 시스템에서 정확히 동일한 ECMAScript 벤치 마크를 실행하면 올해 버전보다 2 배에서 5 배 사이, 심지어 10 배까지 성능이 향상 될 수 있습니다. 그렇다면 동일한 시스템에서 동일한 프로그램을 실행하면 최신 구현에서 2 배 더 빠르기 때문에 ECMAScript가 ECMAScript보다 2 배 빠릅니다. 말이되지 않습니다.
메모리 관리와 관련이 있습니까?
실제로는 아닙니다.
왜 이런 일이 발생합니까?
자원. 돈. 아마도 전체 PHP, Ruby 및 Python 커뮤니티가 VM에서 일하는 사람들보다 컴파일러 프로그래머를 위해 커피를 만드는 사람들이 더 많을 것입니다.
어떤 식 으로든 성능에 영향을 미치는 프로그래밍 언어의 기능에 대한 해결책도 있습니다. 예를 들어, C (여기서는 C 이전에도 존재했던 유사한 언어 클래스의 스탠드 인으로 C를 사용하고 있습니다)는 메모리에 안전하지 않기 때문에 동시에 실행되는 여러 C 프로그램이 중단 될 수 있습니다. 서로의 기억. 따라서 우리는 가상 메모리를 발명하고 모든 C 프로그램이 간접 계층을 거치도록하여 머신에서 실행되는 유일한 척이라고 할 수 있습니다. 그러나 속도가 느리므로 MMU를 발명하고 하드웨어에 가상 메모리를 구현하여 속도를 높입니다.
그러나! 메모리 안전 언어는 그다지 필요하지 않습니다! 가상 메모리가 있다고해서 1 비트에 도움이되지는 않습니다. 실제로, 더 나쁘다 : 가상 메모리는 메모리 안전 언어, 가상 메모리를 하드웨어에 구현할 때에도 도움이되지 않을뿐만 아니라 여전히 성능에 영향을 미친다. 가비지 수집기의 성능에 특히 해를 끼칠 수 있습니다 (메모리 보호 언어의 많은 구현이 사용함).
또 다른 예 : 최신 주류 범용 CPU는 캐시 미스 빈도를 줄이기 위해 정교한 트릭을 사용합니다. 이러한 트릭의 많은 부분은 앞으로 어떤 코드가 실행 될지, 어떤 메모리가 필요할지 예측하려고합니다. 그러나 런타임 다형성이 높은 언어 (예 : OO 언어)의 경우 이러한 액세스 패턴을 예측하기가 실제로 어렵습니다.
그러나 또 다른 방법이 있습니다. 총 캐시 미스 비용은 캐시 미스 수에 개별 캐시 미스 비용을 곱한 것입니다. 주류 CPU는 미스 수를 줄이려고하지만 개별 미스 비용을 줄일 수 있다면 어떨까요?
Azul Vega-3 CPU는 가상화 된 JVM을 실행하기 위해 특별히 설계되었으며 가비지 수집 및 이스케이프 감지 (정적 이스케이프 분석과 동적 인 동적) 및 강력한 메모리 컨트롤러 및 전체 시스템을 돕는 특수 지침이 포함 된 매우 강력한 MMU가있었습니다. 여전히 비행 중 20000 개 이상의 미해결 캐시 미스로 진행할 수 있습니다. 불행히도, 대부분의 언어 별 CPU와 마찬가지로, 그 디자인은 단순히 "거대"인텔, AMD, IBM 등의 사람들에 의해 소비되고 무차별 적으로 시행되었습니다.
CPU 아키텍처는 언어의 고성능 구현이 얼마나 쉽고 얼마나 어려운지에 영향을주는 하나의 예일 뿐입니다 . 현대의 메인 스트림 CPU 프로그래밍 모델에 적합한 C, C ++, D, Rust와 같은 언어는 Java, ECMAScript, Python, Ruby와 같이 CPU를 "싸우고"우회해야하는 언어보다 더 쉽게 만들 수 있습니다. PHP.
실제로, 그것은 모두 돈 문제입니다. ECMAScript에서 고성능 알고리즘을 개발하기 위해 동일한 비용을 지출하는 경우, ECMAScript를 위해 설계된 고성능 운영 체제 인 ECMAScript의 고성능 구현 인 ECMAScript로 고성능 알고리즘을 개발하는 경우 C와 같은 언어를 빠르게 사용하기 위해 수십 년이 걸리면 성능이 동일 할 것입니다. 지금은 ECMAScript와 같은 언어를 빠르게 만드는 것보다 C와 같은 언어를 빠르게 만드는 데 더 많은 돈이 소비되었으며, C와 같은 언어의 가정은 MMU와 CPU에서 운영 체제 및 라이브러리 및 프레임 워크까지 가상 메모리 시스템.
개인적으로 저는 루비 (일반적으로 "느린 언어"로 간주 됨)에 대해 가장 잘 알고 있으므로 두 가지 예를 Hash
들겠습니다. 루비니 우스 의 클래스 (루비의 중앙 데이터 구조 중 하나, 키-값 사전) 루비 구현은 100 % 순수 루비로 작성되었으며,Hash
C로 작성된 YARV (가장 널리 사용되는 구현)의 클래스입니다. 그리고 YARV의 C 확장으로 작성된 이미지 조작 라이브러리가 있으며,이 구현을위한 (느린) 순수한 Ruby "fallback version"도 있습니다. 다이나믹하고 반사적 인 루비 트릭을 사용하는 C는 지원하지 않습니다. Oracle Labs의 Truffle AST 인터프리터 프레임 워크 및 Graal JIT 컴파일 프레임 워크를 활용하는 JRuby의 실험 브랜치는 YARV가 최적화 된 원본 C 버전을 실행할 수있는 한 빠른 순수 루비 "폴백 버전"을 실행할 수 있습니다. 이것은 동적 런타임 최적화, JIT 컴파일 및 부분 평가를 통해 정말 영리한 작업을 수행하는 일부 영리한 사람들에 의해 달성됩니다.
int
파이썬이 사용하는 정수와 같은 무한정 정수가 수학적으로 훨씬 자연 스럽다는 사실에도 불구하고 C는 성능상의 이유로 고정 크기를 선택했습니다 . 하드웨어에서 무제한 정수를 구현하는 것은 고정 크기 정수만큼 빠르지는 않습니다. 구현 세부 사항을 숨기려고하는 언어는 순진한 C 구현에 가깝게하려면 복잡한 최적화가 필요합니다.
이론적으로 두 언어로 정확히 동일한 코드를 작성하고 "완벽한"컴파일러를 사용하여 두 언어를 컴파일하는 경우 두 성능 모두 동일해야합니다.
실제로 성능이 달라지는 몇 가지 이유가 있습니다.
일부 언어는 최적화하기가 더 어렵습니다.
여기에는 특히 코드를 더 동적으로 만드는 기능 (동적 타이핑, 가상 메서드, 함수 포인터)뿐만 아니라 가비지 수집과 같은 기능도 포함됩니다.
이러한 기능을 사용하여 코드를 빠르게 만드는 방법에는 여러 가지가 있지만 일반적으로 사용하지 않는 것보다 약간 느립니다.
일부 언어 구현은 런타임에 일부 컴파일을 수행해야합니다.
이는 Java와 같은 가상 머신이있는 언어 및 JavaScript와 같은 2 진 단계가없는 소스 코드를 실행하는 언어에 특히 적용됩니다.
이러한 언어 구현은 런타임시 더 많은 작업을 수행해야하므로 성능, 특히 시작 직후 시작 시간 / 성능에 영향을줍니다.
언어 구현은 의도적으로 최적화에 더 적은 시간을 소비합니다.
모든 컴파일러는 생성 된 코드뿐만 아니라 컴파일러 자체의 성능도 중요합니다. 컴파일에 너무 오래 걸리면 응용 프로그램 실행 속도가 느려지는 런타임 컴파일러 (JIT 컴파일러)에 특히 중요합니다. 그러나 C ++ 용 컴파일러와 같은 사전 컴파일러에 적용됩니다. 예를 들어 레지스터 할당 은 NP- 완전한 문제이므로 완벽하게 해결하는 것은 현실적이지 않으며 합리적인 시간에 실행되는 휴리스틱이 사용됩니다.
다른 언어의 관용구의 차이점.
공통 라이브러리를 사용하여 특정 언어 (아이디 오 코드)에 공통적 인 스타일로 작성된 코드는 이러한 언어 코드가 각 언어에서 미묘하게 다르게 작동하기 때문에 성능 차이가 발생할 수 있습니다.
예를 들어 vector[i]
C ++, list[i]
C # 및 list.get(i)
Java를 고려하십시오. C ++ 코드는 범위 검사를 수행하지 않고 가상 호출을 수행하지 않으며, C # 코드는 범위 검사를 수행하지만 가상 호출을 수행하지 않으며 Java 코드는 범위 검사를 수행하며 가상 호출입니다. 세 가지 언어 모두 가상 및 비가 상 메서드를 지원하며 C ++ 및 C #은 범위 검사를 포함하거나 기본 배열에 액세스 할 때 범위 검사를 피할 수 있습니다. 그러나 이러한 언어의 표준 라이브러리는 이와 동등한 기능을 다르게 작성하기로 결정했으며 결과적으로 성능이 다릅니다.
일부 컴파일러에는 일부 최적화가 누락되었을 수 있습니다.
컴파일러 작성자는 리소스가 한정되어 있으므로 가능한 모든 최적화를 구현할 수 없으며 다른 문제는 무시해도됩니다. 그리고 그들이 보유한 자원은 다른 영역보다 한 가지 최적화 영역에 초점을 맞출 수 있습니다. 결과적으로 한 언어가 다른 언어보다 더 빠르거나 최적화하기 쉬운 근본적인 이유가 없더라도 다른 언어로 작성된 코드는 컴파일러의 차이로 인해 다른 성능을 가질 수 있습니다.
이것은 매우 일반적인 질문이지만 귀하의 경우 대답은 간단 할 수 있습니다. C ++는 Java가 Java 바이트 코드로 컴파일되는 Java 코드를 컴파일하고 Java 가상 머신을 실행하는 머신 코드로 컴파일합니다. 또 다른 차이점은 가비지 수집 일 수 있는데, 이는 Java 만 제공하는 서비스입니다.
귀하의 질문이 너무 일반적이므로 귀하가 필요한 정확한 답변을 드릴 수 없습니다.
최선의 설명을 위해 C ++ 및 .Net 플랫폼을 살펴 보겠습니다.
C ++은 머신 코드에 매우 가깝고 성능 때문에 예전 10 년 이상 전에 선호되는 프로그래밍 중 하나입니다. IDE에서도 C ++ 프로그램을 개발하고 실행하는 데 필요한 리소스는 많지 않으며 매우 가볍고 빠릅니다. 콘솔에서 C ++ 코드를 작성하고 거기서 게임을 개발할 수도 있습니다. 메모리와 리소스 측면에서 컴퓨터의 용량은 대략 잊었지만 용량은 현재 세대의 프로그래밍 언어와 비교할 수없는 것입니다.
이제 .Net을 보자. .Net 개발을 수행하기위한 전제 조건은 한 가지 유형의 프로그래밍 언어가 아닌 거대한 IDE입니다. C #으로 개발자를 개발하려는 경우에도 IDE 자체에는 기본적으로 J #, VB, 모바일 등과 같은 많은 프로그래밍 플랫폼이 기본적으로 포함됩니다. IDE 설치를 충분히 경험할 수 있다면 사용자 정의 설치를하지 않고 원하는 것을 정확하게 설치하지 않는 한.
.Net에는 IDE 소프트웨어 자체를 설치하는 것 외에도 개발자가 필요로하고 필요로하지 않는 모든 종류의 플랫폼에 쉽게 액세스 할 수 있도록 대용량의 라이브러리 및 프레임 워크가 제공됩니다.
기본적으로 많은 공통 기능과 구성 요소를 사용할 수 있으므로 .Net에서 개발하는 것은 재미있는 경험이 될 수 있습니다. IDE에서 많은 유효성 검사 방법, 파일 읽기, 데이터베이스 액세스 등을 끌어서 놓을 수 있습니다.
결과적으로, 그것은 컴퓨터 자원과 개발 속도 사이의 상충 관계입니다. 이러한 라이브러리와 프레임 워크는 메모리와 리소스를 차지합니다. .Net IDE에서 프로그램을 실행하면 라이브러리, 구성 요소 및 모든 파일을 컴파일하는 데 많은 시간이 걸릴 수 있습니다. 또한 디버깅을 수행 할 때 IDE에서 디버깅 프로세스를 관리하려면 컴퓨터에 많은 리소스가 필요합니다.
일반적으로 .Net 개발을 수행하려면 일부 Ram 및 프로세서가 장착 된 우수한 컴퓨터가 필요합니다. 그렇지 않으면 프로그래밍하지 않을 수도 있습니다. 이 측면에서 C ++ 플랫폼은 .Net보다 훨씬 낫습니다. 여전히 좋은 컴퓨터가 필요하지만 .Net에 비해 용량에 큰 관심이 없습니다.
내 답변이 귀하의 질문에 도움이되기를 바랍니다. 더 알고 싶다면 알려주세요.
편집하다:
내 요점을 간단히 설명하기 위해 주로 "프로그래밍 속도를 제어하는 것은 무엇입니까"라는 질문에 대답합니다.
IDE 관점에서, 상대 IDE에서 C ++ 또는 .Net 언어를 사용하는 것은 코드 작성 속도에 영향을 미치지 않지만 Visual Studio 컴파일러가 프로그램을 실행하는 데 시간이 오래 걸리기 때문에 개발 속도에 영향을 미치지 만 C ++ IDE는 훨씬 가볍습니다. 적은 컴퓨터 리소스를 소비합니다. 따라서 장기적으로 라이브러리 및 프레임 워크에 크게 의존하는 .Net IDE와 비교하여 C ++ 유형의 IDE로 프로그래밍 속도를 높일 수 있습니다. IDE 시작, 컴파일, 프로그램 실행 등을 기다리는 시간이 걸리면 프로그래밍 속도에 영향을 미칩니다. "프로그래밍 속도"가 실제로 "코드 작성 속도"에만 초점을 맞추지 않는 한.
Visual Studio의 라이브러리 및 프레임 워크도 컴퓨터 용량을 소비합니다. 이것이 "메모리 관리"에 관한 질문인지는 확실하지 않지만 Visual Studio IDE를 실행할 때 많은 리소스를 소비 할 수 있으므로 전반적인 "프로그래밍 속도"가 느려질 수 있습니다. 물론 이것은 "코드 작성 속도"와 관련이 없습니다.
당신이 짐작했듯이, 나는 단지 예제로 사용하기 때문에 너무 많은 C ++을 모른다. 내 주요 요점은 컴퓨터 리소스를 소비하는 Visual Studio 유형의 무거운 IDE에 관한 것이다.
아이디어를 얻었고 스레드 시작 질문에 전혀 대답하지 않았다면 긴 게시물에 대해 사과드립니다. 그러나 나는 스레드 스타터에게 질문을 명확하게하고 "빠르고"느리게 알아야 할 것이 무엇인지 정확하게 물어 보라고 조언합니다.