00:00
啊,接着呀,咱们来看这个代码优化策略的第三个,啊也是呢,最后一个说基于这个逃逸分析,哎,我们呢,还可以考虑呢,叫分离对象,或者呢,叫做标量替换,说有的对象呀,可能不需要作为一个连续的内存结构的存在,也可以呢被访问到。啊,那么这个对象的这个部分或者全部呢,可以不存储在这个内存中,而是呢,存储在这个CPU的寄存器当中,啊这段话呢,主要是,呃,不是只是只限于咱们这个Java语言了啊,那翻译成咱们Java语言呢,就是说我们这个对象的话呢,可以不用呢,存储在这个对空间当中,而是呢,存储在我们这个站空间,因为咱们Java虚拟机呢,是基于这个站的机构,而不是基于寄存器的,是吧?哎,存储在这个站当中,好,那么具体呢,我们看一下什么呢,叫做这个叫标量替换。看标量啊K是吧,说呢它呢是指一个无法再分解成更小的数据的数据。那比如说我们Java当中的像基本数据类型啊,也称为呢叫原始数据类型,它呢就属于这个叫标量,那阳IG呢,就是咱们可以把这个非标量呢,比如说就是我们某一个啊user对象,或者呢,比如我们下边这个写的这叫point,就我们自定义的一个类是吧,那我们用了一个point对象,这呢,它称为叫聚合量。
01:15
那它称为呢叫聚合量啊,那么这个聚合量呢,说咱们就可以考虑再分解,因为呢,它可以分解成两个标量,分别呢,是in的类型的X或Y是吧?哎,所以这块你看说还可以呢,分解的数据呢,叫做聚合量,那Java中的这个对象呢,就属于聚合量,因为呢,它可以分解成其他的聚合量和标量,这个能理解吧?啊举个例子啊,比如说呢,咱们打开这个scalela,这个replace啊这样的操作,诶我在下面呢,举个简单的例子。啊,我用这个注释来描述一下,我这呢声明一个class class呢,我们称为呢叫customer。诶,这个呢叫客户是吧,然后在这个客户里边呢,我们可以声明,比如说string型的这个name啊,Int型的一个ID,诶我们在声明呢,叫account类型的叫account,就是每一个客户呢,他都有这个账户,这个账户的话呢,又是一个自定义的一个类,那账户的话呢,也有具体的,比如说我们称为那叫double类型的一个,哎余额是吧,哎简单的来描述就是这样子的,那就相当于我们这个聚合量呢,可以分解成,哎就是不能再细分了,针对这个string,咱们也可以后来不去细分。
02:18
啊,那么下边这个count呢,还是一个聚合量,咱们再对它呢进行细分,又可以把它拆解成是一个,呃,基本数据类型,这呢是标量。在这呢是标量啊,那string的话呢,其实你要再给它拆的话,也可以考虑底层就是一个,哎,我们说的一个查询数组啊,当然呢,JDK9以后呢,就改成BAT数组了是吧?哎就这样一个情况哈,好这呢就是我们所说的这个哎叫聚合量的一个拆分,那我们现在来讲呢,叫标量替换,什么意思啊,咱们知道这个对象呢,属于聚合量,正常来讲呢,我们用的对象呢,应该放到对套对空间当中,但是呢,我们说如果呢,通过这个逃逸分析发现呢,你当前这个对象外边也不用,你就是在那个方法内部去使用,那这时候我们可以考虑把这个聚合量啊,就把它肢解成是几个标量的构成。
03:02
哎,就把它直接成几个标量了啊,那既然是标量了,对于咱们说的这个,嗯,这个咱们就看下边这个图了啊。诶看这个图了,对于咱们说呢,刚才这个代码我们newpoint这个操作呢,就可以直接呢把它去掉啊,在我们这个alo alo这个方法中呢,相当于就是定义了两个呃方法内的局部变量了啊标量一个是X11,一个是二,那这样的话呢,我们说方法内的这个局变量呢,是不是应该放在我们诶这个战当中的战帧当中的局无变量表里边了,一个是一,一个是二。是吧,哎就成这样了,说白了就是我们此时经过这个标量替换以后呢,咱们就也可以把这个数据呢,是不是哎放到我们这个占空间了。哎,就这样的一个情况是吧,哎,那通过这样的话呢,我们也可以大大的减少这个堆空间内存的一个占用,同时呢,还减少了这个JC。啊,这呢也是提升我们性能的一个很好的方便啊,很好的方便啊行,下面呢,接着就提到了我们如何去开启这个标量替换,哎,就是通过我们这样一个参数来开启的,它默认呢也是打开的啊默认呢也是打开的,就是将我们的对象呢打散了分配在这个站上是吧,说的直白一点就是这个意思,行,那下边呢,咱们看一下这个代码,哎,这个代码呢,我给大家把这个例子呢也已经写好了。
04:18
啊,类似于咱们刚才PPT里边看到那个point啊,这呢我们是声明那个user里边呢,有两个属性,然后呢,我们在这个alo alo的方法中,此时呢,我们说这个user对象呢,它呢是为。发生逃逸是吧。行,那针对于未发生逃逸的话呢,我们这个就可以把它呢,替换成这个标量啊,真的是给我们这两个变量进行赋值的操作,同样呢,让我们这个方法呢,执行这是1000万次。对吧,诶这样的情况好,那我们这块呢,诶使用这个参数,大家稍微注意一下,那这个参数呢,我使用的是这个啊CTRLC一下。嗯,CTRL一下好,那此时呢,我们做一个执行。
05:00
嗯,找到我们当前这个操作。啊replace啊,在这我们CR一下,哎,注意我们看一下这里边这个参数。这呢是来设置我们这个对空间的一个大小啊,100兆,这呢是开启了这个逃逸分析啊,其实默认情况下呢,也是开启的啊,我只是把它显示的写出来了,这呢打印一下我们这个JC的一些细节,这呢是呃,先不开启咱们的这个标量替换。先不要开启,不要开启的话呢,意味着我们这个对象是不是还是在我们这个堆空间当中去扭的是吧,我们看一下这个花费的这个时间是多少。OK,跑一下。诶出来了57毫秒,那同时呢,大家注意到我们上边呢,是不是执行了一些相关的这些操作。啊,那么这这些操作呢,是不是就是我们在这个堆空间当中啊,执行的这个垃圾回收是吧?好记住这个操作,然后咱们把这个再打开。打开以后呢,注意此时的话呢,诶,我把这个减号呢,改成是一个加号。我改成是个加号,然后apply OK来直行跑一下。
06:05
好,大家来看是不是这个对比呢,又是非常强烈的,呃,首先的话呢,我们花费的时间呢,你看明显降低。哎,明显降低这呢,实际上也相当于是一个呃,这个变形的一个站上分配是吧,哎,我们这个标量的话呢,也是相当于分配到这个站上了哈,时间呢减少了,而且呢,我们这儿呢,没有发生过这个GC。大家发现了是吧,没有发生过这个JC啊,因为呢,我们就既然不在对空间中分配,就用不着进行垃圾回收了,OK啊,这个结果呢,应该是非常明显的,这个呢,就是咱们所要谈的这个叫啊标量替换。啊,这也是咱们说有了这个叫逃逸分析之后呢,诶,这个代码优化的第三个策略啊,成为呢叫标量替换啊这呢就给大家介绍到这里。
我来说两句