欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java求余%操作引發(fā)的一連串故事

 更新時(shí)間:2021年05月28日 11:54:02   作者:kelthuzadx  
取模運(yùn)算與取余運(yùn)算兩個(gè)概念有重疊的部分但又不完全一致。主要的區(qū)別在于對負(fù)整數(shù)進(jìn)行除法運(yùn)算時(shí)操作不同。本文重點(diǎn)給大家介紹Java求余%操作引發(fā)的一連串故事,感興趣的朋友跟隨小編一起看看吧

操作符%通常用在正整數(shù)上,但同樣可以用在負(fù)整數(shù)和浮點(diǎn)數(shù)上。
  注意:只有當(dāng)被除數(shù)是負(fù)數(shù)時(shí), 余數(shù)才是負(fù)的。

C1 RCE對%的處理

HotSpot VM的C1有個(gè)RCE(Range Check Elimination,范圍檢查消除)優(yōu)化,所謂范圍檢查消除,就是為了正確的拋出數(shù)組越界異常,虛擬機(jī)需要在數(shù)組訪問的一些地方插入隱式的檢查,但是這些檢查會(huì)降低性能,比如在循環(huán)中每次循環(huán)都得檢查一次,所以HotSpot VM會(huì)想辦法在可能的地方消除這些檢查。我在看C1 RCE的時(shí)候發(fā)現(xiàn)目前它對求余符號(hào)的支持較為薄弱,它只能處理形如下面的代碼:

arr[x%arr.length] // 只有除數(shù)是x.length的時(shí)候,才能應(yīng)用RCE優(yōu)化

如果余數(shù)是整數(shù)常量,它就不能工作了:

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

實(shí)際上,根據(jù)JLS的定義,我們知道如果除數(shù)為整數(shù)常量(且等于零,因?yàn)?作為除數(shù)會(huì)拋出運(yùn)行時(shí)異常),是可以推導(dǎo)出結(jié)果的上下界的(也取決于被除數(shù)的正負(fù)),規(guī)則如下:

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

于是,我給JDK發(fā)了個(gè)patch,這個(gè)問題算是解決了。但是Nils提到,C2是否有相同的優(yōu)化呢?后面Tobias幫忙確認(rèn)了一下C2沒有,我再后來也進(jìn)一步確認(rèn)了,所以下一步是調(diào)研C2是否能應(yīng)用同樣的優(yōu)化。

調(diào)研為C2應(yīng)用同樣的優(yōu)化

本來以為是比較trivial的事情,為求余節(jié)點(diǎn)的類型系統(tǒng)加點(diǎn)代碼,推導(dǎo)一下上下界即可,實(shí)際上我也這么做的,但是最后發(fā)現(xiàn)這樣沒有消除上下界。默認(rèn)開啟-XX:+GenerateRangeChecks后,在數(shù)組訪問過程中(Parse::array_addressing),C2仍然生成了范圍檢查。

調(diào)試后發(fā)現(xiàn)推導(dǎo)上下界根本沒有執(zhí)行,因?yàn)镃2創(chuàng)建完求余節(jié)點(diǎn)后,會(huì)執(zhí)行一個(gè)IGVN的過程,即迭代的應(yīng)用多種優(yōu)化,其中就包括理想化,C2理想化是指應(yīng)用很多局部小優(yōu)化的過程,在這個(gè)例子中就是特殊處理形如x%2^n,x%2^n-1x%1的情況,如果除數(shù)是整數(shù)常量,它還會(huì)使用一個(gè)來自https://book.douban.com/subject/1784887/書里面的算法,即Division by Invariant Integers using Multiplication(by Granlund and Montgomery),搜了一下知乎有類似的文章,想要了解細(xì)節(jié)可以讀讀https://zhuanlan.zhihu.com/p/151038723。知道了原因,于是我改了下代碼,禁止了求余節(jié)點(diǎn)的理想化,心想這總可以了吧。

還是不行

是的,還是不行。盡管我已經(jīng)禁止了對求余符號(hào)的理想化優(yōu)化,但是范圍檢查還是生成了。。。我又繼續(xù)看代碼,發(fā)現(xiàn)除了理想化的這個(gè)優(yōu)化之外,C2在IR(中間表示)構(gòu)造的過程中又 又 又 又 又對求余運(yùn)算做了個(gè)優(yōu)化!如果除數(shù)是正整數(shù)常量,且是2^n,那么C2會(huì)對它進(jìn)行變形,IR如圖所示:

