欧美人与禽2O2O性论交,秋霞免费视频,国产美女视频免费观看网址,国产成人亚洲综合网色欲网

Java 和低延遲(java延時任務)

可以構(gòu)建在對外部事件的響應時間方面滿足非常嚴格的要求的 Java 應用程序,但這確實需要仔細考慮。本文討論了在 Java 中開發(fā)低延遲代碼時需要考慮的事項。

每日分享最新,最流行的軟件開發(fā)知識與最新行業(yè)趨勢,希望大家能夠一鍵三連,多多支持,跪求關(guān)注,點贊,留言。

Java 和低延遲(java延時任務)

我已經(jīng)記不清有多少次我被告知 Java 不是一種適合用于開發(fā)以性能為主要考慮因素的應用程序的語言。我的第一反應通常是要求澄清“性能”作為兩個最常見的衡量標準的實際含義 – 吞吐量和延遲,有時會相互沖突,并且針對其中一個進行優(yōu)化的方法可能會對另一個產(chǎn)生不利影響.

存在用于開發(fā) Java 應用程序的技術(shù),這些技術(shù)可以匹配甚至超過使用更傳統(tǒng)的用于此目的的語言構(gòu)建的應用程序的性能要求。但是,從延遲的角度來看,即使這樣也可能不足以獲得最佳性能。Java 應用程序仍然必須依賴操作系統(tǒng)來提供對底層硬件的訪問。通常,延遲敏感(通常稱為“實時”)應用程序在幾乎可以直接訪問底層硬件時運行得最好,這同樣適用于 Java。在本文中,我們將介紹一些當我們希望我們的應用程序最有效地利用系統(tǒng)資源時可以采取的方法。

Java 從一開始就被設計為在廣泛的硬件和系統(tǒng)架構(gòu)中以二進制級別可移植。這是通過設計和實現(xiàn)虛擬機(執(zhí)行平臺的抽象模型)并讓它執(zhí)行Java 源編譯器的輸出來完成的。爭論的焦點是遷移到不同類型的硬件平臺只需要移植虛擬機。應用程序和庫無需修改即可運行(“一次編寫,到處運行”的口號)。

但是,具有嚴格延遲和性能要求的應用程序通常需要在執(zhí)行時盡可能接近硬件 – 他們希望從硬件中榨取所有可能的性能,并且不想要純粹為了可移植性或像動態(tài)內(nèi)存管理這樣的抽象編程概念阻礙了。

多年來,Java 虛擬機已經(jīng)發(fā)展成為一個極其復雜的執(zhí)行平臺,可以在運行時從 Java 字節(jié)碼生成機器代碼,并根據(jù)動態(tài)收集的指標優(yōu)化該代碼。這是靜態(tài)編譯語言(如 C )無法做到的,因為它們沒有所需的運行時信息。選擇數(shù)據(jù)結(jié)構(gòu)和算法時的謹慎方法可以最大限度地減少甚至消除垃圾收集的需要——這可能是 Java 運行時環(huán)境中最明顯的一個方面,它阻止了一致的延遲時間。

但歸根結(jié)底,Java 虛擬機只是——虛擬的——它需要在操作系統(tǒng)之上運行以管理其對硬件平臺的訪問。無論該操作系統(tǒng)是 Linux(可能是服務器端環(huán)境中使用最廣泛的)、Windows 還是其他操作系統(tǒng),問題仍然存在。

Linux 的“問題”

Linux作為 Unix 操作系統(tǒng)家族的一員,多年來一直在發(fā)展。Unix 的第一個版本是在 1960 年代后期開發(fā)的。它首先在學術(shù)界和研究界發(fā)展壯大并獲得了極大的知名度,然后在商業(yè)界以各種形式出現(xiàn)。Linux 已成為 Unix 的主要變體——盡管它仍然保留了許多原始特性。如今,隨著基于容器的執(zhí)行環(huán)境和云的出現(xiàn),它的主導地位幾乎已經(jīng)完全。

