在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

何利用PMC來發(fā)現(xiàn)JVM原生代碼的瓶頸?

Linux閱碼場 ? 來源:Linux閱碼場 ? 2023-03-14 09:55 ? 次閱讀

本文通過對CPU層面的代碼挖掘,發(fā)現(xiàn)JVM存在的問題,并通過對JVM打補(bǔ)丁的方式解決了大實(shí)例下性能不足的問題。

在前面的文章中,我們概述了可觀測性的三大領(lǐng)域:整體范圍,微服務(wù)和實(shí)例。我們描述了洞察每個(gè)領(lǐng)域所使用的工具和技術(shù)。然而,還有一類問題需要深入到CPU微體系架構(gòu)中。本文我們將描述一個(gè)此類問題,并使用工具來解決該問題。

問題概述

問題起始于一個(gè)常規(guī)遷移。在Netflix,我們會定期對負(fù)載進(jìn)行重新評估來優(yōu)化可用容量的利用率。我們計(jì)劃將一個(gè)Java微服務(wù)(暫且稱之為GS2)遷移到一個(gè)更大的AWS實(shí)例上,規(guī)格從m5.4xl(16 vCPU)變?yōu)閙5.12xl(48 vCPU)。GS2是計(jì)算密集型的,因此CPU就成為了受限資源。雖然我們知道,隨著vCPU數(shù)量的增長,吞吐量幾乎不可能實(shí)現(xiàn)線性增長,但可以近線性增長。

在大型實(shí)例上進(jìn)行整合可以分?jǐn)偤笈_任務(wù)產(chǎn)生的開銷,為請求留出更多的資源,并可以抵消亞線性縮放。由于12xl實(shí)例的vCPU數(shù)是4xl實(shí)例的3倍,因此我們預(yù)期每個(gè)實(shí)例的吞吐量能夠提升3倍。在快速進(jìn)行了一次金絲雀測試后發(fā)現(xiàn)沒有發(fā)現(xiàn)錯(cuò)誤,并展示了更低的延遲,該結(jié)果符合預(yù)期,在我們的標(biāo)準(zhǔn)金絲雀配置中,會將流量平均路由到運(yùn)行在4xl上的基準(zhǔn)以及運(yùn)行在12xl上的金絲雀上。

由于GS2依賴 AWS EC2 Auto Scaling來達(dá)到目標(biāo)CPU利用率,一開始我們認(rèn)為只要將服務(wù)重新部署到大型實(shí)例上,然后等待 ASG (Auto Scaling Group)達(dá)到目標(biāo)CPU即可,但不幸的是,一開始的結(jié)果與我們的預(yù)期相差甚遠(yuǎn):

89f46414-c185-11ed-bfe3-dac502259ad0.png

第一張圖展示了單節(jié)點(diǎn)吞吐量和CPU利用率之間的關(guān)系,第二張圖展示了平均請求延遲??梢钥吹疆?dāng)CPU大致達(dá)到50%時(shí),平均吞吐量僅僅增加了約25%,大大低于預(yù)期。更糟糕的是,平均延遲則增加了50%,CPU和延遲的波動也更大。GS2是一個(gè)無狀態(tài)服務(wù),它使用輪詢方式的負(fù)載均衡器來接收流量,因此所有節(jié)點(diǎn)應(yīng)該接收到幾乎等量的流量。RPS(Requests Per Second)也顯示了,不同節(jié)點(diǎn)的吞吐量變化很少:

8a0ef9fa-c185-11ed-bfe3-dac502259ad0.png

但當(dāng)我們查看節(jié)點(diǎn)的CPU和延遲時(shí),發(fā)現(xiàn)了一個(gè)奇怪的模式:

8a279b22-c185-11ed-bfe3-dac502259ad0.png

