日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

编译hotspot_从Hotspot JIT编译器打印生成的汇编代码

發(fā)布時(shí)間:2023/12/3 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 编译hotspot_从Hotspot JIT编译器打印生成的汇编代码 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

編譯hotspot

有時(shí),在對(duì)Java應(yīng)用程序進(jìn)行性能分析時(shí),有必要了解Hotspot JIT編譯器生成的匯編代碼。 這對(duì)于確定已做出的優(yōu)化決策以及我們的代碼更改如何影響生成的匯編代碼非常有用。 在調(diào)試并發(fā)算法以確保已按預(yù)期應(yīng)用可見(jiàn)性規(guī)則時(shí),知道何時(shí)發(fā)出什么指令也很有用。 通過(guò)這種方式,我已經(jīng)在各種JVM中發(fā)現(xiàn)了很多錯(cuò)誤。

該博客說(shuō)明了如何安裝反匯編程序插件,并提供了針對(duì)特定方法的命令行選項(xiàng)。

安裝

以前,有必要獲取調(diào)試版本,以打印由Hotspot JIT為Oracle / SUN JVM生成的匯編代碼。 從Java 7開(kāi)始,如果在標(biāo)準(zhǔn)Oracle Hotspot JVM中安裝了反匯編程序插件 ,就可以打印生成的匯編代碼。 要為64位Linux安裝插件,請(qǐng)按照以下步驟操作:

  • 從https://kenai.com/projects/base-hsdis/downloads下載適當(dāng)?shù)亩M(jìn)制文件或從源代碼構(gòu)建
  • 在Linux上,將linux-hsdis-amd64.so重命名為libhsdis-amd64.so
  • 將共享庫(kù)復(fù)制到$ JAVA_HOME / jre / lib / amd64 / server
  • 您現(xiàn)在已經(jīng)安裝了插件!

    測(cè)試程序

    為了測(cè)試插件,我們需要一些代碼,這些代碼既對(duì)程序員很有趣,又執(zhí)行得足夠熱,可以被JIT優(yōu)化。 JIT何時(shí)進(jìn)行優(yōu)化的一些細(xì)節(jié)可以在這里找到。 下面的代碼可用于通過(guò)讀寫易失字段來(lái)測(cè)量?jī)蓚€(gè)線程之間的平均延遲。 這些易失字段很有趣,因?yàn)樗鼈冃枰P(guān)聯(lián)的硬件籬笆來(lái)遵守Java內(nèi)存模型 。

    import static java.lang.System.out;public class InterThreadLatency {private static final int REPETITIONS = 100 * 1000 * 1000;private static volatile int ping = -1;private static volatile int pong = -1;public static void main(final String[] args)throws Exception{for (int i = 0; i < 5; i++){final long duration = runTest();out.printf("%d - %dns avg latency - ping=%d pong=%d\n",i,duration / (REPETITIONS * 2),ping,pong);}}private static long runTest() throws InterruptedException{final Thread pongThread = new Thread(new PongRunner());final Thread pingThread = new Thread(new PingRunner());pongThread.start();pingThread.start();final long start = System.nanoTime();pongThread.join();return System.nanoTime() - start;}public static class PingRunner implements Runnable{public void run(){for (int i = 0; i < REPETITIONS; i++){ping = i;while (i != pong){// busy spin}}}}public static class PongRunner implements Runnable{public void run(){for (int i = 0; i < REPETITIONS; i++){while (i != ping){// busy spin}pong = i;}}} }

    印刷匯編代碼

    可以使用以下語(yǔ)句打印所有生成的匯編代碼。

    java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly InterThreadLatency

    但是,這會(huì)使您處于無(wú)法看到樹(shù)木的森林的情況。 通常,針對(duì)特定方法更有用。 對(duì)于此測(cè)試,Hotspot將優(yōu)化run()方法并生成兩次。 一次用于OSR版本,然后一次用于標(biāo)準(zhǔn)JIT版本。 標(biāo)準(zhǔn)的JIT版本如下。

    java -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*PongRunner.run' InterThreadLatencyCompiled method (c2) 10531 5 InterThreadLatency$PongRunner::run (30 bytes)total in heap [0x00007fed81060850,0x00007fed81060b30] = 736relocation [0x00007fed81060970,0x00007fed81060980] = 16main code [0x00007fed81060980,0x00007fed81060a00] = 128stub code [0x00007fed81060a00,0x00007fed81060a18] = 24oops [0x00007fed81060a18,0x00007fed81060a30] = 24scopes data [0x00007fed81060a30,0x00007fed81060a78] = 72scopes pcs [0x00007fed81060a78,0x00007fed81060b28] = 176dependencies [0x00007fed81060b28,0x00007fed81060b30] = 8 Decoding compiled method 0x00007fed81060850: Code: [Entry Point] [Constants]# {method} 'run' '()V' in 'InterThreadLatency$PongRunner'# [sp+0x20] (sp of caller)0x00007fed81060980: mov 0x8(%rsi),%r10d0x00007fed81060984: shl $0x3,%r100x00007fed81060988: cmp %r10,%rax0x00007fed8106098b: jne 0x00007fed81037a60 ; {runtime_call}0x00007fed81060991: xchg %ax,%ax0x00007fed81060994: nopl 0x0(%rax,%rax,1)0x00007fed8106099c: xchg %ax,%ax [Verified Entry Point]0x00007fed810609a0: sub $0x18,%rsp0x00007fed810609a7: mov %rbp,0x10(%rsp) ;*synchronization entry; - InterThreadLatency$PongRunner::run@-1 (line 58)0x00007fed810609ac: xor %r11d,%r11d0x00007fed810609af: mov $0x7ad0fcbf0,%r10 ; {oop(a 'java/lang/Class' = 'InterThreadLatency')}0x00007fed810609b9: jmp 0x00007fed810609d00x00007fed810609bb: nopl 0x0(%rax,%rax,1) ; OopMap{r10=Oop off=64};*goto; - InterThreadLatency$PongRunner::run@15 (line 60)0x00007fed810609c0: test %eax,0xaa1663a(%rip) # 0x00007fed8ba77000;*goto; - InterThreadLatency$PongRunner::run@15 (line 60); {poll}0x00007fed810609c6: nopw 0x0(%rax,%rax,1) ;*iload_1; - InterThreadLatency$PongRunner::run@8 (line 60)0x00007fed810609d0: mov 0x74(%r10),%r9d ;*getstatic ping; - InterThreadLatency::access$000@0 (line 3); - InterThreadLatency$PongRunner::run@9 (line 60)0x00007fed810609d4: cmp %r9d,%r11d0x00007fed810609d7: jne 0x00007fed810609c00x00007fed810609d9: mov %r11d,0x78(%r10)0x00007fed810609dd: lock addl $0x0,(%rsp) ;*putstatic pong; - InterThreadLatency::access$102@2 (line 3); - InterThreadLatency$PongRunner::run@19 (line 65)0x00007fed810609e2: inc %r11d ;*iinc; - InterThreadLatency$PongRunner::run@23 (line 58)0x00007fed810609e5: cmp $0x5f5e100,%r11d0x00007fed810609ec: jl 0x00007fed810609d0 ;*if_icmpeq; - InterThreadLatency$PongRunner::run@12 (line 60)0x00007fed810609ee: add $0x10,%rsp0x00007fed810609f2: pop %rbp0x00007fed810609f3: test %eax,0xaa16607(%rip) # 0x00007fed8ba77000; {poll_return}0x00007fed810609f9: retq ;*iload_1; - InterThreadLatency$PongRunner::run@8 (line 60)0x00007fed810609fa: hlt 0x00007fed810609fb: hlt 0x00007fed810609fc: hlt 0x00007fed810609fd: hlt 0x00007fed810609fe: hlt 0x00007fed810609ff: hlt [Exception Handler] [Stub Code]0x00007fed81060a00: jmpq 0x00007fed8105eaa0 ; {no_reloc} [Deopt Handler Code]0x00007fed81060a05: callq 0x00007fed81060a0a0x00007fed81060a0a: subq $0x5,(%rsp)0x00007fed81060a0f: jmpq 0x00007fed81038c00 ; {runtime_call}0x00007fed81060a14: hlt 0x00007fed81060a15: hlt 0x00007fed81060a16: hlt 0x00007fed81060a17: hlt OopMapSet contains 1 OopMaps#0 OopMap{r10=Oop off=64}

    有趣的觀察

    上面的匯編代碼用紅色突出顯示的行非常有趣。 當(dāng)一個(gè)
    寫入volatile字段后,在Java內(nèi)存模型下,寫入必須順序一致 ,即,由于通常應(yīng)用的優(yōu)化(例如將寫入暫存到存儲(chǔ)緩沖區(qū))而不會(huì)重新排序。 這可以通過(guò)插入適當(dāng)?shù)膬?nèi)存屏障來(lái)實(shí)現(xiàn)。 在上述情況下,Hotspot選擇通過(guò)執(zhí)行MOV指令(寄存器到內(nèi)存地址-即寫操作),然后再執(zhí)行具有排序語(yǔ)義的LOCK ADD指令(不使用棧指針作為籬笆慣用法)來(lái)強(qiáng)制執(zhí)行排序。 這在x86處理器上并不理想。 使用單個(gè)LOCK XCHG指令進(jìn)行寫入,可以更有效,更正確地執(zhí)行相同的操作。 這使我想知道JVM是否存在一些重大折衷,以使其可以跨許多體系結(jié)構(gòu)移植,而不是在x86上可以做到的最好。

    參考:在Mechanical Sympathy博客上,從我們的JCG合作伙伴 Martin Thompson 的Hotspot JIT編譯器打印生成的匯編代碼 。

    翻譯自: https://www.javacodegeeks.com/2013/07/printing-generated-assembly-code-from-the-hotspot-jit-compiler.html

    編譯hotspot

    總結(jié)

    以上是生活随笔為你收集整理的编译hotspot_从Hotspot JIT编译器打印生成的汇编代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。