但是,從實時或延遲敏感型應用程序的角度來看,Linux/Unix 確實存在問題。這些主要源于 Unix 被設計為分時系統(tǒng)這一基本事實。它最初的硬件平臺是微型計算機,同時被許多不同的用戶共享。所有用戶都有自己的工作要做,而 Unix 竭盡全力確保所有人都能“公平地分享”計算機資源。

實際上,操作系統(tǒng)會偏愛執(zhí)行大量 I/O 的用戶——包括在終端與系統(tǒng)交互——以犧牲主要執(zhí)行計算的任務(所謂的 CPU 密集型作業(yè))為代價。當我們考慮到當時的計算機幾乎都是單 CPU(單核)時,這是有道理的。

然而,隨著多 CPU 計算機的發(fā)展,需要對 Unix 操作系統(tǒng)的核心進行一些認真的重新設計,以允許有效地使用這些執(zhí)行內(nèi)核。但同樣的方法仍然適用,交互式任務總是比 CPU 密集型任務更受歡迎。有了多個內(nèi)核可用,最終效果仍然是提高整體性能。

如今,幾乎每臺計算機都將擁有多個內(nèi)核,從手機等移動設備到工作站,再到服務器級機器。檢查這些環(huán)境并查看我們是否可以采取不同的方法來改進平臺以更有效地支持實時、延遲敏感的應用程序似乎是有效的。

我們?nèi)绾谓鉀Q這些問題?

在我工作的 Chronicle Software,我們已經(jīng)開發(fā)了許多開源庫來支持構(gòu)建針對低延遲進行優(yōu)化的應用程序,這是基于該領域多年的經(jīng)驗。本文的其余部分描述了我們學到的一些幫助我們實現(xiàn)這一目標的東西。

Java 運行時

影響 Java 應用程序延遲的主要問題是那些與垃圾收集堆管理和使用鎖同步訪問共享資源有關(guān)的問題。存在解決這兩個問題的技術(shù),盡管它們確實需要開發(fā)人員在一定程度上偏離慣用的 Java 編程風格。理想情況下,我們會使用封裝較低級別細節(jié)和專門技術(shù)的庫,但我們確實需要了解“幕后”正在發(fā)生的事情。

為低延遲應用程序設計的框架和庫青睞的一種方法是繞過 Java 垃圾收集器,利用不屬于正常 Java 堆的內(nèi)存(稱為“堆外”內(nèi)存)。內(nèi)存使用正常的操作系統(tǒng)機制映射到持久存儲,或者通過網(wǎng)絡連接復制到其他系統(tǒng)。

使用這種方法的明顯優(yōu)勢是對內(nèi)存的訪問不受垃圾收集器的非確定性干預。缺點是管理在這些區(qū)域中創(chuàng)建的對象的生命周期成為應用程序或庫的責任。

現(xiàn)代應用程序的通用架構(gòu)在組件之間包含某種形式的通信,通?;谙鬟f。消息在通信過程中被序列化為 JSONYAML 等標準格式或從標準格式反序列化,提供此功能的庫通??梢砸敫呒墑e的對象分配。經(jīng)過仔細考慮,可以選擇經(jīng)過精心設計的庫,以最大限度地減少新 Java 對象的創(chuàng)建,從而對性能產(chǎn)生積極影響。

從 Java 的早期開始,對共享可變數(shù)據(jù)的并發(fā)訪問就使用互斥鎖進行同步。如果一個線程試圖獲取另一個線程持有的鎖,那么它會被阻塞,直到鎖被釋放。在多核環(huán)境中,可以使用不需要獲取線程阻塞的替代技術(shù)來實現(xiàn)同步,并且已經(jīng)表明,在大多數(shù)情況下,這對減少延遲有積極的影響。

編寫此類代碼并不簡單,但是,可以在標準 Java 庫中的 Lock 接口后面進行封裝,甚至可以進一步定義允許通過標準 API 進行安全、無鎖并發(fā)訪問的數(shù)據(jù)結(jié)構(gòu)。一些標準的 Java Collections 庫使用這種方法,盡管這對用戶是透明的。

Linux

