惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
The Cloudflare Blog
IT之家
IT之家
V
V2EX
雷峰网
雷峰网
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
Stack Overflow Blog
Stack Overflow Blog
博客园 - Franky
Engineering at Meta
Engineering at Meta
S
SegmentFault 最新的问题
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
小众软件
小众软件
博客园 - 叶小钗
Blog — PlanetScale
Blog — PlanetScale
C
Check Point Blog
A
About on SuperTechFans
B
Blog
月光博客
月光博客
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI

博客园 - 翻滚的咸鱼

Ops权限行为记录源码解析 TaskView方案框架原理 视频解码器问题 常用命令 扫光动效 引导记录 View共享动效 常用脚本文件 Launcher 卡片框架多模块集成 Launcher 桌面源码笔记二 Launcher 桌面源码笔记一 氛围灯动态屏保取色方案二 氛围灯动态屏保取色方案一 自定义最近任务管理器 anr问题 TV RecyclerView 焦点处理笔记 多类型适配器 多屏下字体自动取色 阻尼拉伸方案 图片区域点击处理 RecyclerView设置默认焦点跟多页面焦点抢占 TV RecyclerView 滑动后操作保持落焦在左侧第一个View Fragment翻盖动效 当个View下,使用Drawable入场退场动画
性能优化
翻滚的咸鱼 · 2026-03-30 · via 博客园 - 翻滚的咸鱼

场景:同进程下,出现同时运行的动效,特别是全屏大图,对GPU渲染造成巨大负担

image

明显看出,动效过程中,trace显示异常,两个draw出现,图片大小为3200x2000,都在同一个render跟ui thread下进行提交渲染,(由于图片比较大,而且不能压缩跟裁剪处理),处于串行工作造成掉帧

方案一

针对这种情况,首先尝试利用Glide中的set(Downsampler.ALLOW_HARDWARE_CONFIG, true)api来优化,看下效果

image

可以看到,trace中已经没有upload图片了,这个api的用处,是用来缓存图片数据到GPU存储中的,这里的缓存不是指内存

在图片绘制过程中,每次图片动效,比如全屏轮播,都会带来GPU的重新渲染,跟本地是否缓存图片没关系,普通位图会在应用内存和 GPU 显存中各存一份像素数据

每次绘制时从 CPU 内存,将图片数据打包好,然后上传到 GPU,GPU具体渲染,这样处理可以减少GPU的压力

但是也有限制,比如针对bitmap的 getPixel setPixel 将无法操作,对渲染绘制方面限制,高斯模糊,圆角等都会抛出异常,并且数量不能过多,每个进程都有一个FD上限(文件描述符),超过了1024会导致加载失败,而每个图片缓存都会消耗一个FD,所以需要谨慎使用

trace中看到,其实只是针对upload部分,但是buffer等操作不可避免,依然是在同线程处理,但也可以应付大部分场景了

当然,前提是在应用内,已经优化到极致,比如图片加载时使用override裁剪处理,图片对清晰度要求不高可以压缩处理等

方案二

多线程处理,将该部分绘制丢到子线程中操作

image

可以看到,渲染部分交给了单独线程中service去绘制,不过buffer部分依然实在主线程

通过上面验证,想要进一步优化,只能独立进程,才能彻底分离,否则只能在draw层次去优化

场景:动效卡顿掉帧

image

看出一帧内绘制了五张大图,导致GPU紧张

动效图片是自定义上下轮播View,初始化时add了五个imageview,因为一些可定制跳转需求,recyclerview等无法满足

优化:针对动效动态控制显示隐藏

override fun setTranslationX(translationX: Float) {
        super.setTranslationX(translationX)
        updateVisible()
    }

    override fun setTranslationY(translationY: Float) {
        super.setTranslationY(translationY)
        updateVisible()
    }

    override fun setAlpha(alpha: Float) {
        super.setAlpha(alpha)
        updateVisible()
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        updateVisible()
    }

    private fun updateVisible() {
        visibility = if (
            translationX >= measuredWidth || translationX <= -measuredWidth ||
            translationY >= measuredHeight || translationY <= -measuredHeight ||
            alpha == 0f
        ) {
            INVISIBLE
        } else {
            VISIBLE
        }
    }

View Code

动效过程中,一共只需要显示两张图片,动效结束后只需要显示一张图片,那么可以根据参数更新view状态,调整后在看新的trace

image

除了绘制,还需要关注measure

image

recyclerview中加载是否耗时

image

如果系统资源紧张,Runnable的时间会超过16ms,并且大量线程处于Runnable的状态,或者频繁触发GC

image

选中时间段,查看cpu占比率

image