APNG4Android icon indicating copy to clipboard operation
APNG4Android copied to clipboard

gif加载性能

Open Lieeber opened this issue 3 years ago • 26 comments

你好,我有一个疑问,glide默认有gif加载功能,该库提供的gif加载方式相比glide默认的gif加载有性能上的优势吗?

Lieeber avatar Nov 10 '21 12:11 Lieeber

glide gif解析是在java层,本库gif解析转到native侧,native会比java侧在数据处理上有性能优势

jingpeng avatar Nov 11 '21 02:11 jingpeng

我再补充一些: Glide默认支持Gif解析,但在实际中,发现,当列表中有大量Gif同时播放时,低端的手机很容易会出现卡顿的情况,CPU占用很高. 该库对LZW解压数据这一步进行优化,使用C++代码重新实现了LZW解压算法,并进行了局部优化.性能上是要比原生Glide强的. 当然该库的三个解码器都可以进行逐个控制开启或关闭(APNG,WebP,Gif) 如下代码会禁用该库的Gif解码器(不推荐)

GlideApp.with(imageView)
                    .load(url)
                    .set(AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER, true)
                    .into(imageView);

penfeizhou avatar Nov 11 '21 02:11 penfeizhou

虽然解析gif放到了native层,但是我在实际测试中发现性能比glide自带的还要差,会不会与gifframe处理过程中把数据通过canvas绘制到bitmap,再又将bitmap的数据倒腾到framebuffer中,真正绘制的时候,会再次将数据生成到bitmap有关。

Lieeber avatar Nov 11 '21 04:11 Lieeber

实际测试是怎么测试的呢

jingpeng avatar Nov 11 '21 04:11 jingpeng

用的android studio的 profile工具

Lieeber avatar Nov 11 '21 04:11 Lieeber

这个是使用本库加载gif的性能图CPU部分 截屏2021-11-11 下午1 05 02

这个是默认glide加载同一张gif的的性能图CPU部分 截屏2021-11-11 下午1 06 16

jingpeng avatar Nov 11 '21 05:11 jingpeng

使用本库加载同一个图CPU会降低

jingpeng avatar Nov 11 '21 05:11 jingpeng

这个是使用本库加载gif的性能图内存部分 截屏2021-11-11 下午1 12 58 这个是默认glide加载同一张gif的的性能图内存部分 截屏2021-11-11 下午1 11 34

内存消耗本库略微低一点

jingpeng avatar Nov 11 '21 05:11 jingpeng

world-cup 使用的是这个gif,43k大小,内存本库会节约几M

jingpeng avatar Nov 11 '21 05:11 jingpeng

用的android studio的 profile工具

能否提供更明确的截图信息和测试方法,这个结论跟我之前测试的结果不符

penfeizhou avatar Nov 11 '21 06:11 penfeizhou

虽然解析gif放到了native层,但是我在实际测试中发现性能比glide自带的还要差,会不会与gifframe处理过程中把数据通过canvas绘制到bitmap,再又将bitmap的数据倒腾到framebuffer中,真正绘制的时候,会再次将数据生成到bitmap有关。

对于数据的传输,是一个拷贝过程,相对于图片解码整个流程来说影响较小

penfeizhou avatar Nov 11 '21 06:11 penfeizhou

world-cup 使用的是这个gif,43k大小,内存本库会节约几M

对于更大或更多的Gif,效果会更明显

penfeizhou avatar Nov 11 '21 06:11 penfeizhou

我用的图片比较大,为了效果更明显。 加载的图片为下面6张。没张大小都十几兆。 "https://cdn.pokekara.com/sp1/pokekara/gif/large/61/7c/6105f1403478f6e8deefb401394d987c_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/ba/d4/baf131714001c518e47bbc6b9a8a7bd4_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/02/04/029fbb80847025afb926891c11248804_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/a1/44/a1f34d8009839932f99c162fa8dc7444_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/46/3e/46b811d86929b3316c4098ccfddc103e_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/0e/aa/0e1795452a8d69ee8511e5c9830a22aa_600-600-1.gif" 前两张图片是使用本库加载时的cpu和内存。后两张图是使用glide加载时的cpu和内存。 image image image image

Lieeber avatar Nov 11 '21 06:11 Lieeber

Screenshot_20211111-145302

Lieeber avatar Nov 11 '21 06:11 Lieeber

先对比下一张图?控制变量

jingpeng avatar Nov 11 '21 07:11 jingpeng

一张图cpu和内存差别不太大。用小图区别更加不明显。

Lieeber avatar Nov 11 '21 07:11 Lieeber

稍等,我来复现一下你的测试结果.

penfeizhou avatar Nov 11 '21 07:11 penfeizhou

ok稍后我看下

