java 代码运行速度慢_C代码的运行速度总是比Java快,对吧? 错误!
java 代碼運(yùn)行速度慢
因此,我們都知道,Java解釋緩慢且C的編譯和優(yōu)化運(yùn)行速度非常快。 您可能知道,情況截然不同。
TL; DR Java適用于星座圖,它的速度更快,在JIT上可以執(zhí)行內(nèi)聯(lián),因?yàn)樗蟹椒?功能都是可見(jiàn)的,而C編譯器無(wú)法跨編譯單元(例如庫(kù)等)執(zhí)行優(yōu)化。
AC編譯器將C代碼作為輸入,對(duì)其進(jìn)行編譯和優(yōu)化,并生成要執(zhí)行的特定CPU或體系結(jié)構(gòu)的機(jī)器代碼。 這導(dǎo)致可執(zhí)行文件,無(wú)需進(jìn)一步步驟即可直接在給定計(jì)算機(jī)上運(yùn)行。 另一方面,Java有一個(gè)中間步驟:字節(jié)碼。 因此,Java編譯器將Java代碼作為輸入并生成字節(jié)碼,而字節(jié)碼基本上是抽象機(jī)的機(jī)器代碼。 現(xiàn)在,對(duì)于每個(gè)(流行的)CPU架構(gòu),都有一個(gè)Java Virual機(jī)器,該機(jī)器模擬此抽象機(jī)器并執(zhí)行(解釋)生成的字節(jié)碼。 這聽(tīng)起來(lái)很慢。 但是另一方面,字節(jié)碼是可移植的,因?yàn)橄嗤妮敵鰧⒃谒衅脚_(tái)上運(yùn)行,因此口號(hào)“ 一次寫(xiě)入,隨處運(yùn)行 ”。
現(xiàn)在,使用上述方法,它會(huì)變成“ 編寫(xiě)一次,到處等待 ”,因?yàn)榻忉屍鲿?huì)很慢。 因此,現(xiàn)代JVM所做的只是及時(shí)編譯。 這意味著JVM在內(nèi)部將字節(jié)碼轉(zhuǎn)換為用于CPU的機(jī)器代碼。 但是由于此過(guò)程非常復(fù)雜,因此Hotspot JVM (最常用的一種)僅對(duì)經(jīng)常執(zhí)行的代碼片段執(zhí)行此操作(因此命名為Hotspot )。 除了更快地啟動(dòng)(解釋器立即啟動(dòng),JIT編譯器根據(jù)需要啟動(dòng))之外,還有另一個(gè)好處:熱點(diǎn)JIT已經(jīng)知道代碼的哪些部分被頻繁調(diào)用,什么不被調(diào)用-因此它可以在優(yōu)化輸出時(shí)使用它–這就是我們的例子發(fā)揮作用的地方。
現(xiàn)在,在看我完整的微型示例之前,請(qǐng)注意,Java具有很多功能,例如動(dòng)態(tài)調(diào)度(在接口上調(diào)用方法),它還帶有運(yùn)行時(shí)開(kāi)銷(xiāo)。 因此,Java代碼可能更容易編寫(xiě),但通常仍會(huì)比C代碼慢。 但是,當(dāng)涉及純數(shù)字運(yùn)算時(shí),就像下面的示例一樣,有一些有趣的發(fā)現(xiàn)。
因此,無(wú)需進(jìn)一步討論,這是示例C代碼:
test.c:
int compute(int i);int test(int i);int main(int argc, char** argv) {int sum = 0;for(int l = 0; l < 1000; l++) {int i = 0;while(i < 2000000) {if (test(i))sum += compute(i);i++;} }return sum; }test1.c:
int compute(int i) {return i + 1; }int test(int i) {return i % 3; }現(xiàn)在,主要功能的實(shí)際計(jì)算完全不重要。 關(guān)鍵是它經(jīng)常調(diào)用兩個(gè)函數(shù)(測(cè)試和計(jì)算),并且這些函數(shù)在另一個(gè)編譯單元(test1.c)中。 現(xiàn)在讓我們編譯并運(yùn)行程序:
> gcc -O2 -c test1.c> gcc -O2 -c test.c> gcc test.o test1.o> time ./a.outreal?? ?0m6.693s user?? ?0m6.674s sys?? ?0m0.012s因此,此過(guò)程大約需要6.6秒 。 現(xiàn)在讓我們看一下Java程序:
Test.java
public class Test {private static int test(int i) {return i % 3; }private static int compute(int i) {return i + 1; }private static int exec() {int sum = 0; for (int l = 0; l < 1000; l++) {int i = 0; while (i < 2000000) {if (test(i) != 0) {sum += compute(i); }i++; }}return sum; }public static void main(String[] args) {exec(); } }現(xiàn)在讓我們編譯并執(zhí)行以下命令:
> javac Test.java> time java Testreal??? 0m3.411s user??? 0m3.395s sys???? 0m0.030s因此,花費(fèi)3.4秒的時(shí)間 ,Java可以輕松完成此簡(jiǎn)單任務(wù)(甚至包括JVM的緩慢啟動(dòng))。 問(wèn)題是為什么? 當(dāng)然,答案是JIT可以執(zhí)行C編譯器無(wú)法執(zhí)行的代碼優(yōu)化。 在我們的例子中是函數(shù)內(nèi)聯(lián)。 當(dāng)我們?cè)谧约旱木幾g單元中定義了我們的兩個(gè)微型函數(shù)時(shí),編譯器無(wú)法在編譯test.c時(shí)內(nèi)聯(lián)這些函數(shù)。另一方面,JIT擁有所有方法,并且可以執(zhí)行主動(dòng)內(nèi)聯(lián),因此編譯后的代碼速度更快。
那么,這是一個(gè)在現(xiàn)實(shí)生活中從未發(fā)生過(guò)的完全異國(guó)情調(diào)的虛構(gòu)例子嗎? 是的,沒(méi)有。 當(dāng)然,這是一個(gè)極端的情況,但是請(qǐng)考慮一下代碼中包含的所有庫(kù)。 所有這些方法都不能在C語(yǔ)言中進(jìn)行優(yōu)化,而在Java中,字節(jié)碼的來(lái)源無(wú)關(guān)緊要。 由于所有這些都存在于正在運(yùn)行的JVM中,因此JIT可以對(duì)其核心內(nèi)容進(jìn)行優(yōu)化。 當(dāng)然,C語(yǔ)言有一個(gè)骯臟的技巧可以減輕這種痛苦:Marcos。 在我看來(lái),這就是市長(zhǎng)的原因之一,為什么C中如此之多的庫(kù)仍然使用宏而不是適當(dāng)?shù)墓δ?伴隨著它們帶來(lái)的所有問(wèn)題和麻煩。
現(xiàn)在就在火焰戰(zhàn)爭(zhēng)開(kāi)始之前:這兩種語(yǔ)言都有其長(zhǎng)處和短處,并且在軟件工程領(lǐng)域都占有一席之地。 這篇文章的撰寫(xiě)僅是為了吸引您的魔力,并想知道現(xiàn)代JVM每天都在發(fā)生。
翻譯自: https://www.javacodegeeks.com/2016/02/c-code-always-runs-way-faster-java-right-wrong.html
java 代碼運(yùn)行速度慢
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的java 代码运行速度慢_C代码的运行速度总是比Java快,对吧? 错误!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 华为荣耀手机如何返厂维修
- 下一篇: 马斯克不断公开恳求名人在 X 上发帖,如