某天週末,CPU和JVM聊了起來···
程序員
小兄弟,最近據說你風頭很猛啊緩存
大哥見笑了,豈敢豈敢架構
豈敢?我看你敢的很嘛,本身搞了一套虛擬機,都快把我架空了ide
大哥你看你說的,我就是一Java虛擬機,最終還得把代碼指令發給您來執行。根本離不開你,怎麼會架空你呢函數
我卻是很好奇,既然最終仍是得靠我來執行指令,那你存在的意義又是什麼呢?優化
這您就有所不知了。我做爲中間商,爲程序們提供了最優質便捷的服務,要是讓他們直接跟你打交道,那還得了解你的指令集,你的I/O方式、你的內存管理方式,可麻煩了。spa
別蒙我了,你說的這些,操做系統都封裝好了,程序們直接調用就行了,哪有那麼麻煩?操作系統
。。。。。。翻譯
你說的不錯,不過有一個致命的問題,就是操做系統也幫不上忙。3d
什麼問題?
跨平臺移植
你是說在移植到不一樣的操做系統上嗎?
不只僅是操做系統,還可能移植到別的架構CPU上。這樣原來的程序就無法執行了。
提問題固然容易,那你有什麼好的解決辦法?
個人辦法就是不要讓程序代碼編譯成你的指令集的指令,而是生成一個我定義的中間碼。運行的時候再由我來負責把它們翻譯成當前平臺下對應的CPU指令,交給大家CPU來執行。
好傢伙,還說不是把我架空,這樣一來,你這個中間商好賺差價啊。
不過這對您也沒什麼損失嘛,反正最後仍是躲不開您這一層。
我聽你這意思,那若是其餘語言能編譯成你的中間碼,你也能執行了?
那可不,除了Java,咱還能執行Groovy、Scala,對了,Python咱也能執行。這不跟您同樣嘛,不論是什麼高級語言,最終編譯成你的指令集,你就能執行了,這不一個道理嘛
有點6啊,你這個中間碼是什麼樣的?有這麼厲害,跟個人指令集有什麼不一樣呢?
跟您的指令集很像,不一樣的是個人「指令」不像您的指令有長有短,個人統一都是一個字節,因此也叫字節碼!
都是一個字節?別蒙我了,光內存地址都不止一個字節。
真的,我基本上都是零地址指令,要用的數據都在棧頂,直接操做就是了
都在棧頂?不用寄存器怎麼進行數據操做呢?
誰說必定要有寄存器?我就不用寄存器,您是基於寄存器架構的,而我是基於棧式架構的。運算的時候直接操做棧頂的數據就好了
基於棧?你是說你的指令用到的數據都放在棧裏是嗎?這棧是在內存中,這樣的話數據不停進進出出就要頻繁訪問內存,確定很慢吧?
那確定是比您慢了,不過我也有優化辦法。
什麼辦法,說來聽聽
Top-Of-Stack-CAching,簡稱TOSCA,就是棧頂緩存。在棧頂的數據雖然名義上是在棧頂,但實際我在實現的時候,偷偷的放在了你的寄存器裏,不只能夠減小訪問內存的次數,你到時候執行的時候訪問起來也快得多。
好傢伙,你這小子當面一套,背後一套啊。
你開始說到了「翻譯」,你是怎麼翻譯執行這些字節碼的呢?
咱們爲每一個字節碼都準備了對應的彙編指令,來完成這個字節碼定義的行爲。而後把全部字節碼的彙編指令入口整合到一張表裏來,我來統一派遣分發就能夠了。這些彙編指令到時候就直接交給你CPU來執行就好啦。
我知道了,大家的跨平臺關鍵就是在不一樣平臺生成對應的的彙編指令,是吧!
不過這聽起來有點像是解釋執行啊,跟那些腳本語言解釋執行差很少嘛
你說的那些腳本語言底層是用高級語言在「模擬」執行,而我是直接把字節碼翻譯成了彙編指令,比他們快多了。
再快,那也是解釋執行
好吧,看來得亮出絕活了!
啥?
JIT,just-in-time compilation,即時編譯技術。
這是啥,看上去很厲害的樣子
我在派遣分發的過程當中,發現有頻繁執行的函數或者代碼塊,我就會啓動即時編譯機制,將這部分代碼直接編譯成你CPU的指令,後面就不用再走字節碼派遣表執行了
頻繁執行的函數好理解,頻繁執行的代碼塊是什麼意思?
好比函數中某個循環體,循環執行不少次,雖然可能這個函數調用次數很少,但循環執行要是不少,也會觸發個人即時編譯機制
你是怎麼斷定是不是頻繁呢,不會是憑直覺吧
固然不是,頻不頻繁,我內心是有「數」的。這個數就是計數器,我會統計函數的調用次數和循環體的執行次數。
好小子,有兩把刷子啊,沒少花心思
雕蟲小技,不敢班門弄斧
呀!別聊了,程序員開機了,要去幹活了
今天不周末嗎,他咋還來