jingpeng avatar Nov 11 '21 07:11 jingpeng

我用的图片比较大,为了效果更明显。 加载的图片为下面6张。没张大小都十几兆。 "https://cdn.pokekara.com/sp1/pokekara/gif/large/61/7c/6105f1403478f6e8deefb401394d987c_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/ba/d4/baf131714001c518e47bbc6b9a8a7bd4_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/02/04/029fbb80847025afb926891c11248804_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/a1/44/a1f34d8009839932f99c162fa8dc7444_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/46/3e/46b811d86929b3316c4098ccfddc103e_600-600-1.gif", "https://cdn.pokekara.com/sp1/pokekara/gif/large/0e/aa/0e1795452a8d69ee8511e5c9830a22aa_600-600-1.gif" 前两张图片是使用本库加载时的cpu和内存。后两张图是使用glide加载时的cpu和内存。 image image image image

我这边测试下来确实如此,稍等我进一步验证下.

penfeizhou avatar Nov 11 '21 07:11 penfeizhou

好的 辛苦

Lieeber avatar Nov 11 '21 08:11 Lieeber

在图片较大时,因为数据较大导致native层需要分批调用Reader接口从Java层拿数据,导致JNI调用次数急剧攀升,用于测试的图片每一帧都有数千次JNI的调用,JNI开销导致整体方法性能迅速劣化. 目前建议该情况先通过设置AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER避免该情况. 我会继续跟进,感谢反馈该问题.

penfeizhou avatar Nov 11 '21 10:11 penfeizhou

好的 谢谢。

Lieeber avatar Nov 12 '21 03:11 Lieeber

我再补充一些: Glide默认支持Gif解析,但在实际中,发现,当列表中有大量Gif同时播放时,低端的手机很容易会出现卡顿的情况,CPU占用很高. 该库对LZW解压数据这一步进行优化,使用C++代码重新实现了LZW解压算法,并进行了局部优化.性能上是要比原生Glide强的. 当然该库的三个解码器都可以进行逐个控制开启或关闭(APNG,WebP,Gif) 如下代码会禁用该库的Gif解码器(不推荐)

GlideApp.with(imageView)
                    .load(url)
                    .set(AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER, true)
                    .into(imageView);

你们只是把解析放在了native层,但是当gif解析成一张张的bitmap后,这些bitmap的解析并没有放在native层。

GuoLiangjun123 avatar May 06 '22 10:05 GuoLiangjun123

我再补充一些: Glide默认支持Gif解析,但在实际中,发现,当列表中有大量Gif同时播放时,低端的手机很容易会出现卡顿的情况,CPU占用很高. 该库对LZW解压数据这一步进行优化,使用C++代码重新实现了LZW解压算法,并进行了局部优化.性能上是要比原生Glide强的. 当然该库的三个解码器都可以进行逐个控制开启或关闭(APNG,WebP,Gif) 如下代码会禁用该库的Gif解码器(不推荐)

GlideApp.with(imageView)
                    .load(url)
                    .set(AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER, true)
                    .into(imageView);

你们只是把解析放在了native层,但是当gif解析成一张张的bitmap后,这些bitmap的解析并没有放在native层。

不明白你说的bitmap的解析是什么东西, bitmap就是像素点的集合,不需要什么解析,这也不是性能的瓶颈点

penfeizhou avatar May 06 '22 10:05 penfeizhou

我再补充一些: Glide默认支持Gif解析,但在实际中,发现,当列表中有大量Gif同时播放时,低端的手机很容易会出现卡顿的情况,CPU占用很高. 该库对LZW解压数据这一步进行优化,使用C++代码重新实现了LZW解压算法,并进行了局部优化.性能上是要比原生Glide强的. 当然该库的三个解码器都可以进行逐个控制开启或关闭(APNG,WebP,Gif) 如下代码会禁用该库的Gif解码器(不推荐)

GlideApp.with(imageView)
                    .load(url)
                    .set(AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER, true)
                    .into(imageView);

你们只是把解析放在了native层,但是当gif解析成一张张的bitmap后,这些bitmap的解析并没有放在native层。

不明白你说的bitmap的解析是什么东西, bitmap就是像素点的集合,不需要什么解析,这也不是性能的瓶颈点

gif是被解析成一张张的bitmap绘制在屏幕上的,解析这些bitmap的时候你们是放在哪解析的,还是说你们用的giflib?

GuoLiangjun123 avatar May 06 '22 10:05 GuoLiangjun123

Glide默认支持gif开销最大的不是在解析的过程,而是在生成一张张bitmap,而且在ImageView在显示一张bitmap的同时已经生成了下一张bitmap放在内存里,所以glide默认的gif加载内存才会居高不下

HolinB avatar Feb 16 '23 03:02 HolinB