Skia深入分析10——Skia库的性能与优化潜力

简介: Skia库性能与优化潜力图形/渲染算法/架构作为图形渲染引擎,性能上是非常重要的,按通常Android手机60帧的刷新率,绘制一帧的总时间只有16ms,可谓是毫厘必争。提升性能到最后,就必然跟不同CPU的特性打交道,毕竟一个SIMD下去,好做的提升5、6倍,不那么好做的也达到2、3倍,收益极其可观。 SIMD,在intel上是SSE,在arm上是neon,在

Skia库性能与优化潜力

图形/渲染

算法/架构

作为图形渲染引擎,性能上是非常重要的,按通常Android手机60帧的刷新率,绘制一帧的总时间只有16ms,可谓是毫厘必争。提升性能到最后,就必然跟不同CPU的特性打交道,毕竟一个SIMD下去,好做的提升5、6倍,不那么好做的也达到2、3倍,收益极其可观。
SIMD,在intel上是SSE,在arm上是neon,在mips上则是其dsp功能。使用SIMD,需要代码架构是满足内存连续性要求的,否则需要重构,Skia作为正常的图形渲染引擎,采用行渲染方式,易于实现SIMD。在充分优化的场景,其速度与GPU渲染不相上下。
总体而言,Skia库的渲染架构是遵循连续性,易于优化的。目前Skia中的高频使用函数基本上都进行了优化,并且由于软件渲染使用频率的降低,进一步优化的价值不大。但从代码层面来看覆盖率并不是特别高,遇到特定场景卡顿了,还是可以挖出几个函数优化下的。
从算法来看,Skia里面的图形绘制算法基本上都达到了最优,没有什么多余的步骤。编解码方面,存在一些多余的内存拷贝、采样缩放等。

行填充

这里面的行填充包括一行像素的透明度混合、颜色格式转换、抖动处理。在SkBlitter构建时,根据源、目标像素格式和paint属性挑选。
neon优化的相关代码见 src/opts/SkBlitRow_opts_arm_neon.cpp
主要通过 platformProc的转换而得。
大部分行填充的类型是做了neon优化的,这些也是用得很频繁的函数。

图像绘制

Sprite流程

在前面有讲述,将用来绘制的图像预先旋转缩放好,使之和目标区域一样大,并且坐标没有小数位,可以走进Sprite流程。但目前有不少限制,这些不支持的情况并不是原理不允许,而是没有做,有需要的话可以补上。
详细见
SkSpriteBlitter::ChooseD16
SkSpriteBlitter::ChooseD32

采样

前面已有说明图像采样的设计。
对于Matrix proc,在SkBitmapProcState::chooseMatrixProc函数中决定函数分支。
这些函数也是公共头文件加宏组合出来的。
neon的详见:
src/opts/SkBitmapProcState_matrixProcs_neon.cpp
src/opts/SkBitmapProcState_matrixProcs_neon.h
主要是一次计算四个坐标

对于采样的
src/opts/SkBitmapProcState_filter_neon.h
它与
src/core/SkBitmapProcState_procs.h
构成函数。
这个功能是只是做一个像素的双线性插值计算(计算过程向量化实现)。感觉优化力度并不够。

在仅缩放的插值情况,由于一行的像素是相邻的,插值计算以行为单位处理会比较效率。

高级插值似乎是没有做优化,用得也少,这个还是靠GPU优化好些。

文本绘制

文本绘制中,Skia很关键的优化方法是建立了字形Mask缓存机制,blitMask过程和blitRect的过程相似,也是用的加速过的行渲染函数。这样在绘制文字固定时只是第一次解析字体构建缓存慢。
不过在生成字体Mask缓存的流程中,generateImage函数并没有充分优化。
Mask需要占用一定量的内存,Skia中可以设置其上限(默认8M),这个是每个应用都占这么多,整个系统加起来其实就很大了。应用如果经常变字形,改效果,这个内存很快就会到上限,然后就经常找不到cache从而性能下降。
在一些情况下无法建Mask缓存,只能存路径SkPath,这时的性能也会差一些。

路径绘制

路径绘制里计算边界的过程基本上没有什么好方法优化,填充时也是利用行渲染函数和采样算法。

图像/算法

编解码

解码速度在系统中还是比较重要的,关系到应用开启的速度。
Google对其优化主要在对应的编解码库中实现,Skia里面只是配置参数。
而Skia本身的一些处理如颜色转换、下采样等可能被认为相对解码本身而言较短,并没有做优化。但做一下估计还可以提升5%左右。
制作SOC的厂商可能会修改这一部分代码,使之用特定DSP等硬件实现。不过考虑到硬件编解码的一些限制,还是会有不少场景不得不回归软件编解码。
区域解码基本上是用硬件优化不了或优化不好的,如果内存足够,使用硬解码后原理上也不需要区域解码这种方式提高速度。

特效

特效主要是SkMask,里面有高斯模糊、光照效果等的实现。
其优化的代码也在 src/opts/目录下。
在CPU上做这种代码的优化,需要把浮点转成近似整数,会有一定的精度误差。还是走GPU加速的方案好些。

