Java求余%操作引发的一连串故事

 更新时间:2021年5月28日 15:00  点击:1629

操作符%通常用在正整数上,但同样可以用在负整数和浮点数上。
  注意:只有当被除数是负数时, 余数才是负的。

C1 RCE对%的处理

HotSpot VM的C1有个RCE(Range Check Elimination,范围检查消除)优化,所谓范围检查消除,就是为了正确的抛出数组越界异常,虚拟机需要在数组访问的一些地方插入隐式的检查,但是这些检查会降低性能,比如在循环中每次循环都得检查一次,所以HotSpot VM会想办法在可能的地方消除这些检查。我在看C1 RCE的时候发现目前它对求余符号的支持较为薄弱,它只能处理形如下面的代码:

arr[x%arr.length] // 只有除数是x.length的时候,才能应用RCE优化

如果余数是整数常量,它就不能工作了:

arr[x%3]
for(int i=0;i<10;i++){
  arr[x%10]
}

实际上,根据JLS的定义,我们知道如果除数为整数常量(且等于零,因为0作为除数会抛出运行时异常),是可以推导出结果的上下界的(也取决于被除数的正负),规则如下:

  • x % -y ==> [0, y - 1]
  • x % y ==> [0, y - 1]
  • -x % y ==> [-y + 1, 0]
  • -x % -y ==> [-y + 1, 0]

于是,我给JDK发了个patch,这个问题算是解决了。但是Nils提到,C2是否有相同的优化呢?后面Tobias帮忙确认了一下C2没有,我再后来也进一步确认了,所以下一步是调研C2是否能应用同样的优化。

调研为C2应用同样的优化

本来以为是比较trivial的事情,为求余节点的类型系统加点代码,推导一下上下界即可,实际上我也这么做的,但是最后发现这样没有消除上下界。默认开启-XX:+GenerateRangeChecks后,在数组访问过程中(Parse::array_addressing),C2仍然生成了范围检查。

调试后发现推导上下界根本没有执行,因为C2创建完求余节点后,会执行一个IGVN的过程,即迭代的应用多种优化,其中就包括理想化,C2理想化是指应用很多局部小优化的过程,在这个例子中就是特殊处理形如x%2^n,x%2^n-1x%1的情况,如果除数是整数常量,它还会使用一个来自https://book.douban.com/subject/1784887/书里面的算法,即Division by Invariant Integers using Multiplication(by Granlund and Montgomery),搜了一下知乎有类似的文章,想要了解细节可以读读https://zhuanlan.zhihu.com/p/151038723。知道了原因,于是我改了下代码,禁止了求余节点的理想化,心想这总可以了吧。

还是不行

是的,还是不行。尽管我已经禁止了对求余符号的理想化优化,但是范围检查还是生成了。。。我又继续看代码,发现除了理想化的这个优化之外,C2在IR(中间表示)构造的过程中又 又 又 又 又对求余运算做了个优化!如果除数是正整数常量,且是2^n,那么C2会对它进行变形,IR如图所示:

左边的IR是 IR构造的时候C2做的优化后的效果,右边是理想化优化后的效果。实际上它们做的事情本身是比较重复的,而且经过测试发现,理想化优化的算法要好于IR构造过程中的优化,所以我又提了个patch解决这个问题(不过还在review中)。

结语

