導航:首頁 > 源碼編譯 > 熱載入和自動編譯的區別

熱載入和自動編譯的區別

發布時間:2022-12-24 15:48:14

❶ webpack 熱重載的3種方式

開發階段,如果每次文件變更後,都要手動去打包build是很不方便的,通常在開發階段採用以下三種方式進行熱重載(自動編譯

配置文件提供一個入口和一個出口,webpack根據這個來進行js的打包和編譯工作。package.json文件增加watch腳本 --watch 動態監聽文件的改變並實時打包,輸出新的文件,這樣文件多了之後速度會很慢,而且此打包方式不會熱更新,即每次webpack編譯之後,你還需要手動刷新瀏覽器。
缺點: 需手動刷新瀏覽器
優點: 自動編譯

webpack-dev-server實際上相當於啟用了一個express的Http伺服器+調用了webpack-dev-middleware【簡單的web伺服器和實時重載】。這個Http伺服器和client使用了websocket通訊協議,原始文件做出改動後,webpack-dev-server會用webpack實時的編譯,再用webpack-dev-middleware將webpack編譯後的文件輸出到內存中。【這邊注意,最後的編譯的文件並沒有輸出到目標文件夾,都保存到了內存】(適合純前端項目,很難編寫後端服務,進行整合)

優點: 自動編譯 + 實時重新載入瀏覽器
webpack-dev-server

缺點: 需手動刷新瀏覽器 + 配置文件和插件多
優點: 自動編譯

定義了webpack.config里的entry和output的關系脈絡,webpack-dev-middleware能在此基礎上形成一個文件映射系統,每當應用程序請求一個文件。它匹配到了就把內存中緩存的對應結果以文件格式返回,反之進入下一個中間件。

因為是內存型文件系統,所以重建速度非常快,很適合於開發階段用作靜態資源伺服器;因為webpack可以把任何一種資源當作是模塊來處理,因此能向客戶端反饋各種格式的資源,所以可以替代HTTP伺服器。

三者相比:觀察模式在開發中不實用;web伺服器實用性強;webpack中間件+express使用了2個插件,2個配置文件,配置復雜

事實上,大多數 webpack 用戶用過的 webpack-dev-server 就是一個 express+webpack-dev-middleware 的實現。

二者的區別僅在於 webpack-dev-server 是封裝好的,除了 webpack.config 和命令行參數之外,很難去做定製型開發。而 webpack-dev-middleware 是中間件,可以編寫自己的後端服務然後把它整合進來,相對而言比較靈活自由。

是一個結合webpack-dev-middleware使用的middleware,它可以實現瀏覽器的無刷新更新(hot reload),這也是webpack文檔里常說的HMR(Hot Mole Replacement)。HMR和熱載入的區別是:熱載入是刷新整個頁面。

運行方式:
1、命令行
package.json中指令加上 --hot

2、Nodejs API

熱更新熱重載
webpack-dev-server 自動打包/熱重載

❷ 技術干貨:SQL on Hadoop在快手大數據平台的實踐與優化

快手大數據架構工程師鍾靚近日在 A2M 人工智慧與機器學習創新峰會分享了題為《SQL on Hadoop 在快手大數據平台的實踐與優化》的演講,主要從 SQL on Hadoop 介紹、快手 SQL on Hadoop 平台概述、SQL on Hadoop 在快手的使用經驗和改進分析、快手 SQL on Hadoop 的未來計劃四方面介紹了 SQL on Hadoop 架構。

SQL on Hadoop,顧名思義它是基於 Hadoop 生態的一個 SQL 引擎架構,我們其實常常聽到 Hive、SparkSQL、Presto、Impala 架構。接下來,我會簡單的描述一下常用的架構情況。

HIVE,一個數據倉庫系統。它將數據結構映射到存儲的數據中,通過 SQL 對大規模的分布式存儲數據進行讀、寫、管理。

根據定義的數據模式,以及輸出 Storage,它會對輸入的 SQL 經過編譯、優化,生成對應引擎的任務,然後調度執行生成的任務。

HIVE 當前支持的引擎類型有:MR、SPARK、TEZ。

基於 HIVE 本身的架構,還有一些額外的服務提供方式,比如 HiveServer2 與 MetaStoreServer 都是 Thrift 架構。

此外,HiveServer2 提供遠程客戶端提交 SQL 任務的功能,MetaStoreServer 則提供遠程客戶端操作元數據的功能。

Spark,一個快速、易用,以 DAG 作為執行模式的大規模數據處理的統一分析引擎,主要模塊分為 SQL 引擎、流式處理 、機器學習、圖處理。

SPARKSQL 基於 SPARK 的計算引擎,做到了統一數據訪問,集成 Hive,支持標准 JDBC 連接。SPARKSQL 常用於數據交互分析的場景。

SPARKSQL 的主要執行邏輯,首先是將 SQL 解析為語法樹,然後語義分析生成邏輯執行計劃,接著與元數據交互,進行邏輯執行計劃的優化,最後,將邏輯執行翻譯為物理執行計劃,即 RDD lineage,並執行任務。

PRESTO,一個互動式分析查詢的開源分布式 SQL 查詢引擎。

因為基於內存計算,PRESTO 的計算性能大於有大量 IO 操作的 MR 和 SPARK 引擎。它有易於彈性擴展,支持可插拔連接的特點。

業內的使用案例很多,包括 FaceBook、AirBnb、美團等都有大規模的使用。

我們看到這么多的 SQL on Hadoop 架構,它側面地說明了這種架構比較實用且成熟。利用 SQL on Hadoop 架構,我們可以實現支持海量數據處理的需求。

查詢平台每日 SQL 總量在 70 萬左右,DQL 的總量在 18 萬左右。AdHoc 集群主要用於交互分析及機器查詢,DQL 平均耗時為 300s;AdHoc 在內部有 Loacl 任務及加速引擎應用,所以查詢要求耗時較低。

ETL 集群主要用於 ETL 處理以及報表的生成。DQL 平均耗時為 1000s,DQL P50 耗時為 100s,DQL P90 耗時為 4000s,除上述兩大集群外,其它小的集群主要用於提供給單獨的業務來使用。

服務層是對上層進行應用的。在上層有四個模塊,這其中包括同步服務、ETL 平台、AdHoc 平台以及用戶程序。在調度上層,同樣也有四方面的數據,例如服務端日誌,對它進行處理後,它會直接接入到 HDFS 里,我們後續會再對它進行清洗處理;服務打點的數據以及資料庫信息,則會通過同步服務入到對應的數據源里,且我們會將元數據信息存在後端元數據系統中。

網頁爬取的數據會存入 hbase,後續也會進行清洗與處理。

HUE、NoteBook 主要提供的是互動式查詢的系統。報表系統、BI 系統主要是 ETL 處理以及常見的報表生成,額外的元數據系統是對外進行服務的。快手現在的引擎支持 MR、Presto 及 Spark。

管理系統主要用於管理我們當前的集群。HiveServer2 集群路由系統,主要用於引擎的選擇。監控系統以及運維系統,主要是對於 HiveServer2 引擎進行運維。

我們在使用 HiveServer2 過程中,遇到過很多問題。接下來,我會詳細的為大家闡述快手是如何進行優化及實踐的。

當前有多個 HiveServer2 集群,分別是 AdHoc 與 ETL 兩大集群,以及其他小集群。不同集群有對應的連接 ZK,客戶端可通過 ZK 連接 HiveServer2 集群。

為了保證核心任務的穩定性,將 ETL 集群進行了分級,分為核心集群和一般集群。在客戶端連接 HS2 的時候,我們會對任務優先順序判定,高優先順序的任務會被路由到核心集群,低優先順序的任務會被路由到一般集群。

BeaconServer 服務為後端 Hook Server 服務,配合 HS2 中的 Hook,在 HS2 服務之外實現了所需的功能。當前支持的模塊包括路由、審計、SQL 重寫、任務控制、錯誤分析、優化建議等。

•無狀態,BeaconServer 服務支持水平擴展。基於請求量的大小,可彈性調整服務的規模。

•配置動態載入,BeaconServer 服務支持動態配置載入。各個模塊支持開關,服務可動態載入配置實現上下線。比如路由模塊,可根據後端加速引擎集群資源情況,進行路由比率調整甚至熔斷。

•無縫升級,BeaconServer 服務的後端模塊可單獨進行下線升級操作,不會影響 Hook 端 HS2 服務。

•Hive 支持 SPARK 與 TEZ 引擎,但不適用於生產環境。

•SQL on Hadoop 的 SQL 引擎各有優缺點,用戶學習和使用的門檻較高。

•不同 SQL 引擎之間的語法和功能支持上存在差異,需要大量的測試和兼容工作,完全兼容的成本較高。

•不同 SQL 引擎各自提供服務會給數倉的血緣管理、許可權控制、運維管理、資源利用都帶來不便。

•在 Hive 中,自定義實現引擎。

•自動路由功能,不需要設置引擎,自動選擇適合的加速引擎。

•根絕規則匹配 SQL,只將兼容的 SQL 推給加速引擎。

•復用 HiveServer2 集群架構。

基於 HiveServer2,有兩種實現方式。JDBC 方式是通過 JDBC 介面,將 SQL 發送至後端加速引擎啟動的集群上。PROXY 方式是將 SQL 下推給本地的加速引擎啟動的 Client。

JDBC 方式啟動的後端集群,均是基於 YARN,可以實現資源的分時復用。比如 AdHoc 集群的資源在夜間會自動回收,作為報表系統的資源進行復用。

路由方案基於 HS2 的 Hook 架構,在 HS2 端實現對應 Hook,用於引擎切換;後端 BeaconServer 服務中實現路由 服務,用於 SQL 的路由規則的匹配處理。不同集群可配置不同的路由規則。

為了保證後算路由服務的穩定性,團隊還設計了 Rewrite Hook,用於重寫 AdHoc 集群中的 SQL,自動添加 LIMIT 上限,防止大數據量的 SCAN。

•易於集成,當前主流的 SQL 引擎都可以方便的實現 JDBC 與 PROXY 方式。再通過配置,能簡單的集成新的查詢引擎,比如 impala、drill 等。

•自動選擇引擎,減少了用戶的引擎使用成本,同時也讓遷移變得更簡單。並且在加速引擎過載 的情況下,可以動態調整比例,防止因過載 對加速性能的影響。

•自動降級,保證了運行的可靠性。SQL 路由支持 failback 模塊,可以根據配置選擇是否再路由引擎執行失敗後,回滾到 MR 運行。

•模塊復用,對於新增的引擎,都可以復用 HiveServer2 定製的血緣採集、許可權認證、並發鎖控制等方案,大大降低了使用成本。

•資源復用,對於 adhoc 查詢佔用資源可以分時動態調整,有效保證集群資源的利用率。

當查詢完成後,本地會輪詢結果文件,一直獲取到 LIMIT 大小,然後返回。這種情況下,當有大量的小文件存在,而大文件在後端的時候,會導致 Bad Case,不停與 HDFS 交互,獲取文件信息以及文件數據,大大拉長運行時間。

在 Fetch 之前,對結果文件的大小進行預排序,可以有數百倍的性能提升。

示例:當前有 200 個文件。199 個小文件一條記錄 a,1 個大文件混合記錄 a 與 test 共 200 條,大文件名 index 在小文件之後。

Hive 中有一個 SimpleFetchOptimizer 優化器,會直接生成 FetchTask,減小資源申請時間與調度時間。但這個優化會出現瓶頸。如果數據量小,但是文件數多,需要返回的條數多,存在能大量篩掉結果數據的 Filter 條件。這時候串列讀取輸入文件,導致查詢延遲大,反而沒起到加速效果。

在 SimpleFetchOptimizer 優化器中,新增文件數的判斷條件,最後將任務提交到集群環境,通過提高並發來實現加速。

示例:讀取當前 500 個文件的分區。優化後的文件數閾值為 100。

一個表有大量的子分區,它的 DESC 過程會與元數據交互,獲取所有的分區。但最後返回的結果,只有跟表相關的信息。

與元數據交互的時候,延遲了整個 DESC 的查詢,當元數據壓力大的時候甚至無法返回結果。

針對於 TABLE 的 DESC 過程,直接去掉了跟元數據交互獲取分區的過程,加速時間跟子分區數量成正比。

示例:desc 十萬分區的大表。

•復用 split 計算的數據,跳過 rece 估算重復統計輸入過程。輸入數據量大的任務,調度速率提升 50%。

•parquetSerde init 加速,跳過同一表的重復列剪枝優化,防止 map task op init 時間超時。

•新增 LazyOutputFormat,有 record 輸出再創建文件,避免空文件的產生,導致下游讀取大量空文件消耗時間。

•statsTask 支持多線程聚合統計信息,防止中間文件過多導致聚合過慢,增大運行時間。

•AdHoc 需要打開並行編譯,防止 SQL 串列編譯導致整體延遲時間增大的問題。

HS2 啟動時會對物化視圖功能進行初始化,輪詢整個元資料庫,導致 HS2 的啟動時間非常長,從下線狀態到重新上線間隔過大,可用性很差。

將物化視圖功能修改為延遲懶載入,單獨線程載入,不影響 HS2 的服務啟動。物化視圖支持載入中獲取已緩存信息,保證功能的可用性。

HS2 啟動時間從 5min+提升至<5s。

HS2 本身上下線成本較高,需要保證服務上的任務全部執行完成才能進行操作。配置的修改可作為較高頻率的操作,且需要做到熱載入。

在 HS2 的 ThriftServer 層我們增加了介面,與運維系統打通後,配置下推更新的時候自動調用,可實現配置的熱載入生效。

HiveServer2 的 scratchdir 主要用於運行過程中的臨時文件存儲。當 HS2 中的會話創建時,便會創建 scratchdir。在 HDFS 壓力大的時候,大量的會話會阻塞在創建 scratchdir 過程,導致連接數堆積至上限,最終 HS2 服務無法再連入新連接,影響服務可用性。

對此,我們先分離了一般查詢與 create temporay table 查詢的 scratch 目錄,並支持 create temporay table 查詢的 scratch 的懶創建。當 create temporay table 大量創建臨時文件,便會影響 HDFS NameNode 延遲時間的時候,一般查詢的 scratchdir HDFS NameNode 可以正常響應。

此外,HS2 還支持配置多 scratch,不同的 scratch 能設置載入比率,從而實現 HDFS 的均衡負載。

Hive 調度其中存在兩個問題。

一、子 Task 非執行狀態為完成情況的時候,若有多輪父 Task 包含子 Task,導致子 Task 被重復加入調度隊列。這種 Case,需要將非執行狀態修改成初始化狀態。

二、當判斷子 Task 是否可執行的過程中,會因為狀態檢測異常,無法正常加入需要調度的子 Task,從而致使查詢丟失 Stage。而這種 Case,我們的做法是在執行完成後,加入一輪 Stage 的執行結果狀態檢查,一旦發現有下游 Stage 沒有完成,直接拋出錯誤,實現查詢結果狀態的完備性檢查。

•HS2 實現了介面終止查詢 SQL。利用這個功能,可以及時終止異常 SQL。

•metastore JDOQuery 查詢優化,關鍵字異常跳過,防止元數據長時間卡頓或者部分異常查詢影響元數據。

•增加開關控制,強制覆蓋外表目錄,解決 insert overwrite 外表,文件 rename 報錯的問題。

•hive parquet 下推增加關閉配置,避免 parquet 異常地下推 OR 條件,導致結果不正確。

•executeForArray 函數 join 超大字元串導致 OOM,增加限制優化。

•增加根據 table 的 schema 讀取分區數據的功能,避免未級聯修改分區 schema 導致讀取數據異常。

•部分用戶並沒有開發經驗,無法處理處理引擎返回的報錯。

•有些錯誤的報錯信息不明確,用戶無法正確了解錯誤原因。

•失敗的任務排查成本高,需要對 Hadoop 整套系統非常熟悉。

•用戶的錯誤 SQL、以及需要優化的 SQL,大量具有共通性。人力維護成本高,但系統分析成本低。

SQL 專家系統基於 HS2 的 Hook 架構,在 BeaconServer 後端實現了三個主要的模塊,分別是 SQL 規則控制模塊、SQL 錯誤分析模塊,與 SQL 優化建議模塊。SQL 專家系統的知識庫,包含關鍵字、原因說明、處理方案等幾項主要信息,存於後端資料庫中,並一直積累。

通過 SQL 專家系統,後端可以進行查詢 SQL 的異常控制,避免異常 SQL 的資源浪費或者影響集群穩定。用戶在遇到問題時,能直接獲取問題的處理方案,減少了使用成本。

示例:空分區查詢控制。

SQL 專家系統能解決一部分 HS2 的任務執行的錯誤診斷需求,但是比如作業 健康 度、任務執行異常等問題原因的判斷,需要專門的系統來解決,為此我們設計了作業診斷系統。

作業診斷系統在 YARN 的層面,針對不同的執行引擎,對搜集的 Counter 和配置進行分析。在執行層面,提出相關的優化建議。

作業診斷系統的數據也能通過 API 提供給 SQL 專家系統,補充用於分析的問題原因。

作業診斷系統提供了查詢頁面來查詢運行的任務。以下是命中 map 輸入過多規則的任務查詢過程:

❸ 關於eclispe自動編譯和用ant工具編譯的區別

二者基本沒有區別,只是格式不一樣,用SVN可以區別出來。
每種編譯器都可以生成不精確相同的結果,只要保證代碼執行時是符合規范的並且結果是一致的。
1、利用編譯程序從源語言編寫的源程序產生目標程序的過程。
2、用編譯程序產生目標程序的動作。 編譯就是把高級語言變成計算機可以識別的2進制語言,計算機只認識1和0,編譯程序把人們熟悉的語言換成2進制的。

❹ 如何在idea的jetty插件時自動部署jsp

網上很多人誤解熱部署和熱載入的概念,所以造成亂配置的行為,這里提示一下.
熱部署:就是容器狀態在運行的情況下部署或者重新部署整個項目.在這種情況下一般整個內存會清空,重新載入.簡單來說就是Tomcat或者其他的web伺服器會幫我們重新載入項目.這種方式可能會造成sessin丟失等情況.
熱載入:就是容器狀態在運行的情況下重新載入改變編譯後的類.在這種情況下內存不會清空,sessin不會丟失,但容易造成內存溢出,或者找不到方法。因為內存無法轉變成對像. 一般改變類的結構和模型就會有異常,在已經有的變數和方法中改變是不會出問題的。在中模式最好是在調試過程中使用,免得整個項目載入.
debug模式都支持熱載入.很方便使用.
IDEA TOMCAT WEB開發 SSH開發 修改類不重啟 熱部署 熱載入 IDEA8..
實可以用jreble+maven+tomcat進行熱部置的

❺ 什麼叫熱載入

編譯java類後不重啟Tomcat的一種方式

其實這只是一種表現形式吧,不重啟程序修改生效的應該都叫熱載入

望採納

❻ java熱載入會釋放之前載入的類嗎,GC會在什麼時候回收呢嗎、求高手

GC在任意時候都可能回收垃圾對象所佔的內存,只是概率大小的問題而已。比如,GC發現沒用的對象時,可能立即回收,也可能不立即回收,可能在系統資源快用盡時才回收,我們無法精確的控制垃圾回收,但是,我們可以提醒GC進行垃圾回收,比如對象設置為null或調用object類的相關方法等。

❼ 了解什麼叫做jit compiling,與傳統的編譯技術有何不同

Java 應用程序的性能經常成為開發社區中的討論熱點。因為該語言的設計初衷是使用解釋的方式支持應用程序的可移植性目標,早期
Java 運行時所提供的性能級別遠低於 C 和
C++
之類的編譯語言。盡管這些語言可以提供更高的性能,但是生成的代碼只能在有限的幾種系統上執行。在過去的十年中,Java
運行時供應商開發了一些復雜的動態編譯器,通常稱作即時(Just-in-time,JIT)編譯器。程序運行時,JIT
編譯器選擇將最頻繁執行的方法編譯成本地代碼。運行時才進行本地代碼編譯而不是在程序運行前進行編譯(用 C 或
C++ 編寫的程序正好屬於後一情形),保證了可移植性的需求。有些 JIT 編譯器甚至不使用解釋程序就能編譯所有的代碼,但是這些編譯器仍然通過在程序執行時進行一些操作來保持 Java 應用程序的可移植性。
由於動態編譯技術的多項改進,在很多應用程序中,現代的 JIT 編譯器可以產生與 C 或 C++
靜態編譯相當的應用程序性能。但是,仍然有很多軟體開發人員認為 —— 基於經驗或者傳聞 ——
動態編譯可能嚴重干擾程序操作,因為編譯器必須與應用程序共享 CPU。一些開發人員強烈呼籲對 Java
代碼進行靜態編譯,並且堅信那樣可以解決性能問題。對於某些應用程序和執行環境而言,這種觀點是正確的,靜態編譯可以極大地提高 Java
性能,或者說它是惟一的實用選擇。但是,靜態地編譯 Java 應用程序在獲得高性能的同時也帶來了很多復雜性。一般的
Java 開發人員可能並沒有充分地感受到 JIT 動態編譯器的優點。

本文考察了 Java 語言靜態編譯和動態編譯所涉及的一些問題,重點介紹了實時 (RT) 系統。簡要描述了 Java
語言解釋程序的操作原理並說明了現代 JIT 編譯器執行本地代碼編譯的優缺點。介紹了 IBM 在 WebSphere Real Time 中發布的
AOT 編譯技術和它的一些優缺點。然後比較了這兩種編譯策略並指出了幾種比較適合使用 AOT
編譯的應用程序領域和執行環境。要點在於這兩種編譯技術並不互斥:即使在使用這兩種技術最為有效的各種應用程序中,它們也分別存在一些影響應用程序的優缺
點。

執行 Java 程序

Java 程序最初是通過 Java SDK 的 javac程序編譯成本地的與平台無關的格式(類文件)。可將此格式看作 Java
平台,因為它定義了執行 Java 程序所需的所有信息。Java 程序執行引擎,也稱作 Java 運行時環境(JRE),包含了為特定的本地平台實現
Java 平台的虛擬機。例如,基於 Linux 的 Intel x86 平台、Sun Solaris 平台和 AIX 操作系統上運行的 IBM
System p 平台,每個平台都擁有一個 JRE。這些 JRE 實現實現了所有的本地支持,從而可以正確執行為
Java 平台編寫的程序。

事實上,操作數堆棧的大小有實際限制,但是編程人員極少編寫超出該限制的方法。JVM 提供了安全性檢查,對那些創建出此類方法的編程人員進行通知。

Java 平台程序表示的一個重要部分是位元組碼序列,它描述了 Java
類中每個方法所執行的操作。位元組碼使用一個理論上無限大的操作數堆棧來描述計算。這個基於堆棧的程序表示提供了平台無關性,因為它不依賴任何特定本地平台
的 CPU 中可用寄存器的數目。可在操作數堆棧上執行的操作的定義都獨立於所有本地處理器的指令集。Java
虛擬機(JVM)規范定義了這些位元組碼的執行(參見 參考資料)。執行 Java 程序時,用於任何特定本地平台的任何 JRE 都必須遵守 JVM
規范中列出的規則。

因為基於堆棧的本地平台很少(Intel X87 浮點數協處理器是一個明顯的例外),所以大多數本地平台不能直接執行 Java 位元組碼。為了解決這個問題,早期的 JRE 通過解釋位元組碼來執行 Java 程序。即 JVM 在一個循環中重復操作:

◆獲取待執行的下一個位元組碼;

◆解碼;

◆從操作數堆棧獲取所需的操作數;

◆按照 JVM 規范執行操作;

◆將結果寫回堆棧。

這種方法的優點是其簡單性:JRE 開發人員只需編寫代碼來處理每種位元組碼即可。並且因為用於描述操作的位元組碼少於 255 個,所以實現的成本比較低。當然,缺點是性能:這是一個早期造成很多人對 Java 平台不滿的問題,盡管擁有很多其他優點。

解決與 C 或 C++ 之類的語言之間的性能差距意味著,使用不會犧牲可移植性的方式開發用於 Java 平台的本地代碼編譯。

編譯 Java 代碼

盡管傳聞中 Java 編程的 「一次編寫,隨處運行」
的口號可能並非在所有情況下都嚴格成立,但是對於大量的應用程序來說情況確實如此。另一方面,本地編譯本質上是特定於平台的。那麼 Java
平台如何在不犧牲平台無關性的情況下實現本地編譯的性能?答案就是使用 JIT 編譯器進行動態編譯,這種方法已經使用了十年(參見圖 1):

圖 1. JIT 編譯器

使用 JIT 編譯器時,Java
程序按每次編譯一個方法的形式進行編譯,因為它們在本地處理器指令中執行以獲得更高的性能。此過程將生成方法的一個內部表示,該表示與位元組碼不同但是其級
別要高於目標處理器的本地指令。(IBM JIT
編譯器使用一個表達式樹序列表示方法的操作。)編譯器執行一系列優化以提高質量和效率,最後執行一個代碼生成步驟將優化後的內部表示轉換成目標處理器的本
地指令。生成的代碼依賴運行時環境來執行一些活動,比如確保類型轉換的合法性或者對不能在代碼中直接執行的某些類型的對象進行分配。JIT
編譯器操作的編譯線程與應用程序線程是分開的,因此應用程序不需要等待編譯的執行。

圖 1 中還描述了用於觀察執行程序行為的分析框架,通過周期性地對線程取樣找出頻繁執行的方法。該框架還為專門進行分析的方法提供了工具,用來存儲程序的此次執行中可能不會改變的動態值。

因為這個 JIT 編譯過程在程序執行時發生,所以能夠保持平台無關性:發布的仍然是中立的 Java 平台代碼。C 和 C++ 之類的語言缺乏這種優點,因為它們在程序執行前進行本地編譯;發布給(本地平台)執行環境的是本地代碼。

挑戰

盡管通過 JIT 編譯保持了平台無關性,但是付出了一定代價。因為在程序執行時進行編譯,所以編譯代碼的時間將計入程序的執行時間。任何編寫過大型 C 或 C++ 程序的人都知道,編譯過程往往較慢。

為了克服這個缺點,現代的 JIT
編譯器使用了下面兩種方法的任意一種(某些情況下同時使用了這兩種方法)。第一種方法是:編譯所有的代碼,但是不執行任何耗時多的分析和轉換,因此可以快
速生成代碼。由於生成代碼的速度很快,因此盡管可以明顯觀察到編譯帶來的開銷,但是這很容易就被反復執行本地代碼所帶來的性能改善所掩蓋。第二種方法是:
將編譯資源只分配給少量的頻繁執行的方法(通常稱作熱方法)。低編譯開銷更容易被反復執行熱代碼帶來的性能優勢掩蓋。很多應用程序只執行少量的熱方法,因
此這種方法有效地實現了編譯性能成本的最小化。

動態編譯器的一個主要的復雜性在於權衡了解編譯代碼的預期獲益使方法的執行對整個程序的性能起多大作用。一個極端的例子是,程序執行後,您非常清楚哪些方
法對於這個特定的執行的性能貢獻最大,但是編譯這些方法毫無用處,因為程序已經完成。而在另一個極端,程序執行前無法得知哪些方法重要,但是每種方法的潛
在受益都最大化了。大多數動態編譯器的操作介於這兩個極端之間,方法是權衡了解方法預期獲益的重要程度。

Java 語言需要動態載入類這一事實對 Java
編譯器的設計有著重要的影響。如果待編譯代碼引用的其他類還沒有載入怎麼辦?比如一個方法需要讀取某個尚未載入的類的靜態欄位值。Java
語言要求第一次執行類引用時載入這個類並將其解析到當前的 JVM
中。直到第一次執行時才解析引用,這意味著沒有地址可供從中載入該靜態欄位。編譯器如何處理這種可能性?編譯器生成一些代碼,用於在沒有載入類時載入並解
析類。類一旦被解析,就會以一種線程安全的方式修改原始代碼位置以便直接訪問靜態欄位的地址,因為此時已獲知該地址。

IBM JIT
編譯器中進行了大量的努力以便使用安全而有效率的代碼補丁技術,因此在解析類之後,執行的本地代碼只載入欄位的值,就像編譯時已經解析了欄位一樣。另外一
種方法是生成一些代碼,用於在查明欄位的位置以前一直檢查是否已經解析欄位,然後載入該值。對於那些由未解析變成已解析並被頻繁訪問的欄位來說,這種簡單
的過程可能帶來嚴重的性能問題。

動態編譯的優點

動態地編譯 Java 程序有一些重要的優點,甚至能夠比靜態編譯語言更好地生成代碼,現代的 JIT 編譯器常常向生成的代碼中插入掛鉤以收集有關程序行為的信息,以便如果要選擇方法進行重編譯,就可以更好地優化動態行為。

關於此方法的一個很好的例子是收集一個特定 array操作的長度。如果發現每次執行操作時該長度基本不變,則可以為最頻繁使用的

array長度生成專門的代碼,或者可以調用調整為該長度的代碼序列。由於內存系統和指令集設計的特性,用於復制內存的最佳通用常式的執行速度通
常比用於復制特定長度的代碼慢。例如,復制 8
個位元組的對齊的數據可能需要一到兩條指令直接復制,相比之下,使用可以處理任意位元組數和任意對齊方式的一般復制循環可能需要 10 條指令來復制同樣的 8

個位元組。但是,即使此類專門的代碼是為某個特定的長度生成的,生成的代碼也必須正確地執行其他長度的復制。生成代碼只是為了使常見長度的操作執行得更快,
因此平均下來,性能得到了改進。此類優化對大多數靜態編譯語言通常不實用,因為所有可能的執行中長度恆定的操作比一個特定程序執行中長度恆定的操作要少得
多。

此類優化的另一個重要的例子是基於類層次結構的優化。例如,一個虛方法調用需要查看接收方對象的類調用,以便找出哪個實際目標實現了接收方對象的虛方法。
研究表明:大多數虛調用只有一個目標對應於所有的接收方對象,而 JIT
編譯器可以為直接調用生成比虛調用更有效率的代碼。通過分析代碼編譯後類層次結構的狀態,JIT
編譯器可以為虛調用找到一個目標方法,並且生成直接調用目標方法的代碼而不是執行較慢的虛調用。當然,如果類層次結構發生變化,並且出現另外的目標方法,
則 JIT
編譯器可以更正最初生成的代碼以便執行虛調用。在實踐中,很少需要作出這些更正。另外,由於可能需要作出此類更正,因此靜態地執行這種優化非常麻煩。

因為動態編譯器通常只是集中編譯少量的熱方法,所以可以執行更主動的分析來生成更好的代碼,使編譯的回報更高。事實上,大部分現代的
JIT
編譯器也支持重編譯被認為是熱方法的方法。可以使用靜態編譯器(不太強調編譯時間)中常見的非常主動的優化來分析和轉換這些頻繁執行的方法,以便生成更好
的代碼並獲得更高的性能。

這些改進及其他一些類似的改進所產生的綜合效果是:對於大量的 Java 應用程序來說,動態編譯已經彌補了與 C 和 C++ 之類語言的靜態本地編譯性能之間的差距,在某些情況下,甚至超過了後者的性能。

缺點

但是,動態編譯確實具有一些缺點,這些缺點使它在某些情況下算不上一個理想的解決方案。例如,因為識別頻繁執行的方法以及編譯這些方法需要時間,所以應用
程序通常要經歷一個准備過程,在這個過程中性能無法達到其最高值。在這個准備過程中出現性能問題有幾個原因。首先,大量的初始編譯可能直接影響應用程序的
啟動時間。不僅這些編譯延遲了應用程序達到穩定狀態的時間(想像 Web
伺服器經
歷一個初始階段後才能夠執行實際有用的工作),而且在准備階段中頻繁執行的方法可能對應用程序的穩定狀態的性能所起的作用也不大。如果 JIT
編譯會延遲啟動又不能顯著改善應用程序的長期性能,則執行這種編譯就非常浪費。雖然所有的現代 JVM
都執行調優來減輕啟動延遲,但是並非在所有情況下都能夠完全解決這個問題。

其次,有些應用程序完全不能忍受動態編譯帶來的延遲。如 GUI 介面之類互動式應用程序就是這樣的例子。在這種情況下,編譯活動可能對用戶使用造成不利影響,同時又不能顯著地改善應用程序的性能。

最後,用於實時環境並具有嚴格的任務時限的應用程序可能無法忍受編譯的不確定性性能影響或動態編譯器本身的內存開銷。

因此,雖然 JIT 編譯技術已經能夠提供與靜態語言性能相當(甚至更好)的性能水平,但是動態編譯並不適合於某些應用程序。在這些情況下,Java 代碼的提前(Ahead-of-time,AOT)編譯可能是合適的解決方案。

AOT Java 編譯

大致說來,Java 語言本地編譯應該是為傳統語言(如 C++ 或
Fortran)而開發的編譯技術的一個簡單應用。不幸的是,Java 語言本身的動態特性帶來了額外的復雜性,影響了 Java
程序靜態編譯代碼的質量。但是基本思想仍然是相同的:在程序執行前生成 Java 方法的本地代碼,以便在程序運行時直接使用本地代碼。目的在於避免
JIT 編譯器的運行時性能消耗或內存消耗,或者避免解釋程序的早期性能開銷。

挑戰

動態類載入是動態 JIT 編譯器面臨的一個挑戰,也是 AOT
編譯的一個更重要的問題。只有在執行代碼引用類的時候才載入該類。因為是在程序執行前進行 AOT
編譯的,所以編譯器無法預測載入了哪些類。就是說編譯器無法獲知任何靜態欄位的地址、任何對象的任何實例欄位的偏移量或任何調用的實際目標,甚至對直接調
用(非虛調用)也是如此。在執行代碼時,如果證明對任何這類信息的預測是錯誤的,這意味著代碼是錯誤的並且還犧牲了 Java 的一致性。

因為代碼可以在任何環境中執行,所以類文件可能與代碼編譯時不同。例如,一個 JVM
實例可能從磁碟的某個特定位置載入類,而後面一個實例可能從不同的位置甚至網路載入該類。設想一個正在進行 bug
修復的開發環境:類文件的內容可能隨不同的應用程序的執行而變化。此外,Java 代碼可能在程序執行前根本不存在:比如 Java
反射服務通常在運行時生成新類來支持程序的行為。

缺少關於靜態、欄位、類和方法的信息意味著嚴重限制了 Java 編譯器中優化框架的大部分功能。內聯可能是靜態或動態編譯器應用的最重要的優化,但是由於編譯器無法獲知調用的目標方法,因此無法再使用這種優化。

內聯

內聯是一種用於在運行時生成代碼避免程序開始和結束時開銷的技術,方法是將函數的調用代碼插入到調用方的函數中。但是內聯最大的益處可能是優化方可見的代碼的范圍擴大了,從而能夠生成更高質量的代碼。下面是一個內聯前的代碼示例:

int foo() { int x=2, y=3; return bar(x,y); }final int bar(int a, int b) { return a+b; }

如果編譯器可以證明這個 bar就是 foo()中調用的那個方法,則 bar中的代碼可以取代 foo()中對
bar()的調用。這時,bar()方法是 final類型,因此肯定是 foo()中調用的那個方法。甚至在一些虛調用例子中,動態 JIT
編譯器通常能夠推測性地內聯目標方法的代碼,並且在絕大多數情況下能夠正確使用。編譯器將生成以下代碼:

int foo() { int x=2, y=3; return x+y; }

在這個例子中,簡化前名為值傳播的優化可以生成直接返回
5的代碼。如果不使用內聯,則不能執行這種優化,產生的性能就會低很多。如果沒有解析
bar()方法(例如靜態編譯),則不能執行這種優化,而代碼必須執行虛調用。運行時,實際調用的可能是另外一個執行兩個數字相乘而不是相加的
bar方法。所以不能在 Java 程序的靜態編譯期間直接使用內聯。

AOT
代碼因此必須在沒有解析每個靜態、欄位、類和方法引用的情況下生成。執行時,每個這些引用必須利用當前運行時環境的正確值進行更新。這個過程可能直接影響
第一次執行的性能,因為在第一次執行時將解析所有引用。當然,後續執行將從修補代碼中獲益,從而可以更直接地引用實例、靜態欄位或方法目標。

另外,為 Java 方法生成的本地代碼通常需要使用僅在單個 JVM 實例中使用的值。例如,代碼必須調用 JVM
運行時中的某些運行時常式來執行特定操作,如查找未解析的方法或分配內存。這些運行時常式的地址可能在每次將 JVM 載入到內存時變化。因此 AOT
編譯代碼需要綁定到 JVM 的當前執行環境中,然後才能執行。其他的例子有字元串的地址和常量池入口的內部位置。

在 WebSphere Real Time 中,AOT 本地代碼編譯通過 jxeinajar工具(參見圖 2)來執行。該工具對 JAR 文件中所有類的所有方法應用本地代碼編譯,也可以選擇性地對需要的方法應用本地代碼編譯。結果被存儲到名為 Java eXEcutable (JXE) 的內部格式中,但是也可輕松地存儲到任意的持久性容器中。

您可能認為對所有的代碼進行靜態編譯是最好的方法,因為可以在運行時執行最大數量的本地代碼。但是此處可以作出一些權衡。編譯的方法越多,代碼佔用的內存
就越多。編譯後的本地代碼大概比位元組碼大 10 倍:本地代碼本身的密度比位元組碼小,而且必須包含代碼的附加元數據,以便將代碼綁定到 JVM
中,並且在出現異常或請求堆棧跟蹤時正確執行代碼。構成普通 Java 應用程序的 JAR
文件通常包含許多很少執行的方法。編譯這些方法會消耗內存卻沒有什麼預期收益。相關的內存消耗包括以下過程:將代碼存儲到磁碟上、從磁碟取出代碼並裝入
JVM,以及將代碼綁定到 JVM。除非多次執行代碼,否則這些代價不能由本地代碼相對解釋的性能優勢來彌補。

圖 2. jxeinajar

跟大小問題相違背的一個事實是:在編譯過的方法和解釋過的方法之間進行的調用(即編譯過的方法調用解釋過的方法,或者相反)可能比這兩類方法各自內部之間
進行的調用所需的開銷大。動態編譯器通過最終編譯所有由 JIT
編譯代碼頻繁調用的那些解釋過的方法來減少這項開銷,但是如果不使用動態編譯器,則這項開銷就不可避免。因此如果是選擇性地編譯方法,則必須謹慎操作以使
從已編譯方法到未編譯方法的轉換最小化。為了在所有可能的執行中都避免這個問題而選擇正確的方法會非常困難。
優點
雖然 AOT 編譯代碼具有上述的缺點和挑戰,但是提前編譯 Java 程序可以提高性能,尤其是在不能將動態編譯器作為有效解決方案的環境中。

可以通過謹慎地使用 AOT 編譯代碼加快應用程序啟動,因為雖然這種代碼通常比 JIT
編譯代碼慢,但是卻比解釋代碼快很多倍。此外,因為載入和綁定 AOT
編譯代碼的時間通常比檢測和動態編譯一個重要方法的時間少,所以能夠在程序執行的早期達到那樣的性能。類似地,互動式應用程序可以很快地從本地代碼中獲
益,無需使用引起較差響應能力的動態編譯。

RT 應用程序也能從 AOT 編譯代碼中獲得重要的收益:更具確定性的性能超過了解釋的性能。WebSphere Real Time
使用的動態 JIT 編譯器針對在 RT 系統中的使用進行了專門的調整。使編譯線程以低於 RT
任務的優先順序操作,並且作出了調整以避免生成帶有嚴重的不確定性性能影響的代碼。但是,在一些 RT 環境中,出現 JIT
編譯器是不可接受的。此類環境通常需要最嚴格的時限管理控制。在這些例子中,AOT
編譯代碼可以提供比解釋過的代碼更好的原始性能,又不會影響現有的確定性。消除 JIT
編譯線程甚至消除了啟動更高優先順序 RT 任務時發生的線程搶占所帶來的性能影響。

優缺點統計

動態(JIT)編譯器支持平台中立性,並通過利用應用程序執行的動態行為和關於載入的類及其層次結構的信息來生成高質量的代碼。但是
JIT
編譯器具有一個有限的編譯時預算,而且會影響程序的運行時性能。另一方面,靜態(AOT)編譯器則犧牲了平台無關性和代碼質量,因為它們不能利用程序的動
態行為,也不具有關於載入的類或類層次結構的信息。AOT 編譯擁有有效無限制的編譯時預算,因為 AOT
編譯時間不會影響運行時性能,但是在實踐中開發人員不會長期等待靜態編譯步驟的完成。

表 1 總結了本文討論的 Java 語言動態和靜態編譯器的一些特性:

表 1. 比較編譯技術

兩種技術都需要謹慎選擇編譯的方法以實現最高的性能。對動態編譯器而言,編譯器自身作出決策,而對於靜態編譯器,由開發人員作出選擇。讓
JIT 編譯器選擇編譯的方法是不是優點很難說,取決於編譯器在給定情形中推斷能力的好壞。在大多數情況下,我們認為這是一種優點。

因為它們可以最好地優化運行中的程序,所以 JIT 編譯器在提供穩定狀態性能方面更勝一籌,而這一點在大量的生產 Java
系統中最為重要。靜態編譯可以產生最佳的互動式性能,因為沒有運行時編譯行為來影響用戶預期的響應時間。通過調整動態編譯器可以在某種程度上解決啟動和確
定性性能問題,但是靜態編譯在需要時可提供最快的啟動速度和最高級別的確定性。表 2 在四種不同的執行環境中對這兩種編譯技術進行了比較:

表 2. 使用這些技術的最佳環境

圖 3 展示了啟動性能和穩定狀態性能的總體趨勢:

圖 3. AOT 和 JIT 的性能對比

使用 JIT 編譯器的初始階段性能很低,因為要首先解釋方法。隨著編譯方法的增多及 JIT
執行編譯所需時間的縮短,性能曲線逐漸升高最後達到性能峰值。另一方面,AOT 編譯代碼啟動時的性能比解釋的性能高很多,但是無法達到 JIT
編譯器所能達到的最高性能。將靜態代碼綁定到 JVM 實例中會產生一些開銷,因此開始時的性能比穩定狀態的性能值低,但是能夠比使用 JIT
編譯器更快地達到穩定狀態的性能水平。

沒有一種本地代碼編譯技術能夠適合所有的 Java
執行環境。某種技術所擅長的通常正是其他技術的弱項。出於這個原因,需要同時使用這兩種編譯技術以滿足 Java
應用程序開發人員的要求。事實上,可以結合使用靜態和動態編譯以便提供最大可能的性能提升 —— 但是必須具備平台無關性,它是 Java
語言的主要賣點,因此不成問題。

結束語

本文探討了 Java 語言本地代碼編譯的問題,主要介紹了 JIT 編譯器形式的動態編譯和靜態 AOT 編譯,比較了二者的優缺點。

雖然動態編譯器在過去的十年裡實現了極大的成熟,使大量的各種 Java 應用程序可以趕上或超過靜態編譯語言(如 C++ 或
Fortran)所能夠達到的性能。但是動態編譯在某些類型的應用程序和執行環境中仍然不太合適。雖然 AOT
編譯號稱動態編譯缺點的萬能解決方案,但是由於 Java 語言本身的動態特性,它也面臨著提供本地編譯全部潛能的挑戰。

這兩種技術都不能解決 Java 執行環境中本地代碼編譯的所有需求,但是反過來又可以在最有效的地方作為工具使用。這兩種技術可以相互補充。能夠恰當地使用這兩種編譯模型的運行時系統可以使很大范圍內的應用程序開發環境中的開發人員和用戶受益。

❽ 配置Linux內核的時候,驅動的靜態編譯和動態編譯有什麼區別

驅動的動態編譯會生成.ko文件,系統啟動後需要載入該驅動後才能使用相應設備。
而靜態編譯則直接編譯進內核,系統啟動的時候會自動載入該驅動。
靜態編譯太多驅動至內核,會導致內核體積過大,啟動時間較長。而動態編譯則比較自由靈活,需要用的時候即載入,不需要的時候即卸載。我以前在EasyARM-iMX280的學習手冊里看到寫得很清楚,你可以去看看的。

❾ ahci和IDE的區別

AHCI和IDE的區別如下:

1、概念不同

AHCI:是在Intel的指導下,由多家公司聯合研發的介面標准,它允許存儲驅動程序啟用高級串列 ATA 功能,如本機命令隊列和熱插拔,其研發小組成員主要包括Intel、AMD、戴爾、Marvell、邁拓、微軟、Red Hat、希捷和StorageGear等著名企業。

IDE:一般指集成開發環境,是用於提供程序開發環境的應用程序,一般包括代碼編輯器、編譯器、調試器和圖形用戶界面等工具。

2、開發背景不同

AHCI:本質是一種PCI類設備,在系統內存匯流排和串列ATA設備內部邏輯之間扮演一種通用介面的角色。這類設備描述了一個含控制和狀態區域、命令序列入口表的通用系統內存結構;每個命令表入口包含SATA設備編程信息,和一個指向描述表的指針。

IDE:從開始在主機或終端機開發程序,IDE才漸漸的成為必要的工具。早期的編程語言在送進編譯器處理之前,必須要先經過流程圖、撰寫表格、打卡,所以當時並不需要IDE。Basic是第一個有IDE的編程語言,同時也是第一個可以直接在主機或終端機前開發程序,他的IDE是採取命令行的方式,並不像現代的IDE使用選單和圖形化。

3、功能不同

AHCI:是高級串列,ATA。

IDE:集成了代碼編寫功能、分析功能、編譯功能、調試功能等一體化的開發軟體服務套。

(9)熱載入和自動編譯的區別擴展閱讀:

IDE的優點

1、節省時間和精力。IDE的目的就是要讓開發更加快捷方便,通過提供工具和各種性能來幫助開發者組織資源,減少失誤,提供捷徑。

2、建立統一標准。當一組程序員使用同一個開發環境時,就建立了統一的工作標准,當IDE提供預設的模板,或者不同團隊分享代碼庫時,這一效果就更加明顯了。

3、管理開發工作。首先,IDE提供文檔工具,可以自動輸入開發者評論,或者迫使開發者在不同區域編寫評論。其次,IDE可以展示資源,更便於發現應用所處位置,無需在文件系統裡面艱難的搜索。

❿ java web中什麼是熱載入

代碼修改了不是要解析(或者編譯)嗎,生成.class文件啊,然後不是要拷貝到容器目錄下嗎(所謂發布程序),
很久很久以前,程序員修改了代碼,發布class文件之後,伺服器是要重新啟動的(相當費時間,於是喝杯咖啡啥的,java圖標...)。
現在很多伺服器容器,不許要重啟了,修改的class文件直接可以生效。所謂"熱載入"。

閱讀全文

與熱載入和自動編譯的區別相關的資料

熱點內容
gz壓縮文件夾 瀏覽:177
字母h從右往左跑的c語言編程 瀏覽:127
安卓手機如何擁有蘋果手機橫條 瀏覽:765
業余編程語言哪個好學 瀏覽:137
按照文件夾分個壓縮 瀏覽:104
航空工業出版社單片機原理及應用 瀏覽:758
如何在電信app上綁定親情號 瀏覽:376
安卓的怎麼用原相機拍月亮 瀏覽:805
配音秀為什麼顯示伺服器去配音了 瀏覽:755
c盤清理壓縮舊文件 瀏覽:325
app怎麼交付 瀏覽:343
圖蟲app怎麼才能轉到金幣 瀏覽:175
如何做徵文app 瀏覽:446
用什麼app管理斐訊 瀏覽:169
安卓如何下載寶可夢劍盾 瀏覽:166
編譯器開發屬於哪個方向 瀏覽:940
megawin單片機 瀏覽:687
以色列加密貨幣監督 瀏覽:909
程序員前端現在怎麼樣 瀏覽:499
伺服器和介面地址ping不通 瀏覽:557