盡管我們確認(rèn)了節(jié)點(diǎn)之間的流量分布相當(dāng),但CPU和延遲度量卻展示了一種非常不同的雙峰分布模式。"低波段"的節(jié)點(diǎn)展示了很低的CPU和延遲,且?guī)缀鯖]有波動,而"高波段"的節(jié)點(diǎn)則具有相當(dāng)高的CPU和延遲,以及更大的波動。我們發(fā)現(xiàn)大約12%的節(jié)點(diǎn)處于低波段中,隨著時(shí)間的推移,這一圖形讓人產(chǎn)生懷疑。兩種波段中,在(節(jié)點(diǎn)上的)JVM的整個(gè)運(yùn)行時(shí)間內(nèi),其性能特點(diǎn)保持一致,即節(jié)點(diǎn)不會跳出其所在的波段。我們就此開始進(jìn)行問題定位。

首次嘗試解決

一開始我們嘗試對比快慢兩種節(jié)點(diǎn)的火焰圖。雖然火焰圖清晰地給出了采樣到的CPU利用率之間的差異,但堆棧之間的分布保持不變,因此并沒有獲得有價(jià)值的結(jié)論。我們轉(zhuǎn)而使用JVM專用的性能采樣,從基本的hotspot 統(tǒng)計(jì)到更詳細(xì)的 JFR (Java Flight Recorder)來比較事件分布,然而還是一無所獲,快慢兩種節(jié)點(diǎn)的事件數(shù)量和分布都沒有出現(xiàn)值得關(guān)注的差異。我們?nèi)匀粦岩蒍IT行為可能有問題,通過對perf-map-agent 采集的符號映射進(jìn)行了一些基本統(tǒng)計(jì),結(jié)果發(fā)現(xiàn)了另一個(gè)死角。

False Sharing

在確定沒有在app-,OS-和JVM層面有所遺漏之后,我們感覺答案可能隱藏在更低的層次。幸運(yùn)的是,m5.12xl實(shí)例類型暴露了一組PMCs (Performance Monitoring Counters, 即PMU 計(jì)數(shù)器),因此我們可以使用PerfSpect采集一組基線計(jì)數(shù)器數(shù)據(jù):

8a482ff4-c185-11ed-bfe3-dac502259ad0.png

在上表中,低CPU/延遲的節(jié)點(diǎn)代表"快節(jié)點(diǎn)",而高CPU/延遲的節(jié)點(diǎn)代表"慢節(jié)點(diǎn)"。除了CPU上的明顯差異外,還看到慢節(jié)點(diǎn)的CPI幾乎是快節(jié)點(diǎn)的3倍。此外,我們還看到了更高的L1緩存活動以及4倍的MACHINE_CLEARS計(jì)數(shù)。一種常見的導(dǎo)致這種現(xiàn)象的原因稱為false sharing,即當(dāng)2個(gè)core讀/寫恰好共享同一L1 cache line的不相關(guān)的變量的模式。Cache line是一個(gè)類似內(nèi)存頁的概念,數(shù)據(jù)塊(x86系統(tǒng)通常為64字節(jié))會進(jìn)出該緩存,過程如下:

8a65b902-c185-11ed-bfe3-dac502259ad0.png

圖中的每個(gè)core都有自己的私有緩存,由于兩個(gè)cores會訪問相同的內(nèi)存空間,因此必須保證緩存一致。這種一致性稱為緩存一致協(xié)議。Thread 0會寫入紅色變量,一致性協(xié)議會將Thread 0中的整個(gè)cache line標(biāo)記為"已修改",并將Thread 1的緩存標(biāo)記為"無效"。

而后,當(dāng)Thread 1讀取藍(lán)色變量時(shí),即使藍(lán)色變量不是"已修改"的,一致性協(xié)議也會強(qiáng)制從緩存中重載上次修改的內(nèi)容(本例中為Thread 0的緩存)到cache line中。解決私有緩存之間的一致性需要花費(fèi)一定時(shí)間并導(dǎo)致CPU暫停。此外,還需要通過最后一級共享緩存的控制器來監(jiān)控來回的一致性流量,進(jìn)而導(dǎo)致更多的暫停。我們認(rèn)為CPU緩存一致性是理所當(dāng)然的,但這種false sharing模式表明,如果只讀取與無關(guān)數(shù)據(jù)相鄰的變量時(shí),就會造成巨大的性能損耗。

