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文件夹,里面是测试各项性能的代码。

相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
小程序 JavaScript
【微信小程序】-- WXML 模板语法 - 事件绑定 -- tap & input (十)
【微信小程序】-- WXML 模板语法 - 事件绑定 -- tap & input (十)
|
Java Android开发
Android如何通过Gradle发布Android依赖库(aar)到 jitpack 公共仓库
Android如何通过Gradle发布Android依赖库(aar)到 jitpack 公共仓库
932 0
|
4月前
|
SQL JavaScript API
Node.js 24 原生 SQLite 支持
Node.js 24 原生支持 SQLite(`node:sqlite`),无需第三方库即可高效操作数据库。提供同步 API,含 `DatabaseSync`、预编译语句及完整 CRUD 方法,适用于脚本、工具和轻量服务,零依赖、安全简洁。(239字)
639 1
|
机器学习/深度学习 算法 API
MiniMax-M1开源:支持百万级上下文窗口的混合MoE推理模型!
MiniMax最新发布了全球首个开源大规模混合架构的推理模型——MiniMax-M1!
967 0
|
缓存 Android开发
Skia深入分析5——skia文字绘制的实现
文字绘制主要包括编码转换(主要是中文)、字形解析(点线或image)和实际渲染三个步骤。在这个过程中,字形解析和实际渲染均是耗时步骤。Skia对文字解析的结果做了一套缓存机制。在中文字较多,使用多种字体,绘制的样式(粗/斜体)有变化时,这个缓存会变得很大,因此Skia文字缓存做了内存上的限制。 1、SkPaint 文字绘制与SkPaint的属性相关很大,先回头看下SkPaint相关
7806 0
|
存储 API Android开发
Skia深入分析
原文出处:http://blog.csdn.net/hgl868/article/details/45583667 一、渲染层级从渲染流程上分,Skia可分为如下三个层级:1、指令层:SkPicture、SkDeferredCanvas->SkCanvas这一层决定需要执行哪些绘图操作,绘图操作的预变换矩阵,当前裁剪区域,绘图操作产生在哪些layer上,Layer的生成与合并。
5218 0
|
算法
[白话解析] 深入浅出一致性Hash原理
[白话解析] 深入浅出一致性Hash原理
|
消息中间件 数据可视化 Java
【Java】The Java Headless Mode
【Java】The Java Headless Mode
485 0
【Java】The Java Headless Mode
|
机器学习/深度学习 算法 PyTorch
机器学习之PyTorch和Scikit-Learn第6章 学习模型评估和超参数调优的最佳实践Part 2
本节中,我们来看两个非常简单但强大的诊断工具,可帮助我们提升学习算法的性能:学习曲线和验证曲线,在接下的小节中,我们会讨论如何使用学习曲线诊断学习算法是否有过拟合(高方差)或欠拟合(高偏置)的问题。另外,我们还会学习验证曲线,它辅助我们处理学习算法中的常见问题。
868 0
机器学习之PyTorch和Scikit-Learn第6章 学习模型评估和超参数调优的最佳实践Part 2