자바는 속도가 느리다는 명성을 가지고있다 .
- 자바는 정말 느리다?
- 그렇다면 왜 그렇습니까? 병목 현상은 어디에 있습니까? 비효율적 인 JVM 때문입니까? 쓰레기 수거? JNI 랩 C 코드 대신 순수한 바이트 코드 라이브러리? 다른 많은 언어들에도 이러한 기능이 있지만 속도 저하에 대한 명성은 없습니다.
답변
현대 Java는 여전히 메모리 호그이지만 가장 빠른 언어 중 하나입니다. Java 는 VM을 시작하는 데 오랜 시간이 걸리기 때문에 느리게 명성을 얻었습니다.
여전히 Java가 느리다고 생각 되면 벤치 마크 게임 결과를 참조하십시오 . 미리 컴파일 된 언어 (C, Fortran 등)로 작성된 엄격하게 최적화 된 코드가 이길 수 있습니다. 그러나 Java는 PHP, Ruby, Python 등보다 10 배 이상 빠를 수 있습니다. 일반적인 컴파일 된 언어 (표준 라이브러리를 사용하는 경우)를 능가 할 수있는 특정 영역이 있습니다.
“느린”Java 응용 프로그램에 대한 변명의 여지가 없습니다. 개발자와 레거시 코드 / 라이브러리는 언어보다 훨씬 더 많은 책임이 있습니다. 또한 ‘기업’을 비난합니다.
“자바는 느리다”군중에 공평하게, 여기에는 여전히 느리다 (2013 년 업데이트).
-
라이브러리는 종종 성능이 아니라 “정확성”및 가독성을 위해 작성됩니다. 제 생각에는 이것이 자바가 여전히 평판이 좋지 않은 주된 이유, 특히 서버 측입니다. 이것은 문자열 문제를 기하 급수적으로 악화시킵니다. 몇 가지 간단한 실수가 일반적입니다. 객체는 기본 요소 대신 자주 사용되므로 성능이 떨어지고 메모리 사용이 증가합니다. 표준 라이브러리를 포함한 많은 Java 라이브러리는 변경 가능하거나 간단한 형식 (char [] 또는 StringBuffer)을 재사용하지 않고 문자열을 자주 만듭니다. 속도가 느리고 나중에 수거 할 쓰레기가 많이 발생합니다. 이 문제를 해결하기 위해 개발자는 가능한 경우 기본 컬렉션과 특히 Javalution의 라이브러리를 사용하는 것이 좋습니다.
-
문자열 연산이 약간 느립니다. Java는 불변의 UTF-16 인코딩 문자열 객체를 사용합니다. 즉, ASCII (C, C ++)보다 더 많은 메모리, 더 많은 메모리 액세스가 필요하며 일부 작업이 더 복잡합니다. 당시에는 이식성 에 대한 올바른 결정 이었지만 성능 비용이 약간 듭니다. UTF-8 은 이제 더 나은 선택처럼 보입니다.
-
범위 검사로 인해 C에 비해 배열 액세스가 약간 느립니다 . 벌금은 커졌지 만 이제는 작습니다 (Java 7은 많은 중복 범위 검사를 최적화합니다).
-
임의 메모리 액세스가 부족하면 일부 I / O 및 비트 수준 처리 속도가 느려질 수 있습니다 (예 : 압축 / 압축 해제). 이것은 현재 대부분의 고급 언어의 안전 기능입니다.
-
Java는 C보다 많은 메모리를 사용하며 응용 프로그램이 메모리 바운드 또는 메모리 대역폭 바운드 (캐싱 등) 인 경우 속도가 느려집니다. 단점은 할당 / 할당 해제 속도가 매우 빠르다는 것입니다 (최적화 됨). 이것은 현재 대부분의 고급 언어의 기능이며, 명시 적 메모리 할당이 아닌 객체 및 GC 사용으로 인해 발생합니다 . 잘못된 도서관 결정.
-
스트림 기반 I / O는 (IMO, 잘못된 선택) 때문에 각 스트림 액세스에서 동기화가 필요하기 때문에 느립니다 . NIO는 이것을 고쳤 지만 사용하기가 쉽지 않습니다 . 한 번에 요소 대신 배열에 대한 읽기 / 쓰기를 수행하여이 문제를 해결할 수 있습니다.
-
Java는 C와 동일한 저수준 기능을 제공하지 않으므로 더러운 인라인 어셈블러 트릭을 사용하여 일부 작업을 더 빠르게 수행 할 수 없습니다. 이것은 이식성을 제공하며 현재 대부분의 고급 언어 기능입니다.
-
Java 애플리케이션이 매우 오래된 JVM 버전과 연관되어있는 것이 일반적입니다. 특히 서버 측. 이 오래된 JVM은 최신 버전에 비해 매우 비효율적 일 수 있습니다.
결국 Java는 일부 성능을 희생시키면서 보안과 이식성을 제공하고 실제로는 까다로운 작업을 위해 설계되었습니다. 속도 저하에 대한 명성의 대부분은 더 이상 가치가 없습니다.
그러나 Java가 대부분의 다른 언어보다 빠른 곳은 여러 곳 입니다.
-
메모리 할당 및 할당 해제는 빠르고 저렴합니다. 캐시 된 것을 재사용하는 것보다 새로운 다중 kB 배열을 할당하는 것이 20 % 더 빠릅니다 (또는 그 이상!).
-
객체 인스턴스화 및 객체 지향 기능은 처음부터 설계되었으므로 사용하기가 매우 빠릅니다 (경우에 따라 C ++보다 빠름). 이것은 부분적으로 명시적인 할당이 아닌 좋은 GC에서 비롯된 것입니다 (많은 작은 객체 할당에 더 친숙합니다). 사용자 정의 메모리 관리를 롤링하고 malloc을 효율적으로 수행하여 C를 코딩 할 수는 있지만 쉽지는 않습니다.
-
메소드 호출은 기본적으로 무료이며 경우에 따라 대형 메소드 코드보다 빠릅니다. 핫스팟 컴파일러 최적화 메소드 호출에 실행 정보를 사용하여 매우 효율적인 인라인있다. 추가 실행 정보를 사용하면 때때로 선행 컴파일러보다 성능이 우수하고 수동 인라이닝을 수행 할 수 있습니다. 컴파일러가 인라인하지 않기로 결정한 경우 메소드 호출에 약간의 성능 저하가 발생하는 C / C ++와 비교하십시오.
-
동기화 및 멀티 스레딩은 쉽고 효율적입니다. Java는 처음부터 스레드를 인식하도록 설계되었습니다. 최신 컴퓨터에는 일반적으로 여러 코어가 있으며 스레딩이 언어에 내장되어 있으므로 매우 쉽게 활용할 수 있습니다. 기본적으로 표준 단일 스레드 C 코드에 비해 추가 100 % ~ 300 % 속도 향상. 그렇습니다. 신중하게 작성된 C 스레딩과 라이브러리는 이것을 능가 할 수 있지만 프로그래머에게는 많은 추가 작업이 필요합니다.
-
문자열에는 길이가 포함됩니다. 일부 작업이 더 빠릅니다. 이것은 널로 구분 된 문자열 (C에서 공통)을 사용하여 이깁니다. Java 7에서 사람들은 String.subString () 최적화를 사용했습니다. 사람들이 어리석게 사용하고 메모리 누수가 발생했기 때문입니다.
-
어레이 복사가 고도로 최적화되었습니다. 최신 버전에서 Java는 System.arraycopy에 대해 수동 조정 어셈블러를 사용합니다. 결과는 arraycopy / memcopy-heavy 작업에서 내 코드가 C에서 동등한 마진으로 동등한 것을 보았습니다.
-
JIT 컴파일러는 L1 / L2 캐시를 사용하는 것이 현명 합니다 . 미리 컴파일 된 프로그램은 코드를 실시간으로 실행중인 특정 CPU 및 시스템에 맞게 조정할 수 없습니다. JIT는 이런 방식으로 매우 효율적인 루프 변환을 제공합니다.
몇 가지 다른 역사적 사실이 “자바는 느리다”라는 평판에 기여했습니다.
- JIT 컴파일 (Java 1.2 / 1.3) 이전에는 언어 만 해석되고 컴파일되지 않았으므로 매우 느 렸습니다.
- JIT 컴파일이 효율적이되기까지 시간이 걸렸습니다 (각 버전에서 크게 개선됨)
- 클래스 로딩은 수년에 걸쳐 훨씬 더 효율적이되었습니다. 예전에는 비효율적이고 속도가 느 렸습니다.
- Swing 및 UI 코드는 기본 그래픽 하드웨어를 잘 사용하지 않았습니다.
- 스윙은 끔찍합니다. 나는 왜 Java가 데스크탑에 붙 잡히지 않았는지 AWT와 Swing을 비난합니다.
- 라이브러리 클래스에서 많은 동기화 사용; 동기화되지 않은 버전을 사용할 수 있습니다
- 애플릿 은 네트워크를 통해 전체 JAR 을 전송하고 부팅 할 VM을로드 하기 때문에 영원히로드 됩니다.
- 성능 저하가 심할 때 사용되는 동기화 (각 Java 버전에 최적화되어 있음) 그러나 반사는 여전히 비용이 많이 든다.
답변
처음에는 Java가 특별히 빠르지는 않았지만 지나치게 느리지 않았습니다. 요즘 Java는 매우 빠릅니다. 내가 말한 사람들로부터 Java가 느리다는 인상에 대해 두 가지가 있습니다.
-
VM 시작 시간이 느립니다. 초기 Java 구현은 기본 애플리케이션과 비교하여 필수 라이브러리 및 애플리케이션을 시작하고로드하는 데 오랜 시간이 걸렸습니다.
-
느린 UI. 초기 스윙 은 느렸다. 대부분의 Windows 사용자가 기본 Metal L & F를 못 찾게하는 데 도움이되지 않았을 것입니다.
위의 점을 감안할 때 사람들이 ‘자바는 느리다’라는 인상을 받았다는 것은 놀라운 일이 아닙니다.
기본 응용 프로그램 또는 Visual Basic 개발에 익숙한 사용자 또는 개발자 응용 두 가지 점이 응용 프로그램에서 가장 눈에 띄는 부분이며 응용 프로그램에 대한 첫 인상입니다 (GUI 이외의 응용 프로그램이 아닌 한) 경우에만 적용됩니다.).
코드 실행 및 시작 시간이 전혀 연결되지 않았더라도 응용 프로그램을 시작하는 데 8 초가 걸리는 즉시 이전의 Visual Basic 응용 프로그램과 비교할 때 “코드를 매우 빠르게 실행”한다고 사용자에게 확신시키지 않습니다.
첫인상을 망치는 것은 소문과 신화를 시작하는 좋은 방법입니다. 그리고 소문과 신화는 죽이기 어렵다.
요컨대, Java는 느리지 않습니다. “자바는 느린 태도”를 가진 사람들은 10 년 전의 자바에 대한 첫인상을 기반으로합니다.
답변
Java가 느리지 않다는 의견이 가득 찬 페이지를 읽은 후에는 다른 의견으로 대답해야합니다.
언어의 속도 저하는 ‘빠른’기대치에 따라 크게 달라집니다. C #이 빠르다고 생각하면 Java도 빠릅니다. 문제 도메인이 데이터베이스 또는 반 실시간 처리와 관련이 있으면 Java도 충분히 빠릅니다. 더 많은 하드웨어를 추가하여 응용 프로그램을 확장하고 싶다면 Java가 가장 빠를 것입니다. 5-10의 스케일에서 상수 팩터 속도가 그다지 가치가 없다고 생각하면 Java를 빠르게 고려할 수 있습니다.
큰 데이터 세트에서 숫자 계산을 수행하거나 CPU 자원이 제한되어 있고 5-10의 규모로 지속적인 속도 향상이 큰 실행 환경에 바인딩 된 경우. 0.5 배속이라도 계산이 완료되는 데 500 시간이 단축 될 수 있습니다. 이 경우 Java는 마지막 성능을 얻을 수 없으며 Java를 느리게 생각할 수 있습니다.
답변
두 가지 다른 질문을하는 것 같습니다.
- Java는 정말로 느리며 왜 그렇다면 그 이유는 무엇입니까?
- 많은 대안보다 빠르지 만 Java가 왜 느리게 인식됩니까?
이 중 첫 번째는 “로프가 얼마나 오래 걸리는가”라는 질문입니다. “느린”의 정의로 귀결됩니다. 순수한 인터프리터에 비해 Java는 매우 빠릅니다. 어떤 종류의 바이트 코드로 (일반적으로) 컴파일 된 다음 기계 코드 (예 : C # 또는 .NET의 다른 것)로 동적으로 컴파일 된 다른 언어와 비교할 때 Java는 거의 비슷한 수준입니다. 일반적으로 순수한 기계 코드로 컴파일되고 언어 최적화 프로그램 (예 : C, C ++, Fortran, Ada)을 개선하는 것 외에는 아무 일도하지 않는 사람들로 구성된 팀과 비교할 때 Java는 몇 가지 일을 잘 하지만 전반적으로 잘 수행합니다. 적어도 다소 느린 경향이 있습니다.
이것의 대부분은 주로 구현과 관련이 있습니다. 기본적으로 동적 / JIT 컴파일러가 실행되는 동안 사용자가 기다리고 있다는 사실에 기인합니다. 따라서 시작하는 데 꽤 오랜 시간 동안 실행되는 프로그램이 없다면 컴파일러가 어려운 최적화에 많은 시간을 소비하게 만드는 것은 정당화하기 어렵습니다. 따라서 대부분의 Java (및 C # 등) 컴파일러는 실제로 어려운 최적화에 많은 노력을 기울이지 않습니다. 많은 경우에, 최적화가 적용되는 위치보다 수행되는 최적화가 적습니다. 많은 최적화 문제는 NP가 완료되었으므로 문제의 크기가 커질수록 시간이 빠르게 증가합니다. 이유 내에서 시간을 유지하는 한 가지 방법은 한 번에 하나의 함수와 같은 것에 만 최적화를 적용하는 것입니다. 개발자 만 컴파일러를 기다리는 경우 훨씬 더 오래 걸릴 수 있고 프로그램의 훨씬 더 큰 청크에 동일한 최적화를 적용 할 수 있습니다. 마찬가지로 일부 최적화 코드는 매우 털이 많기 때문에 상당히 클 수 있습니다. 다시 말하지만 사용자는 해당 코드가로드되는 동안 대기하고 있기 때문에 (그리고 JVM 시작 시간이 전체 시간에서 중요한 요소 인 경우가 많음) 구현시 한 장소에서 절약 된 시간과 다른 장소에서 손실되는 시간의 균형을 유지해야합니다. 털이 최적화의 이점을 누리면 JVM을 작게 유지하는 것이 일반적으로 더 유리합니다.
두 번째 문제는 Java를 사용하면 “모든 크기에 맞는”종류의 솔루션을 어느 정도 얻을 수 있다는 것입니다. 예를 들어, 많은 Java 개발자에게 Swing은 기본적으로 유일한 사용 가능한 윈도우 라이브러리입니다. C ++과 같은 것에는 문자 그대로 수십 개의 윈도우 라이브러리, 응용 프로그램 프레임 워크 등이 있으며, 각각 사용 편의성 대 빠른 실행, 일관된 모양과 느낌, 기본 모양과 느낌 등의 고유 한 절충안이 있습니다. 유일한 고집 포인트는 일부 (예 : Qt)가 (적어도 상업적인 용도로는) 상당히 비쌀 수 있다는 것입니다.
셋째, C ++로 작성된 많은 코드 (그리고 C도 훨씬 더)는 단순히 더 오래되고 더 성숙합니다. 코드 최적화에 여분의 시간을 소비하는 것이 정상적인 예상되는 동작이었을 때 수십 년 전에 작성된 핵심 루틴이 많이 포함되어 있습니다. 그것은 종종 더 작고 빠른 코드에 실질적인 이점이 있습니다. C ++ (또는 C)는 코드가 작고 빠르다는 크레딧을 얻지 만 실제로 개발자의 제품이자 코드 작성 시간의 제약 조건입니다. 어느 정도까지는 사람들이 속도를 걱정할 때 종종 C ++을 선택합니다. 그들은 시간과 노력을 추가로 최적화하고 새로운 세대의 빠른 C ++ 코드를 작성했습니다.
요약하자면, 일반적인 Java 구현은 최대한의 최적화 문제를 야기합니다. 설상가상으로 Java가 보이는 곳에서는 윈도우 툴킷 및 JVM 시작 시간과 같은 것이 언어 자체의 실행 속도보다 더 큰 역할을합니다. 많은 경우에 C와 C ++는 또한 최적화에서 더 열심히 노력한 결과물에 대한 신뢰를 얻습니다.
두 번째 질문에 관해서는, 나는 그것이 직장에서의 인간 본성의 문제라고 생각합니다. 몇몇 열광 자들은 자바가 맹목적으로 빠르다는 주장을 다소 부풀렸다. 누군가 그것을 시도해보고 사소한 프로그램조차 시작하는 데 몇 초가 걸리고 실행되면 느리고 서투른 느낌이 든다는 것을 알았습니다. JVM의 시작 시간이며, 처음 시도 할 때 코드가 아직 컴파일되지 않았다는 사실을 인식하기 위해 사물을 분석하는 사람은 거의 없을 것입니다. 기다리는 동안 컴파일되는 것도 있습니다. 더 나쁜 것은, 충분히 빠르게 작동하더라도 모양과 느낌은 대부분의 사용자에게는 일반적으로 이질적이고 어색해 보일 것입니다.
이들을 함께 추가하면 Java가 느리고, 추악하고 어색하다는 상당히 간단하고 자연스러운 반응이 나타납니다. 이 과민 반응하는 경향이 그리고이라고 생각 결론이 빨리 정말 말 과대 광고를 감안할 때 끔찍 대신 (정확한)의 느린 “약간 느리게, 그 대부분에서 특정 상황.” 이것은 일반적으로 언어로 처음 몇 개의 프로그램을 작성하는 개발자에게는 최악입니다. 대부분의 언어로 “hello world”프로그램을 실행하면 즉각적으로 나타나지만 Java에서는 JVM이 시작될 때 쉽게 인식 할 수있는 일시 정지가 있습니다. 타이트한 루프에서 훨씬 느리게 실행되는 순수한 인터프리터조차도로드와 비트가 조금 더 빨리 실행될 수 있기 때문에 이와 같은 코드에서는 여전히 더 빨리 나타납니다.
답변
자바의 초기 (1990 년대 중반에서 후반까지)의 오래된 정보입니다. Java의 모든 주요 버전은 이전 버전에 비해 상당한 속도 향상을 가져 왔습니다. Oracle이 Java의 Java 7 용 JVM과 JRockit을 합병 한이 추세는 계속 될 것으로 보입니다.
다른 많은 인기있는 현대 언어 (Python, Ruby, PHP)와 비교할 때 Java는 대부분의 용도에서 실제로 훨씬 빠릅니다. C 또는 C ++과는 일치하지 않지만 많은 작업에서 충분히 가깝습니다. 실제 성능 문제는 사용하는 메모리 양에 관한 것입니다.
답변
“긴 시작 시간”의 주요 원인은 동적 연결입니다. Java 애플리케이션은 컴파일 된 클래스로 구성됩니다. 각 클래스는 name으로 다른 클래스 (인수 유형, 메소드 호출 …)를 참조 합니다. JVM은 시작시 해당 이름을 검사하고 일치시켜야합니다. 주어진 시간에 필요한 부분 만 수행하면서 점진적으로 수행하지만 여전히해야 할 일입니다.
C 응용 프로그램에서 해당 연결 단계는 컴파일이 끝날 때 발생합니다. 특히 큰 응용 프로그램의 경우 속도가 느리지 만 개발자 만 볼 수 있습니다. 링크하면 OS가 단순히 “있는 그대로”RAM에로드해야하는 실행 파일이 생성됩니다.
Java에서, 링크는 애플리케이션이 실행될 때마다 발생합니다. 따라서 시작 시간이 길다.
캐싱 기술을 포함하여 다양한 최적화가 적용되었으며 컴퓨터가 더 빨라지고 (응용 프로그램이 “더 크게”얻을수록 “더 빠르다”) 문제의 중요성이 최근에 크게 줄었습니다. 그러나 오래된 편견이 남아 있습니다.
나중에 성능에 관해서는 배열 액세스 (주로 해시 함수 및 기타 암호화 알고리즘)를 사용한 소형 계산에 대한 내 벤치 마크는 일반적으로 최적화 된 C 코드가 Java 코드보다 약 3 배 빠릅니다. 때로는 C가 Java보다 30 % 빠르며, 구현 된 알고리즘에 따라 C가 4 배 빠를 수도 있습니다. 프로세서가 제공하는 64×64-> 128 곱셈 opcode로 인해 “C”코드가 실제로 큰 정수 산술을 위해 어셈블리되었을 때 10x 요소를 보았지만 가장 긴 정수 유형이 64 비트이기 때문에 Java를 사용할 수 없습니다 long
. 이것은 엣지 케이스입니다. 실제 조건에서 I / O 및 메모리 대역폭 고려 사항으로 인해 C 코드 가 Java보다 실제로 3 배 더 빠릅니다.
답변
Java는 특히 양적 작업의 경우 속도가 느립니다.
최적화 된 멀티 스레드 ATLAS 라이브러리 와 함께 R , Python 및 C / C ++ 조합을 사용합니다 . 이러한 각 언어에서 약 4 초 안에 3000 x 3000 행렬의 복식 행렬을 곱할 수 있습니다. Java에서 Colt 및 Parallel Colt를 사용하면 동일한 작업에 185 초가 걸립니다! 이러한 자바 라이브러리가 본질적으로 평행 함에도 불구하고 놀랍습니다.
따라서 순수한 Java는 정량 작업에 적합하지 않습니다. Jblas는 ATLAS를 사용하므로 Java를위한 최고의 선형 대수 라이브러리 인 것 같습니다.
내 컴퓨터는 RAM이 3GB 인 HP Core 2 Duo 입니다. 64 비트 Ubuntu 10.04 (Lucid Lynx)를 사용합니다.