c++與java的優缺點

   大多數程序員都認爲C/C++會比Java語言快,甚至於以爲從Java語言誕生以來,「執行速度緩慢」的帽子就應當被扣在頭頂,這種觀點的出現是因爲Java剛出現的時候JIT編譯技術還不成熟,主要靠解釋器執行的Java語言確實性能比較低下。可是在今天JIT編譯技術已經發展成熟以後,Java語言有可能在速度上與C/C++爭一日長短了嗎?這個問題的答案,讓咱們從二者的編譯器談起。  

  Java與C/C++的編譯器對比其實是表明了最經典的JIT編譯器與靜態編譯器的對比,也很大程度上決定了Java與C/C++的性能對比的結果,由於不管是C/C++仍是Java代碼,最終編譯以後被機器執行的都是本地機器碼,哪一種語言性能更高,除了它們自身的API庫實現得好壞之外,其他的比較就成了一場「拼編譯器」、「拼輸出代碼質量」的遊戲。固然,這種比較也是剔除了開發效率的片面對比,語言間孰優孰劣,誰快誰慢的問題都是很難有結果的爭論,下面咱們就回到正題,看看這兩種語言的編譯器各有何優點。 

  Java虛擬機的JIT編譯器與C/C++的靜態優化編譯器相比,可能會因爲下列這些緣由致使輸出的本地代碼有一些劣勢(下面列舉的也包括一些虛擬機執行子系統的性能劣勢): 

  首先,由於JIT編譯器運行佔用的是用戶程序運行時間,具備很大的時間壓力,它能提供的優化手段也嚴重受制於編譯成本。若是編譯速度不能達到要求,那用戶將在啓動程序或程序的某部分察覺到重大延遲,這點使得JIT編譯器不敢隨便引入大規模的優化技術,而編譯的時間成本在靜態優化編譯器中並非主要的關注點。 

  其次,Java語言是動態的類型安全語言,這意味着須要由虛擬機來確保程序不會違反語言語義或訪問非結構化內存。在實現層面上看,這就意味着虛擬機必須頻繁進行動態檢查,如對象實例訪問時檢查空指針、數組元素訪問時檢查上下界範圍、類型轉換時檢查繼承關係等等。對於這類程序代碼沒有明確寫出的檢查行爲,儘管編譯器會努力進行優化,可是整體上仍然要消耗着很多的運行時間。 

  Java語言中雖然沒有virutal關鍵字,可是使用虛方法的頻率卻遠遠大於C/C++語言,這意味着運行時對方法接收者進行多態選擇的頻率要遠遠大於C/C++語言,也意味着JIT編譯器在進行一些優化,如方法內聯時難度要遠大於C/C++的靜態優化編譯器。 

  Java語言是能夠動態擴展的語言,運行時加載新的類可能改變程序類型繼承關係,這使得不少全局的優化都難以進行,由於編譯器沒法看見程序的全貌,許多全局優化措施都只能以激進優化的方式來完成,編譯器不得不時刻注意並隨着類型變化而在運行是撤消或從新進行一些優化。 

  Java語言中的對象內存分配都是堆上進行,只有方法中的局部變量纔在棧上分配。而C/C++的對象則有多種內存分配方式,既可能在堆上分配,也可能在棧上分配,若是能夠把線程私有的對象在棧上分配,將能夠減輕內存回收的壓力,也不須要考慮內存屏障方面的問題。另外,C/C++中主要由用戶程序代碼來回收分配的內存,這就不存在無用對象篩選的過程,所以效率上(僅指運行效率,排除了開發效率)也垃圾收集機制要高。 

  Java語言相對C/C++的劣勢上面說了一大堆,倒不是說Java就真的不如C/C++了,相信你們也注意到了,Java語言的這些性能上的劣勢都是爲了換取開發效率上的優點而付出的代價,動態安全、動態擴展、垃圾回收這些「拖後腿」特性都爲Java語言的開發效率做出了很大貢獻。況且,也不見得就沒有Java的JIT編譯器能作,而C/C++的靜態優化編譯器不能作的優化:因爲C/C++編譯器的靜態性,以運行期性能監控爲基礎的優化措施它都沒法進行,如調用頻率預測(Call Frequency Prediction)、分支頻率預測(Branch Frequency Prediction)、裁剪未被選擇的分支(Untaken Branch Pruning)等,這些都會造成一些Java語言獨有的性能優點。
相關文章
相關標籤/搜索