GPU

Skia-GPU在当前的方式下,需要将绘制结果拷贝出来,因而不好用做渲染。
但如果修改一下,允许外界输入 EGL-Image来创建SkSurface,映射为输出的纹理和FBO,便可以将这次拷贝避免。不过,不走窗口系统,仅仅只是输出到一个纹理是否会对GPU性能有影响,很难说。
Skia-GPU流程的缓存的管理感觉不如硬件加速引擎hwui那一套好。

BenchMark

Skia目录下面有个 bench文件夹,里面是测试各项性能的代码。

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
6月前
|
大数据 API 图形学
Unity优化——批处理的优势
Unity优化——批处理的优势
164 0
|
3月前
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
63 10
|
20天前
|
编解码 Android开发 UED
构建高效Android应用:从内存优化到用户体验
【10月更文挑战第11天】本文探讨了如何通过内存优化和用户体验改进来构建高效的Android应用。介绍了使用弱引用来减少内存占用、懒加载资源以降低启动时内存消耗、利用Kotlin协程进行异步处理以保持UI流畅,以及采用响应式设计适配不同屏幕尺寸等具体技术手段。
42 2
|
3月前
|
缓存 监控 Android开发
构建高效的Android应用:从内存优化到用户体验
【7月更文挑战第57天】 在竞争激烈的移动市场中,一个高效、流畅且具有优秀用户体验的Android应用是成功的关键。本文将深入探讨如何通过内存管理和界面优化来提升应用性能,包括实用的编程技巧和策略,以及如何利用Android系统提供的工具进行调试和性能监控。读者将学习到如何识别和解决常见的性能瓶颈,以及如何设计出既美观又实用的用户界面。
|
5月前
|
编解码 缓存 Android开发
构建高效的Android应用:从内存优化到响应式设计
【5月更文挑战第37天】 在竞争激烈的移动应用市场中,一个高效、流畅的Android应用是吸引和保留用户的关键。本文将深入探讨构建高效Android应用的多个关键方面,包括内存优化策略、布局性能和响应式设计原则。我们将通过具体的技术实践和案例分析,揭示如何提升应用性能,减少资源消耗,并确保在不同设备上的兼容性和用户体验一致性。
|
6月前
|
移动开发 测试技术 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【5月更文挑战第15天】 在移动开发领域,一个成功的Android应用不仅需要具备吸引用户的功能,更应提供流畅和高效的用户体验。随着技术的不断进步,开发者面临着将先进技术集成到现有架构中以提高应用性能的挑战。本文将深入探讨如何通过最新的Android框架和工具来优化应用性能,包括对UI的响应性、内存管理以及多线程处理等关键方面的改进,旨在帮助开发者构建出更加强大、快速且稳定的Android应用。
|
6月前
|
存储 缓存 算法
构建安卓应用的高效图片加载策略
【4月更文挑战第16天】在移动设备上优化用户体验的关键之一是快速而高效的图片加载。对于Android平台而言,由于设备多样性和网络环境的不稳定性,设计一个既能提升速度又能减少资源消耗的图片加载策略尤为重要。本文将深入探讨在Android应用中实现图片加载的几种技术手段,包括图片格式选择、内存缓存、磁盘缓存以及使用第三方库等,旨在为开发者提供一套综合性的解决方案,以实现在不同设备和网络环境下的高效图片加载。
|
6月前
|
缓存 Android开发 UED
构建高效Android应用:从优化用户体验到提升性能
【5月更文挑战第15天】 在移动开发领域,构建一个高效的Android应用不仅仅意味着实现功能,还要确保流畅的用户体验和出色的性能。本文将深入探讨如何通过界面优化、代码整洁、资源管理和多线程处理等技术手段来提升Android应用的整体效率。我们将透过实际案例,揭示常见性能瓶颈的成因,并提供相应的解决方案。此外,文章还会涵盖最新的Android Studio工具和Lint检查的使用,帮助开发者早期发现潜在问题。
|
6月前
|
移动开发 监控 前端开发
构建高效Android应用:从内存优化到性能提升
【4月更文挑战第11天】在移动开发领域,一个流畅、高效的应用与用户体验息息相关。尤其对于安卓平台,设备的多样性和碎片化为开发者带来了额外的挑战。本文将探讨一系列针对Android应用的优化策略,从内存管理的最佳实践到布局优化,以及如何利用最新的Android框架特性来提升应用性能。我们将深入了解如何诊断性能瓶颈,并采用切实可行的技术手段进行调优,旨在帮助开发者构建出更加健壮、快速且响应灵敏的应用。
41 0
|
6月前
|
移动开发 Java Android开发
构建高效的Android应用:从内存优化到性能提升
【4月更文挑战第7天】 在移动开发领域,尤其是针对资源受限的Android设备,应用的性能和稳定性是决定用户满意度的关键因素。本文深入探讨了Android应用开发中如何通过内存优化、多线程处理以及电池使用效率的提升来增强应用的整体性能。我们将透过具体案例分析和最佳实践的分享,指导开发者避免常见的性能陷阱,打造更流畅、响应更快的Android应用。