一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務(wù)器之家 - 編程語言 - Java教程 - JVM進(jìn)階教程之字段訪問優(yōu)化淺析

JVM進(jìn)階教程之字段訪問優(yōu)化淺析

2021-06-28 10:24機(jī)智的小鳴 Java教程

這篇文章主要給大家介紹了關(guān)于JVM進(jìn)階教程之字段訪問優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在實(shí)際中,java程序中的對(duì)象或許 本身就是逃逸 的,或許因?yàn)?方法內(nèi)聯(lián)不夠徹底 而被即時(shí)編譯器 當(dāng)成是逃逸 的,這兩種情況都將

導(dǎo)致即時(shí)編譯器 無法進(jìn)行標(biāo)量替換 ,這時(shí),針對(duì)對(duì)象字段訪問的優(yōu)化顯得更為重要。

?
1
2
3
4
static int bar(foo o, int x) {
 o.a = x;
 return o.a;
}
  1. 對(duì)象o是傳入?yún)?shù), 不屬于逃逸分析的范圍 (jvm中的逃逸分析針對(duì)的是 新建對(duì)象 )
  2. 該方法會(huì)將所傳入的int型參數(shù)x的值存儲(chǔ)至實(shí)例字段foo.a中,然后再讀取并返回同一字段的值
  3. 這段代碼涉及 兩次 內(nèi)存訪問操作:存儲(chǔ)和讀取實(shí)例字段foo.a
  4. 代碼可以手工優(yōu)化成如下
?
1
2
3
4
static int bar(foo o, int x) {
 o.a = x;
 return x;
}

即時(shí)編譯器也能作出類似的 自動(dòng)優(yōu)化

字段讀取優(yōu)化

即時(shí)編譯器會(huì)優(yōu)化 實(shí)例字段 和 靜態(tài)字段 的訪問,以 減少總的內(nèi)存訪問次數(shù)

即時(shí)編譯器將 沿著控制流 ,緩存各個(gè)字段 存儲(chǔ)節(jié)點(diǎn) 將要存儲(chǔ)的值,或者字段 讀取節(jié)點(diǎn) 所得到的值

  • 當(dāng)即時(shí)編譯器 遇到對(duì)同一字段的讀取節(jié)點(diǎn) 時(shí),如果緩存值還沒有失效,那么將讀取節(jié)點(diǎn) 替換 為該緩存值
  • 當(dāng)即時(shí)編譯器 遇到對(duì)同一字段的存儲(chǔ)節(jié)點(diǎn) 時(shí),會(huì) 更新 所緩存的值
    • 當(dāng)即時(shí)編譯器遇到 可能更新 字段的節(jié)點(diǎn)時(shí),它會(huì)采取 保守 的策略, 舍棄所有的緩存值
    • 方法調(diào)用節(jié)點(diǎn) :在即時(shí)編譯器看來,方法調(diào)用會(huì)執(zhí)行 未知代碼
    • 內(nèi)存屏障節(jié)點(diǎn) :其他線程可能異步更新了字段

樣例1

?
1
2
3
4
static int bar(foo o, int x) {
 int y = o.a + x;
 return o.a + y;
}

實(shí)例字段foo.a被讀取兩次,即時(shí)編譯器會(huì)將第一次讀取的值緩存起來,并且 替換 第二次的字段讀取操作,以 節(jié)省 一次內(nèi)存訪問

?
1
2
3
4
5
static int bar(foo o, int x) {
 int t = o.a;
 int y = t + x;
 return t + y;
}

樣例2

?
1
2
3
4
5
6
7
static int bar(foo o, int x) {
 o.a = 1;
 if (o.a >= 0)
  return x;
 else
  return -x;
}

字段讀取節(jié)點(diǎn)被替換成一個(gè) 常量 ,進(jìn)一步觸發(fā)更多的優(yōu)化

?
1
2
3
4
static int bar(foo o, int x) {
 o.a = 1;
 return x;
}

樣例3

?
1
2
3
4
5
6
7
8
class foo {
 boolean a;
 void bar() {
  a = true;
  while (a) {}
 }
 void whatever() { a = false; }
}

即時(shí)編譯器會(huì)將while循環(huán)中讀取實(shí)例字段a的操作 直接替換為常量true

?
1
2
3
4
5
6
7
8
void bar() {
 a = true;
 while (true) {}
}
// 生成的機(jī)器碼將陷入這一死循環(huán)中
0x066b: mov r11,qword ptr [r15+0x70] // 安全點(diǎn)測試
0x066f: test dword ptr [r11],eax  // 安全點(diǎn)測試
0x0672: jmp 0x066b     // while (true)

1、可以通過 volatile 關(guān)鍵字標(biāo)記實(shí)例字段a,以 強(qiáng)制 對(duì)a的讀取

