00:00
接下来我们聊聊一个功能,叫对象重用,这个可以大幅度提升咱们的一个性能。但是呢?你要注意它使用是有限制,什么叫对象重用呢?其实很简单,就是在有操作链的一个。呃,合并起来的一个链条里面,咱们不是有个操作链吗?比如说SAS跟map是不是串在一起啊,这个时候即使它串在一起,他们之间的数据拷贝也是通过一个什么先拷贝,他这样设计的目的是为了防止那个线安全问题。也就是说呀,什么叫深拷贝?我简单举个例子大家就懂了,咱们正常写代码是不是这样?呃,比如说有一个对象AA呀。或者咱们以图来理解吧。比如说这是一个GM,那GM呢,它这里是不是就涉及到了一个什么呢。
01:05
堆跟账了对吧,那比如说这里有个对象。对象实例。那咱们这边是不是可能有个碳啊,就引用啊,比如说小A,那这个时候是不是应该是这样子。小A,就是咱们的变呃,对象名是不是引用,它实际指向的是不是堆里边的这个对象啊。对吧。这是正常一个构成,比如说字符串吧,啊,比如说你你你是。啊,图算也不不对啊,就比如说一个对象嘛,实例,也就真正这个对象所包含的数据是不是在堆上面,那什么叫深拷贝呢?深拷贝是这样,对象实例他会原原本本的拷贝一份。然后呢?这个引用也是一个新的,比如说我叫A1。
02:01
好。这就是深拷贝了。也就是说。他实际的数据,实际的对象实力是会拷贝一份,那新的引用指向的是新的对象实力,这个叫深拷贝,那做这个事儿是不是可能很费劲呢,对吧,那有一种叫前拷贝。拷贝是什么意思?一项实例,我不再拷贝了。因为咱们知道对象的话,它是比声明一个引用对吧,我只需要声明一个新的引用,指向原来的这个地方就可以了。就变成这样了。那么现在是不是有两个指向的是一个实际的对象啊?对吧。那系统就是前拷贝,那咱们的对象重用其实就有点像这个前拷贝了,是不是省略的对象实力真正的资格拷贝这个过程对吧,但是这有一个。使用场景的限制是什么?你想想。
03:00
如果他修改了对象。那么对应的对他来讲,这个对象是不是就。词也被改了对吧,因为这里才是真正保存它真正数据的地方。一个改,另一个看到也是改之后的,就是可能出现的一个线程安全问题。那我们刚才对象重用优化的就是这个地方,把深拷贝变成直接给给到他,那么这边有个注意事项,一个对象只被下游一个function处理。所有下游方处理时不得改变对象内部的值。或者啊,这个是啊或这第一个很好理解,来咱们想想咱们的拓扑结构有没有可能是这么一种情况呢。有吧?大家注意,这个不是并行实例啊,这都是几个不同的算子。
04:02
比如说这个叫扇子A。这个是扇子贝。这个叫扇子C。那如果开启了对象重用啊,那比如说它实际存储的在这个位置,他们是可以串的,对吧。啊,别说串不串了,比如说实际上对象在这里,那么他钱拷贝给他,是不是他自己指向这里,他也指向这里,他也。给到了C对吧。那这个就属于算子A,传递数据的时候,传递给多个方式。对吧,那这有什么问题呢?比如说算子B对这个对象进行了修改,那是不是会影响到C这里的数据啊,那这样的话,你可能计算结果是错的,这就现场安全问题,对吧?所以他说呢,要么你只被下游,被一个下游的翻个省处理。
05:04
或者呢,你要么都不去改变对象内部的值是什么意思,还是刚才这个场景,呃,你。重用给他,重用给他,重用给他。那么这个时候呢?就有问题了。你,呃,这个时候如果算子B也好,算子C也好,都不会去修改这个数据本身内部的值,那这样是可以是允许的,那么我们来看看我们当前这个案例。可不可以呢,其实就刚好咱们这个UIDDEMO啊这里。当之前为了演示那个UID的恢复,我是不是又写了一个代码?对吧,咱们提交一下。提到这个。提交这个。原来那个。
06:01
我们看一下他的作业图。刚好咱们修改的代码就变成了这种情况。对吧,那比如说他升拷贝给他了钱呃。比如说他可以拷贝给他。那会怎么样?又拷贝给他,刚刚好这边。这个是一个map对吧,这是一个。但是呢,如果是哈希的话,它是会阶段的,也就是说他我们应该是发生在这一阶段,那在这个阶段map直接拷贝给Fiat这一块呢,其实无所谓吧,会不会修改不会对吧。那至少咱们这里。还是可以用。那这个之前咱们提交过了,那么现在我们开启对象重用怎么开呢?
07:10
直接指定一个参数object reuse,这参数其实在沃本UI也能看到啊,啊,现在没了,那API里面也能指定啊,在咱们env里边,你看Env.get configgu.set。什么?呃,什么reuse?啊,我看一下啊那个API。在这里有啊,Enable。你看是不是有一个开启对象重用啊。那么目前这个对象从用官方文档现在列出来只列在data set API。他只对data set列出来了。它是在执行环境里面。看。
08:00
允许重用flink内部用于反序列和传递数据的对象,对吧?可能会导致错误,而不知道这个行为的情况下,对吧,就可能你要评估好再来使用这个对象重用。那具体怎么评估呢?就我们刚才讲的,你要么下游的三个省只有一种,要么不会改变,都不会改变对象内部的值。要考虑到县城安全的问题。那这个呢,咱们简单。也可以在这里开启啊,提交参数指定也可以来我提给大家看一眼。刚才那个是不是停掉了啊。好呢。打开,打开之后咱们。点进这个作业,作业里面最后是不是有一个configuration。对吧,在这里呢,大家其实可以看到咱们的执行配置。
09:04
对象重用是开启的。默认呢,它是一个forces,默认都是不开的。那我们可以看一下这个火焰图。我们可以看到基本上这里呢,也没有什么。平顶的对吧,没有大平顶。那接下来我们提交一个不开启的。我把这个配置项给删掉。啊,不是啊,不是不是不是。
10:00
哎。算了,重新拷贝吧。那么拷贝上面这个得呢。上面这个就是之前没有开启对象重用的,我们来瞅一瞅。那我们刚才看的是哪个Fiat是吧?啊,那看你。等他跑起来。好,开始看一个火焰图。
11:09
那大家其实可以看到这个。火焰图这就有区别了吧,它的平顶是不是明显比之前的多了一点,因为它会花更多的时间在那个序列化上面,这个序列化你看都是什么?默认的序列化T对不对?那你再看看这里。除了IO序列化,然后是RA的,读数据的要进行序列化,对吧,发数据的要反序列化,读数据的要序列化,从这中间他就能给我们节省一点时间。你从这个最直观的来看,这个火焰图,它的执行时长就能看到一个对比,你看特别明显。同一个算子啊,同一个代码,同一个资源,开不开启对象重用的一个区别,另外我们看看当前执行的这个对象重用,不指定的话,默认就是关了,默认就关了。
我来说两句