根據(jù)已掌握的知識,我們使用 Intel vTune 來進(jìn)行微體系架構(gòu)的性能采樣。通過研究熱點(diǎn)方法以及匯編代碼,我們找出了超過100CPI的指令(執(zhí)行非常慢的指標(biāo)),如下:

8a74318a-c185-11ed-bfe3-dac502259ad0.png

1到6的編號表示源代碼和vTune匯編視圖中對應(yīng)的相同代碼/變量。紅色箭頭表示的CPI值可能屬于上一條指令,這是由于在沒有PEBS(基于處理器事件的采樣)的情況下進(jìn)行了性能采樣,并且通常是被單條指令關(guān)閉的。(5)中的repne scan是一個(gè)相對少見的定義在JVM代碼庫中的操作,我們將這個(gè)代碼片段鏈接到用于子類檢查的例程(在撰寫本文時(shí),JDK主線中存在相同的代碼)中。關(guān)于HotSpot中的子類型檢查的細(xì)節(jié)超出了本文的范疇,有興趣的可以參見2002年出版的Fast Subtype Checking in the HotSpot JVM。

基于該工作負(fù)載中使用的類層次結(jié)構(gòu)的特點(diǎn),我們不斷更新(6)_secondary_super_cache字段的代碼路徑,它是最后找到的二級父類的單元素緩存,注意該字段與_secondary_supers相鄰。_secondary_supers是所有父類的列表,會在掃描開始時(shí)讀取(1)。多線程會對這些字段進(jìn)行讀寫操作,且如果字段(1)和(6)處于相同的cache line,那么就會出現(xiàn)false sharing的情況。在上圖中,我們使用紅色和藍(lán)色高亮了這些導(dǎo)致false sharing的字段。

由于cache line的長度為64字節(jié),而指針長度為8字節(jié),因此這些字段有1/8的機(jī)會讓處于不同的cache line中,有7/8的機(jī)會共享相同的cache line。1/8的即12.5%,這與前面觀測到的快節(jié)點(diǎn)的比例相同。

問題的修復(fù)需要設(shè)涉及對JDK的補(bǔ)丁操作,我們在_secondary_super_cache和_secondary_supers字段中間插入padding來保證它們不會使用相同的cache line。注意我們并沒有修改JDK的功能,只是變更了數(shù)據(jù)布局:

8a98b87a-c185-11ed-bfe3-dac502259ad0.png

部署補(bǔ)丁之后的效果立竿見影。下圖中節(jié)點(diǎn)上的CPU出現(xiàn)了斷崖式下降。在這里,我們可以看到中午進(jìn)行了一次紅黑部署,而新的ASG和修補(bǔ)后的JDK在12:15時(shí)生效:

8aaabee4-c185-11ed-bfe3-dac502259ad0.png

此時(shí)CPU和延遲展示了相似的曲線,慢波段節(jié)點(diǎn)消失不見。

True Sharing

隨著自動擴(kuò)容達(dá)到CPU目標(biāo),但我們注意到單個(gè)節(jié)點(diǎn)仍然無法處理超過150RPS,而我們的目標(biāo)是250RPS。針對補(bǔ)丁版本的JDK進(jìn)行的又一輪vTune性能采樣,發(fā)現(xiàn)圍繞二級父類的緩存查找出現(xiàn)了瓶頸。在經(jīng)過補(bǔ)丁之后又出現(xiàn)了相同的問題,一開始讓人感到困惑,但在仔細(xì)研究后發(fā)現(xiàn),現(xiàn)在我們使用的是true sharing,與false sharing不同,兩個(gè)獨(dú)立的變量共享了一個(gè)cache line,true sharing指相同的變量會被多線程/core讀寫。這種情況下,CPU強(qiáng)制內(nèi)存排序是導(dǎo)致速度減慢的原因。