公平地說,多年來,Unix 的“實時”變體已經(jīng)為專門的應用程序提供了不同的執(zhí)行環(huán)境。雖然這些通常是利基產(chǎn)品,但現(xiàn)在許多這些方法和功能在 Unix 和 Linux 的主流發(fā)行版中都可用。

最小化延遲的特性通常分為兩類,內(nèi)存管理和線程調(diào)度。

Linux 進程中的所有內(nèi)存,包括 Java 的垃圾收集堆,都會被臨時“換出”到磁盤,以便其他進程可以在需要將內(nèi)存重新帶入之前將 RAM 用于自己的目的。這一切都會發(fā)生對進程完全透明,內(nèi)存中的數(shù)據(jù)和后備存儲中的數(shù)據(jù)之間的訪問時間差異可能有幾個數(shù)量級。當然,堆外內(nèi)存也有同樣的行為。

但是,現(xiàn)代 Unix 和 Linux 系統(tǒng)允許標記內(nèi)存區(qū)域,以便操作系統(tǒng)在尋找要從進程中回收的區(qū)域時忽略它們。這意味著,對于該進程中的那些內(nèi)存區(qū)域,內(nèi)存訪問時間將是一致的(并且總體上被認為更快)。不得不說,在繁忙的Java應用程序中,訪問進程內(nèi)存的頻率會降低該內(nèi)存被分頁的可能性,但風險仍然存在。

以這種方式固定一個進程的內(nèi)存意味著其他進程的內(nèi)存更少,這可能會因此受到影響,但在“實時”世界中,我們必須有點自私!

為低延遲而設計的數(shù)據(jù)結(jié)構(gòu)通常會默認或通過選項提供將其內(nèi)存鎖定或固定在 RAM 中的能力。

Java 程序中的線程,就像來自其他應用程序甚至操作系統(tǒng)任務的線程一樣,可以訪問由稱為調(diào)度程序的操作系統(tǒng)組件管理的 CPU。調(diào)度程序有一組策略,用于決定選擇哪些需要訪問 CPU 的線程(稱為 Runnable 線程)——通常 Runnable 線程比 CPU 多。

如前所述,Unix/Linux 中的傳統(tǒng)調(diào)度策略旨在支持交互式線程而不是 CPU 綁定線程。如果我們試圖運行對延遲敏感的應用程序,這對我們沒有幫助——我們希望我們的線程以某種方式優(yōu)先于其他非延遲敏感的線程。

現(xiàn)代 Unix/Linux 系統(tǒng)提供了可以提供這些功能的替代調(diào)度策略,通過允許將線程調(diào)度優(yōu)先級固定在高級別,以便它們在可運行時總是從其他線程接管 CPU 資源,這意味著它們可以更多地響應事件迅速地。

但也可以進一步影響調(diào)度程序的行為。通常,在管理線程時會使用所有可用的 CPU 資源。如今,可以更改調(diào)度程序使用哪些 CPU。我們可以從調(diào)度程序可用的 CPU 中完全移除 CPU,并將它們專門用于我們的專用線程。

或者,我們可以將 CPU 分成組,并將一組 CPU 與特定的線程組相關(guān)聯(lián)。此功能是 Linux 更通用的資源管理組件(稱為組)的一部分。它構(gòu)成了 Linux 對虛擬化的支持的一部分,并且是實現(xiàn)容器的關(guān)鍵,例如在現(xiàn)代環(huán)境中由 Docker 生成的容器。但是,它可以通過特定的系統(tǒng)調(diào)用用于一般應用程序。

就像上面描述的內(nèi)存鎖定一樣,我們是自私的,因為這樣做顯然會對系統(tǒng)的其他部分產(chǎn)生負面影響。需要非常小心地配置以獲得最佳結(jié)果,因為錯誤的可能性很高,而且出錯的后果可能很嚴重。

結(jié)論

編寫和部署低延遲應用程序是一項高技能活動,不僅需要了解所使用的語言,還需要了解應用程序運行的環(huán)境。在本文中,我概述了一些需要考慮的領域,以及如何解決這些問題。

資源

要詳細了解本文中討論的一些主題,請查看本書。

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號
公眾號
在線咨詢
分享本頁
返回頂部