JVM字段访问优化

都是通过即时编译器优化生成的IR图来精简最后的机器码(在生成机器码前就好像人浏览了一遍代码,通过前后关联情况手动消除了一些重复或无效的代码),去掉无效代码,减少在code cache中存储的机器码的大小,节省内存,提高程序运行速度。

主要包括:缓存读取、去除重复操作、分支优化、不可达分支消除

一、对象字段读取优化

优化一:缓存读取

static int bar(Foo o, int x) {
  int y = o.a + x;  // 将o.a存入缓存
  return o.a + y;  // 直接从缓存读取o.a(IR图中直接从缓存取值)
}

优化二:去重去不可达分支,可达分支优化

static int bar(Foo o, int x) {
  o.a = 1;
  if (o.a >= 0)  // 缓存中o.a为1,该行判断可以默认为true(IR图中自动消除该行)
    return x;
  else  // 冗余无效代码,(IR图中自动消除该else分支)
    return -x;
}

// 优化后程序
static int bar(Foo o, int x) {
  o.a = 1;
  return x;
}

二、对象字段存储优化

同一个字段先后被存储两次,两次操作中间没有对该字段的读取操作,没有被方法调用或者没有被间接存储到其他字段,JVM会消除第一处的冗余赋值指令(Volatile同样可以阻止该优化,强制属性值实时刷入内存)

class Foo {
  int a = 0;  // 冗余重复代码,被优化(IR图中被去除)
  void bar() {
    a = 1;  // 冗余重复代码,被优化(IR图中被去除)
    a = 2;  // 最终执行的赋值语句
  }
}

// 优化后程序
class Foo { 
  void bar() {
    a = 2;  // 最终执行的赋值语句
  }
}

三、局部变量死存储优化

与对象的字段值一样包含去除重复或者无效代码,优化分支选择。

// 重复代码消除
int bar(int x, int y) {
  int t = x*y;  // 重复冗余代码,IR图中被去除
  t = x+y;
  return t;
}

// 分支代码优化
int bar(boolean f, int x, int y) {
  int t = x*y;  // 编译后此处为int t ,具体赋值操作留到if程序块中
  if (f)
    t = x+y;
  return t;  // 如果走这条路才会对t进行第一行的赋值操作(int t = x*y) 并返回
}

// 不可达分支
int bar(int x) {
  if (false)  // 不可达分支,IR图中不会被编译
    return x;
  else
    return -x;
}

ps :可能出现异常时,无法进行字段优化

// 除零异常
int bar(int x, int y) {
  int t = x/y;  // 由于可能出现y=0的算术操作异常,所以该行不能被优化去除
  t = x+y;
  return t;
}

参考文章:

https://time.geekbang.org/column/article/39683

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值