我們推斷,消除false sharing并提高了總吞吐量會導(dǎo)致增加相同JVM父類緩存代碼路徑的執(zhí)行次數(shù)。本質(zhì)上,我們有更高的執(zhí)行并發(fā)性,但由于CPU強(qiáng)制內(nèi)存排序協(xié)議,導(dǎo)致父類緩存壓力過大。通常的解決方式是避免一起寫入相同的共享變量,這樣就可以有效地繞過JVM的輔助父類緩存。由于此變更改變了JDK的行為,因此我們使用了命令行標(biāo)志,完整的補(bǔ)丁如下:

8aba1cf4-c185-11ed-bfe3-dac502259ad0.png

在禁用父類緩存寫操作之后的結(jié)果如下:

8acf5aa6-c185-11ed-bfe3-dac502259ad0.png

可以看到在CPU達(dá)到目標(biāo)55%的情況下,吞吐量達(dá)到了350 RPS,是我們一開始使用m5.12xl的吞吐量的3.5倍,同時(shí)降低了平均和尾部延遲。

后續(xù)工作

在我們的場景下,禁用寫入二級父類緩存工作良好,雖然這并不一定適用于所有場景,但過程中使用到的方法,工具集可能會對遇到類似現(xiàn)象的人有所幫助。在處理該問題時(shí),我們碰到了 JDK-8180450,這是一個(gè)5年前的bug,它所描述的問題和我們遇到的一模一樣。諷刺的是,在真正找到答案之前,我們并不能確定是這個(gè)bug。

總結(jié)

我們傾向于認(rèn)為現(xiàn)在的JVM是一個(gè)高度優(yōu)化的環(huán)境,在很多場景中展示出了類似C+++的性能。雖然對于大多數(shù)負(fù)載來說是正確的,但需要提醒的是,JVM中運(yùn)行的特定負(fù)載可能不僅僅受應(yīng)用代碼的設(shè)計(jì)和實(shí)現(xiàn)的影響,還會受到JVM自身的影響,本文中我們描述了如何利用PMC來發(fā)現(xiàn)JVM原生代碼的瓶頸,對其打補(bǔ)丁,并且隨后使負(fù)載的吞吐量提升了3倍以上。當(dāng)遇到這類性能問題時(shí),唯一的解決方案是在CPU微體系結(jié)構(gòu)層面進(jìn)行挖掘。intel vTune使用PMC提供了有價(jià)值的信息(如通過m5.12xl實(shí)例類型暴露出來的信息)。在云環(huán)境中跨所有實(shí)例類型和大小公開一組更全面的PMC和PEBS可以為更深入的性能分析鋪平道路,并可能獲得更大的性能收益。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • PMC
    PMC
    +關(guān)注

    關(guān)注

    0

    文章

    89

    瀏覽量

    14944
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    158

    瀏覽量

    12252
  • RPSMA
    +關(guān)注

    關(guān)注

    0

    文章

    2

    瀏覽量

    6185
  • AWS
    AWS
    +關(guān)注

    關(guān)注

    0

    文章

    433

    瀏覽量

    24449