我认为为求余节点推导上下界也是有意义的,如果以后有其他优化会变形为求余运算,那么它们可以应用这个推导,同时,为求余做统一完善的类型推导这件事本身也是正确的,所以我又提了个patch。可以看到,最终我只消除了C1 arr[x%4]的范围检查,还是没能消除C2 arr[x%4]的范围检查,是不是以后可以说C1有的地方做的比C2好了(狗头hh。

以上就是Java求余%操作引发的一连串故事的详细内容,更多关于Java求余%的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章

  • mysql_connect与mysql_pconnect的区别详解

    在mysql中我们会看到有两种常用的数据库连接模式,一种是长久连接,另一各是页面访问完之后就断了连接,下面我来分别介绍mysql_connect与mysql_pconnect的区别,有需要了解...2016-11-25
  • C#中 paint()与Onpaint()的区别

    paint是事件onpaint方法onpaint方法是调用paint事件的,用哪一个,效果是一样,就看那一个方便了内部是这样实现的:...2020-06-25
  • phpems SQL注入(cookies)分析研究

    PHPEMS(PHP Exam Management System)在线模拟考试系统基于PHP+Mysql开发,主要用于搭建模拟考试平台,支持多种题型和展现方式,是国内首款支持题冒题和自动评分与教师评分相...2016-11-25
  • IntelliJ IDEA2021.1 配置大全(超详细教程)

    这篇文章主要介绍了IntelliJ IDEA2021.1 配置大全(超详细教程),需要的朋友可以参考下...2021-04-18
  • 浅谈Spring Cloud Netflix-Ribbon灰度方案之Zuul网关灰度

    这篇文章主要介绍了浅谈Spring Cloud Netflix-Ribbon灰度方案之Zuul网关灰度,想了解Ribbon灰度的同学可以参考下...2021-04-09
  • Painter绘制红衣喝酒男水粉画效果教程

    今天小编在这里就来给Painter的这一款软件的使用者们来说一说绘制红衣喝酒男水粉画效果的教程,各位想知道具体绘制步骤的使用者,那么下面就快来跟着小编一起看一看教程...2016-09-14
  • 全身个性化!贱驴619打滚机械键盘87键评测

    电竞行业的红火带动了机械键盘的发展,不少我们熟知的老牌PC厂商都纷纷进军了电竞行业。当然了免不了一些年轻的电竞厂商。贱驴就是在这个时代诞生的,旗下最让我们熟知的就是模块化的007电竞鼠标了!其他的电竞产品也人如其名,和贱驴的名字一样非常有个性化,本次评测的是贱驴619打滚机械键盘,驴打滚这种命名也真的是醉了,废话不多说先来开箱看看!...2016-09-12
  • iPhone6怎么激活?两种苹果iPhone6激活教程图文详解

    iPhone6新机需要激活后才可以正常使用,那么对于小白用户来说,iPhone6如何激活使用呢?针对此问题,本文就为大家分别介绍Wifi无线网络激活以及iPhone6连接电脑激活这两种有效的方法,希望本文能够帮助到大家...2022-09-14
  • Ecshop提示Only variables should be passed by reference in错误

    在安装好ecshop软件之后我们打开首页时提示Only variables should be passed by reference in错误了,碰到这个问题是什么原因呢?下面我们就一起来看看解决办法吧。...2016-11-25
  • C语言实现放烟花的程序

    这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
  • python opencv 画外接矩形框的完整代码

    这篇文章主要介绍了python-opencv-画外接矩形框的实例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-04
  • Java实现经典游戏复杂迷宫

    这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
  • Photoshop制作雨中野外孤独行走的一头牛海报教程

    今天小编在这里就来给各位photoshop的这一款软件的使用者们来说下制作雨中野外孤独行走的一头牛海报的教程,各位想知道具体制作方法的使用者们,大家就快来看一看小编给...2016-09-14
  • PHP添加MongoDB扩展实例教程

    由于要使用mikoomi mongodb plugin插件,所以需要php对mongodb的扩展支持,默认通过源安装的php并没有mongodb的扩展支持,具体可以通过php -m|grep mongo 验证 。这里就结...2016-11-25
  • php身份证校验码的计算例子

    下面来给各位同学介绍一个php身份证校验码的计算例子,希望本函数代码能帮助到各位同学哦。 例子 代码如下 复制代码 public function id_ver...2016-11-25
  • C# WinForm多线程解决界面卡死问题的完美解决方案,使用BeginInvoke

    问题描述:当我们的界面需要在程序运行中不断更新数据时,当一个textbox的数据需要变化时,为了让程序执行中不出现界面卡死的现像,最好的方法就是多线程来解决一个主线程来创建界...2020-06-24
  • Painter绘制帅气卡通魔法王子漫画教程

    今天小编在这里就来给Painter的这一款软件的使用者们来说一下绘制帅气卡通魔法王子漫画的具体教程,各位想知道绘制步骤的使用者,那么下面就快来跟着小编一起看一看教程...2016-09-14
  • Illustrator鼠绘堆雪人的孩童矢量插画教程

    今天小编在这里就来给各位Illustrator的这一款软件的使用者们来说说鼠绘堆雪人的孩童矢量插画的教程,各位想知道具体绘制方法的使用者们,那么各位就快来跟着小编来看看...2016-09-14
  • 409错误是什么 http 409错误怎么解决

    409错误是什么?http 409错误怎么解决呢?不少站长在遇到这个错误代码之后都一筹莫展,本次一聚教程网为大家带来了详细的说明,快来看看吧。 409错误是什么: HTTP 40...2017-01-22