2、實(shí)際上,即時(shí)編譯器將 在volatile字段訪問前后插入內(nèi)存屏障節(jié)點(diǎn)

  • 這些 內(nèi)存屏障節(jié)點(diǎn) 將 阻止 即時(shí)編譯器 將屏障之前所緩存的值用于屏障之后的讀取節(jié)點(diǎn)之上
  • 在x86_64平臺(tái)上,volatile字段讀取前后的內(nèi)存屏障都是no-op
    • 在 即時(shí)編譯過程中的屏障節(jié)點(diǎn) ,還是會(huì) 阻止即時(shí)編譯器的字段讀取優(yōu)化
    • 強(qiáng)制在循環(huán)中使用 內(nèi)存讀取指令 訪問實(shí)例字段foo.a的最新值

3、同理, 加解鎖操作同樣也會(huì)阻止即時(shí)編譯器的字段讀取優(yōu)化

字段存儲(chǔ)優(yōu)化

如果一個(gè)字段先后被存儲(chǔ)了兩次,而且這 兩次存儲(chǔ)之間沒有對(duì)第一次存儲(chǔ)內(nèi)容讀取 ,那么即時(shí)編譯器將 消除 第一個(gè)字段存儲(chǔ)

樣例1

?
1
2
3
4
5
6
7
class foo {
 int a = 0;
 void bar() {
  a = 1;
  a = 2;
 }
}

即時(shí)編譯器將消除bar方法的冗余存儲(chǔ)

?
1
2
3
void bar() {
 a = 2;
}

樣例2

即便在某個(gè)字段的兩個(gè)存儲(chǔ)操作之間讀取該字段,即時(shí)編譯器也可能在 字段讀取優(yōu)化 的幫助下,將第一個(gè)存儲(chǔ)操作當(dāng)作 冗余存儲(chǔ)

場景:例如兩個(gè)存儲(chǔ)操作之間隔著許多代碼,又或者因?yàn)?方法內(nèi)聯(lián) 的原因,將兩個(gè)存儲(chǔ)操作納入到同一編譯單元里(如構(gòu)造器中字段的初始化以及隨后的更新)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class foo {
 int a = 0;
 void bar() {
  a = 1;
  int t = a;
  a = t + 2;
 }
}
// 優(yōu)化為
class foo {
 int a = 0;
 void bar() {
  a = 1;
  int t = 1;
  a = t + 2;
 }
}
// 進(jìn)一步優(yōu)化為
class foo {
 int a = 0;
 void bar() {
  a = 3;
 }
}

如果所存儲(chǔ)的字段被標(biāo)記為 volatile ,那么即時(shí)編譯器也 不能消除冗余存儲(chǔ)

死代碼消除

樣例1

?
1
2
3
4
5
int bar(int x, int y) {
 int t = x*y;
 t = x+y;
 return t;
}

沒有節(jié)點(diǎn)依賴于t的第一個(gè)值 x*y ,因此該乘法運(yùn)算將被消除

?
1
2
3
int bar(int x, int y) {
 return x+y;
}

樣例2

?
1
2
3
4
5
6
int bar(boolean f, int x, int y) {
 int t = x*y;
 if (f)
  t = x+y;
 return t;
}

部分程序路徑上有冗余存儲(chǔ)(f=true),該路徑上的乘法運(yùn)算將會(huì)被消除

?
1
2
3
4
5
6
7
8
int bar(boolean f, int x, int y) {
 int t;
 if (f)
  t = x+y;
 else
  t = x*y;
 return t;
}

樣例3

?
1
2
3
4
5
6
int bar(int x) {
 if (false)
  return x;
 else
  return -x;
}

不可達(dá)分支指的是任何程序路徑都不可達(dá)到的分支,即時(shí)編譯器將 消除不可達(dá)分支

?
1
2
3
int bar(int x) {
 return -x;
}

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

原文鏈接:http://zhongmingmao.me/2019/01/06/jvm-advanced-optimization-filed-access/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 暖暖视频日本 | 微拍秒拍99福利精品小视频 | 国产在线精品亚洲第一区香蕉 | 欧美亚洲激情在线 | 午夜爽喷水无码成人18禁三级 | 欧美在线播放一区二区 | 国产成人一级 | 美女禁区视频免费观看精选 | 日本熟hdx| 国产亚洲精品看片在线观看 | 久久天天躁狠狠躁夜夜躁 | 婷婷99视频精品全部在线观看 | 视频在线视频免费观看 | 国产老村长足疗店对白 | 1313午夜精品久久午夜片 | 午夜一级影院 | 青春草在线观看精品免费视频 | 狠狠综合视频精品播放 | 免费看国产一级特黄aa大片 | 狠狠插入 | ysl蜜桃色成人麻豆 youwu在线影院 | 亚洲 欧美 制服 校园 动漫 | 天堂8在线天堂资源在线 | 隔壁的漂亮邻居hd中文 | 亚洲视频免费在线观看 | 女教师被学生糟蹋三天 | 精品精品国产自在久久高清 | 久久不射网| 欧美一区二区三区四区视频 | 色综合久久中文字幕网 | 亚洲福利区 | 亚洲欧美专区精品久久 | 精品久久久久久久久免费影院 | 国产香蕉一区二区精品视频 | 草莓视频深夜释放 | 国产亚洲99影院 | 色综合视频一区二区三区 | jj免费视频| 久久精品小视频 | 日韩色在线观看 | 男人女人插 |