原文標(biāo)題:通過硬件計(jì)數(shù)器,將性能提升3倍之旅

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    jvm的類加載器的整體結(jié)構(gòu)及過程解析

    才能有一個(gè)更清晰的概念。 為了走進(jìn)JVM,深入了解底層,王子打算寫一個(gè)JVM的專題,留下自己對JVM探索的足跡,同時(shí)也希望能幫到小伙伴們更好的理解JVM。 那我們開始吧。 JAVA
    的頭像 發(fā)表于 09-27 15:49 ?3423次閱讀
    <b class='flag-5'>jvm</b>的類加載器的整體結(jié)構(gòu)及過程解析

    進(jìn)擊的 Java ,云原生時(shí)代的蛻變

    部分性能。我們是否可以將AOT做到極致?完全移除字節(jié)碼到本地代碼的編譯過程?原生代碼編譯為了將Java應(yīng)用編譯成本地可執(zhí)行代碼,我們首先要解決JVM
    發(fā)表于 09-17 15:54

    Jvm的整體結(jié)構(gòu)和特點(diǎn)

    的整體結(jié)構(gòu)大致如下:    1、類加載器  類加載器用來加載Java類到JVM虛擬機(jī)中,源代碼程序.java文件在經(jīng)過編譯器編譯之后就被轉(zhuǎn)換成字節(jié)代碼.class文件,類加載器負(fù)責(zé)讀取字節(jié)代碼
    發(fā)表于 01-05 17:23

    為什么低代碼平臺都不采用原生代碼的方式

    聰明的開發(fā)者可以基于傳統(tǒng)的開發(fā)模型以一種更加敏捷的方式開發(fā)移動應(yīng)用。畢竟傳統(tǒng)移動開發(fā)大多遵循瀑布式的開發(fā)模式。低代碼平臺可以很好的做為敏捷開發(fā)工具來使用。下面一起來了解一下相關(guān)的知識吧! 低代碼
    發(fā)表于 05-09 14:51 ?969次閱讀

    Java:JVM虛擬機(jī)的入門知識

    Java開發(fā)現(xiàn)在面試越來越難了,進(jìn)大廠必備的JVM、多線程高并發(fā)這都是最基礎(chǔ)的知識了,今天我們一起學(xué)習(xí)Java虛擬機(jī)入門。
    的頭像 發(fā)表于 07-01 11:43 ?2342次閱讀
    Java:<b class='flag-5'>JVM</b>虛擬機(jī)的入門知識

    如何解決JVM中一個(gè)極小概率發(fā)生的bug

    到 CMS 代碼存在 bug,導(dǎo)致 JVM 在弱內(nèi)存模型的平臺上 Crash。在分析過程中,涉及到 CMS 垃圾回收原理、內(nèi)存屏障、對象頭、以及 ParNew 并行回收算法中多個(gè)線程競爭處理的相關(guān)技術(shù)
    的頭像 發(fā)表于 08-23 17:35 ?3453次閱讀

    JVM內(nèi)存布局的多方面了解

      JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過程中內(nèi)存申請、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的JVM對于內(nèi)存的劃分方式和管理機(jī)制存在部分差異。結(jié)合JVM虛擬機(jī)規(guī)范,一起
    發(fā)表于 07-08 15:09 ?422次閱讀

    JVM內(nèi)存布局詳解

    JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過程中內(nèi)存申請、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的JVM對于內(nèi)存的劃分方式和管理機(jī)制存在部分差異。結(jié)合JVM虛擬機(jī)規(guī)范,一起
    的頭像 發(fā)表于 04-26 10:10 ?550次閱讀
    <b class='flag-5'>JVM</b>內(nèi)存布局詳解

    Spring干掉原生JVM?

    這意味著,除了 Spring 誕生以來就支持的 Java 虛擬機(jī),官方添加了使用 GraalVM 將 Spring 應(yīng)用編譯成原生鏡像的 beta 支持,這樣的話,就能提供一種新的方式部署 Spring 應(yīng)用。Spring Native 支持 Java 和 Kotlin
    的頭像 發(fā)表于 05-05 09:25 ?580次閱讀
    Spring干掉<b class='flag-5'>原生</b><b class='flag-5'>JVM</b>?

    詳解Java虛擬機(jī)的JVM內(nèi)存布局

    JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過程中內(nèi)存申請、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的JVM對于內(nèi)存的劃分方式和管理機(jī)制存在部分差異。結(jié)合JVM虛擬機(jī)規(guī)范,一起
    的頭像 發(fā)表于 07-13 09:52 ?542次閱讀
    詳解Java虛擬機(jī)的<b class='flag-5'>JVM</b>內(nèi)存布局

    jvm的dump太大了怎么分析

    文件需要耗費(fèi)大量的時(shí)間和計(jì)算資源。 然而,這并不意味著我們無法分析和利用JVM dump文件。以下是一些方法和技巧,可幫助我們有效地分析大型JVM dump文件。 使用工具:首先,我們可以使用一些專門用于分析
    的頭像 發(fā)表于 12-05 11:01 ?2797次閱讀

    jvm內(nèi)存分析命令和工具

    JVM內(nèi)存分析是Java開發(fā)和調(diào)優(yōu)過程中非常重要的一部分。通過對JVM內(nèi)存分析命令和工具的深入了解和使用,可以幫助開發(fā)人員識別內(nèi)存泄漏、性能瓶頸等問題,并對Java應(yīng)用進(jìn)行優(yōu)化。 下面將從不同的角度
    的頭像 發(fā)表于 12-05 11:07 ?1237次閱讀

    jvm運(yùn)行時(shí)內(nèi)存區(qū)域劃分

    JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,它是Java編程語言的運(yùn)行環(huán)境。JVM的主要功能是將Java源代碼轉(zhuǎn)換為機(jī)器代碼,并且在運(yùn)行時(shí)管理Java程序
    的頭像 發(fā)表于 12-05 14:08 ?559次閱讀

    jvm和jmm的區(qū)別

    JVM(Java Virtual Machine)和JMM(Java Memory Model)是 Java 開發(fā)者非常熟悉的概念。JVM 是 Java 程序的運(yùn)行環(huán)境,而 JMM 則定義了多線程
    的頭像 發(fā)表于 12-05 14:27 ?1381次閱讀

    聊聊JVM如何優(yōu)化

    首先應(yīng)該明確的是JVM調(diào)優(yōu)不是常規(guī)手段,JVM的存在本身就是為了減輕開發(fā)對于內(nèi)存管理的負(fù)擔(dān),當(dāng)出現(xiàn)性能問題的時(shí)候第一時(shí)間考慮的是代碼邏輯與設(shè)計(jì)方案,以及是否達(dá)到依賴中間件的瓶頸,最后才
    的頭像 發(fā)表于 08-05 17:49 ?514次閱讀
    聊聊<b class='flag-5'>JVM</b>如何優(yōu)化
    主站蜘蛛池模板: 国产午夜视频在线观看网站 | 99热最新在线 | 亚洲资源最新版在线观看 | 日韩一级一欧美一级国产 | 午夜无遮挡怕怕怕免费视频 | 国产高清色播视频免费看 | 在线观看网站黄 | 色www永久免费 | 147西西人体大胆免费网 | 好紧好爽的午夜寂寞视频 | 亚洲人成毛片线播放 | 1024你懂的在线播放欧日韩 | 狠狠亚洲狠狠欧洲2019 | 欧美色亚洲 | 午夜在线观看免费高清在线播放 | 黄www色 | 5278欧美一区 | 天天视频官网天天视频在线 | 三级毛片网站 | 国产精品任我爽爆在线播放6080 | 国产成人夜间影院在线观看 | 久久久噜噜噜久久久午夜 | 三级国产在线 | 男人操女人免费网站 | 九九51精品国产免费看 | 国内精品久久久久影院男同志 | 国产精品毛片久久久久久久 | 国产99在线播放免费 | 天堂中文www在线 | 天天干天天做 | 高清视频在线观看+免费 | 黄 色 录像成 人播放免费 | 夜夜草天天干 | 欧美四虎影院 | 色综合久久久久久久久五月性色 | 一级毛片一片毛 | 一级毛片不收费 | 李老汉和小花的性生生活 | 天天夜干| 黑色丝袜在丝袜福利国产 | 人人做天天爱夜夜爽中字 |