00:00
那么基于咱们讲的这个逃逸分析啊,那么我们可以进代进对这个代码进行这个优化,那这里边的优化呀,我们主要从如下的三个角度呢来进行说明啊,第一个也是咱们刚才那会提到的叫做占上分配,对吧?咱们可以将诶堆当中分配对象空间的这个行为呢,转化为对站上进行分配。啊,那这呢,我们也避免了进行这个垃圾回收啊,可以提高程序的一个性能,那进行战略分配的前提呢,就是咱们刚才说了,通过这个逃逸分析之后呢,发现这个对象呢,没有发生逃逸的,我们才可以考虑呢,进行占上的分配。诶,那就是这个问题,好,那我们首先呢来看一下,这叫占上分配,至于说这个同步省略和呃,这个标量替换,咱们一会儿再说这两个点。好,那首先呢,我们来看下这个占占上分配,说git编译器啊,在编译期间,根据逃逸分析的结果,如果发现一个对象呢,没有发生逃逸啊,那这时候我们就要占上呢,进行这个对象的分配。这个战场分配完以后,执行这个战中的这个相应的操作啊,你当前这个战争的方法是吧,哎,当我们这个线程结束,或者当你这个方法结束的时候呢,自然而然的你这个呃站呢就出战了,那相应的你这个站上的这个对象呢,也就自动的空间呢也会被释放。
01:14
啊就无需呢,再进行这个JC,那哪些情况呢,是属于这个,呃,经过逃逸分析以后呢,发现没有,呃发现那个逃逸除方法了呢,诶咱们刚才那会儿呢,是不是也给大家举例子了啊,叫变量给了一个成员变量赋值,哎方法返回值啊,实例引用传递啊,就是对应着咱们刚才给大家讲的这三种情况。对吧,哎,在这里边给我们这个呃,Obj这个对象呢,相当于进行了一个赋值啊,这个呢,就属于我们在这里边给大家赋值,这呢是相当于我们这个根据这个诶返回是吧?根据这个返回我们呢,诶把它呢,呃在方法外有可能被使用到是吧?诶还有一种呢,就是我们在这个里边呢,发生了一个调用啊,引用了我们当前这个成员变量。哎,就是这样个情况啊好,这呢就是属于我们发生逃逸的情况,那么没有发生逃逸的呢,我们就可以实现这个叫占上分配。
02:05
啊,就是这样的一个行为,好那么下边呢,咱们给大家举一个例子,哎,通过这个例子的前后对比呢,大家能够去理解一下,我们所谓的叫占上分配,好我们来看这个代码。这个代码呢是这样写的,这呢是一个起始时间,这呢是一个结束时间,在这个中间啊,我们调用了,哎,为了让这个情况呢更容易凸显出来,我这呢是让循环执行1000万次。啊,每执行一次的话呢,我们会调用这个叫啊alo这样一个方法,这个方法里边呢,我们创建了一个对象。啊,那很显然我们这个对象,哎,大家看一下是不是我们此时这个user这个对象未发生逃逸啊。哎,发生诶逃逸,那么因为你没有发生逃逸,所以我们可以考虑呢,就是将我们new的这个对象是不是分配到我们这个叫诶占空间是吧?哎,我们这个占空间上,好,这就是这样一个道理啊,然后上面的话呢,我们需要做这样的一些参数,首先呢,是我们这个堆空间的一个,呃。
03:01
整体的一个,呃,空间的一个设置啊,我这用了一个G,然后呢,我们开启呃这个注意我们先没有开启咱们的这个,呃,叫什么逃逸分析是吧,没有开启这个逃逸分析,然后这块呢,是打印我们这个垃圾回收的一些细节,好首先呢,我们把它呢,诶CTRLC一下。啊,CTRLC一下,那这块呢,我们打开这呢去选择,嗯,咱们现在想操作的是这个stack啊location啊站上分配这样一个行为,好CTRLV把零呢粘过来啊很好理解这里边的几个参数对吧?好注意此时呢,咱们是没有开启这个占上分配的。啊,不是没有开启这个叫逃逸分析的是吧,没有开启逃逸分析的情况下呢,就意味着我们所有的对象呢,都是在这个堆空间当中去开辟的这个空间,好,那那最后的话呢,我们让当年这个进程呢,也停下来,真的是这个1000秒。啊,这个方便呢,咱们去查看一下这个内存的一个情况啊好,我们把这个程序呢跑起来。嗯,可以了,那这时候呢,出来这个77毫秒,实际上呢,就对应着我们创建了是不是1000万个这个右侧对象花费的这个时间啊,那目前呢,没有结束,是因为还在我们这个进行一个等待啊好,那么在这个情况下呢,咱们可以通过啊,还是咱们这个JVVM打开。
04:16
打开呢,找到我们当前这个程序。诶看我们这块有个叫诶充氧器是吧,诶打开这个内存。来大家看一下这里边儿这个情况,这呢是咱们这个user对象,这个对象的话呢,大家看这是不是现在有1000万个。哎,我们内存当中有1000万个这个对象啊,都存在着呢。啊,这呢,就是我们所谓的是不是实例的一个个数是吧,好这块我们把它呢就停止了,哎通过这个呢,大家能够看到这个细节了,OK,我把它呢停下来,接下来的话呢,我们只需要做一个很小的操作。我把这里边儿这个减号啊,我改成加号,加号呢就意味着我们开启的叫逃逸分析。啊赖OK,那此时的话呢,我们说这个对象的尸体没有发生逃逸,他就会考虑叫战上分配跑一下。
05:06
首先大家会发现我们此时花费的时间呢,是不是少很多,刚才呢是70多毫秒,现在呢只需要四毫秒,对吧?啊,这是其一啊,然后呢,我们再查看一下咱们当前的这个内存当中到底有多少个对象呢?嗯,这时候大家看一下,我们此时这个user在这个内存当中,它这个个数啊,是不是就不足我们说的这个1000万个了啊,因为我们这块呢,其实根本就不会维护这么多的这个对象。哎,就是这样一个情况,好,那通过这个呢,大家应该很清楚的能够,诶了解到我们想要描述的这个点啊,就是确实呢,我们这个执行的速度是不是更快一些啊,分别呢,不用花这么长时间了,是吧?诶这是一个层面,好我们再给大家进一步的去说啊,我们这块呢,还来修改这个参数,我此时呢,把这个一个G的内存呢,我改掉,改成了256兆。哎,后边这个也一样,哎,256兆,那压1G呢,就是此时咱们这个堆空间啊,是不是就变小了。
06:04
那这个空间变小会影响什么呢?那我们现在创建的对象呢,又足够多,这就有可能是不是发生这个JC啊好,那在咱们,诶咱们应该先演示这个情况啊,没有开启诶没有开启这个逃逸分析的时候。来,我们看一下。嗯,可以了,那其实这个时间呢,比刚才咱们这块呢,稍微快一点啊,50多毫秒,但是呢,相当于我们开启了逃逸分析也会比较慢,那上面呢,咱们也看到了它执行过这个JC,那就是因为咱们这个往对空间中放的时候呢,是不是,呃嗯,这个新生代码了,那我们这块呢,是不是就要发生这个JC是吧?哎,这两大家注意一下好,然后的话呢,我这块把这个逃逸分析呢给它打开。来,OK,好,再来。诶,神奇的事情发生了,这时候大家会发现呢,我们执行的时间呢比较短,这是其一,其次的话呢,我们根本就没有发生过GC。
07:05
没有发生过JC,因为呢,咱们在站上是不是根本呢也不会,诶是不是出现这个GC啊,哎这呢是我们看到的这两个点啊,几个方向啊,一个呢执行时间比较短,其次的话呢,我们没有发生的JC啊,再次的话呢,就是我们看到这个,呃,真正在内存中维护的我们这个这个user对象的个数呢,是不是也不会说是1万个对吧?诶从这几个角度呢,我们来分析了一下,诶这个呢叫诶战商分配这样的一个策略啊,确实呢,效果还是比较好的。啊是这样的啊,咱们刚才也提到是不是默认情况下呢,咱们这个逃逸分析呢,它参数在GDK7的时候也是开启的是吧?哎,我们这块呢,就把它关闭啊,两个情况做了一个对比。
我来说两句