左邊的IR是 IR構(gòu)造的時(shí)候C2做的優(yōu)化后的效果,右邊是理想化優(yōu)化后的效果。實(shí)際上它們做的事情本身是比較重復(fù)的,而且經(jīng)過測試發(fā)現(xiàn),理想化優(yōu)化的算法要好于IR構(gòu)造過程中的優(yōu)化,所以我又提了個(gè)patch解決這個(gè)問題(不過還在review中)。

結(jié)語

我認(rèn)為為求余節(jié)點(diǎn)推導(dǎo)上下界也是有意義的,如果以后有其他優(yōu)化會(huì)變形為求余運(yùn)算,那么它們可以應(yīng)用這個(gè)推導(dǎo),同時(shí),為求余做統(tǒng)一完善的類型推導(dǎo)這件事本身也是正確的,所以我又提了個(gè)patch??梢钥吹?,最終我只消除了C1 arr[x%4]的范圍檢查,還是沒能消除C2 arr[x%4]的范圍檢查,是不是以后可以說C1有的地方做的比C2好了(狗頭hh。

以上就是Java求余%操作引發(fā)的一連串故事的詳細(xì)內(nèi)容,更多關(guān)于Java求余%的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Hadoop之Mapreduce序列化

    Hadoop之Mapreduce序列化

    本文主要帶我們了解Mapreduce序列化,序列化就是把內(nèi)存中的對象,轉(zhuǎn)換成字節(jié)序列(或其他數(shù)據(jù)傳輸協(xié)議)以便于存儲(chǔ)到磁盤(持久化)和網(wǎng)絡(luò)傳輸。想進(jìn)一步了解更多的小伙伴,可以參考閱讀本文
    2023-03-03
  • 深入理解Java中的類加載器原理

    深入理解Java中的類加載器原理

    這篇文章主要介紹了深入理解Java中的類加載器原理,類加載器負(fù)責(zé)加載所有的類,系統(tǒng)為所有被載入內(nèi)存中的類生成一個(gè)java.lang.Class實(shí)例,需要的朋友可以參考下
    2024-01-01
  • Springboot基于assembly的服務(wù)化打包方案及spring boot部署方式

    Springboot基于assembly的服務(wù)化打包方案及spring boot部署方式

    這篇文章主要介紹了Springboot基于assembly的服務(wù)化打包方案及springboot項(xiàng)目的幾種常見的部署方式,本文主要針對第二種部署方式提供一種更加友好的打包方案,需要的朋友可以參考下
    2017-12-12
  • Java面試題解析之判斷以及防止SQL注入

    Java面試題解析之判斷以及防止SQL注入

    這篇文章主要介紹了Java面試題解析之判斷以及防止SQL注入,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • SpringBoot如何使用內(nèi)嵌Tomcat問題

    SpringBoot如何使用內(nèi)嵌Tomcat問題

    這篇文章主要介紹了SpringBoot如何使用內(nèi)嵌Tomcat問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Java實(shí)現(xiàn)List去重的幾種方法總結(jié)

    Java實(shí)現(xiàn)List去重的幾種方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Java中List去重的幾種常用方法總結(jié),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)和參考價(jià)值,需要的小伙伴可以了解一下
    2023-09-09
  • SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)

    SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了如何使用Vue、SpringBoot和EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出數(shù)據(jù)功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-05-05
  • Java?Springboot異步執(zhí)行事件監(jiān)聽和處理實(shí)例

    Java?Springboot異步執(zhí)行事件監(jiān)聽和處理實(shí)例

    Java?SpringBoot中,監(jiān)聽和處理事件是一種常見的模式,它允許不同的組件之間通過事件進(jìn)行通信,事件監(jiān)聽和處理通常通過Spring的事件發(fā)布-訂閱模型來實(shí)現(xiàn),一個(gè)簡單的Spring?Boot應(yīng)用程序示例,其中將包括事件的定義、事件的發(fā)布以及事件的監(jiān)聽
    2024-07-07
  • SpringBoot實(shí)現(xiàn)本地存儲(chǔ)文件上傳及提供HTTP訪問服務(wù)的方法

    SpringBoot實(shí)現(xiàn)本地存儲(chǔ)文件上傳及提供HTTP訪問服務(wù)的方法

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)本地存儲(chǔ)文件上傳及提供HTTP訪問服務(wù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • java封裝實(shí)例用法講解

    java封裝實(shí)例用法講解

    在本篇文章里小編給大家整理了一篇關(guān)于java封裝實(shí)例用法及相關(guān)知識(shí)點(diǎn),有興趣的朋友們可以參考下。
    2021-01-01

最新評(píng)論