GPU|如何用 GPU硬件层加速优化Android系统的游戏流畅度( 二 )


【GPU|如何用 GPU硬件层加速优化Android系统的游戏流畅度】
经友盟+ U-APM自定义异常测试 , 下列机型会产生高libGLES_Mali.so占用的问题 , 因此我们需要基于底层硬件的运行情况来解决流畅性问题 , 同时由于存在问题的机型不止一种 , 我们需要从内存层面着手 , 考虑如何调用较少的内存缓存区并及时释放内存 。

解决方案及优化 基于前文的分析 , 我们首先尝试从缓冲区入手进行优化 。 单缓冲区方案? 使用glMapBufferRange和GL_MAP_UNSYNCHRONIZED.然后使用单个缓冲区内的子区域构建旋转 。 这避免了对多个缓冲区的需求 , 但是这一方案仍然存在一些问题 , 我们仍需要处理管理子区域依赖项 , 这一部分的代码给我们带来了额外的工作量 。 多缓冲区方案? 我们尝试在系统中创建多个缓冲区 , 并以循环方式使用缓冲区 。 通过计算我们得到了适合的缓冲区的数目 , 在之后的帧中 , 代码可以去重新使用这些循环缓冲区 。 由于我们使用了大量的循环缓冲区 , 那么大量的日志记录和数据库写入是非常有必要的 。 但是有几个因素会导致此处的性能不佳:1. 产生了额外的内存使用和GC压力2. Android 操作系统实际上是将日志消息写入日志而并非文件 , 这需要额外的时间 。 3. 如果只有一次调用 , 那么这里的性能消耗微乎其微 。 但是由于使用了循环缓冲区 , 所以这里需要用到多次调用 。 我们会在基于c#中的 Mono 分析器中启用内存分配跟踪函数用于定位问题:
$ adb shell setprop debug.mono.profile log:callsalloc
我们可以看到该方法在每次调用时都花费时间:
Method call summary Total(ms) Self(ms) Calls Method name 782 5 100 MyApp.MainActivity:Log (stringobject[
) 775 3 100 Android.Util.Log:Debug (stringstringobject[
) 634 10 100 Android.Util.Log:Debug (stringstring)
在这里定位到我们的日志记录花费了大量时间 , 我们的下一步方向可能需要改进单个调用 , 或者寻求全新的解决方案 。
log:alloc还让我们看到内存分配;日志调用直接导致了大量的不合理内存分配:
Allocation summary Bytes Count Average Type name 41784 839 49 System.String 4280 144 29 System.Object[

硬件加速 最后尝试引入硬件加速 , 获得了一个新的绘图模型来将应用程序渲染到屏幕上 。 它引入了DisplayList 结构并且记录视图的绘图命令以加快渲染速度 。
同时 , 可以将 View 渲染到屏幕外缓冲区并随心所欲地修改它而不用担心被引用的问题 。 此功能主要适用于动画 , 非常适合解决我们的帧率问题可以更快地为复杂的视图设置动画 。
如果没有图层 , 在更改动画属性后 , 动画视图将使其无效 。 对于复杂的视图 , 这种失效会传播到所有的子视图 , 它们反过来会重绘自己 。
在使用由硬件支持的视图层后 , GPU 会为视图创建纹理 。 因此我们可以在我们的屏幕上为复杂的视图设置动画 , 并且使动画更加流畅 。
代码示例:
// Using the Object animator view.setLayerType(View.LAYER_TYPE_HARDWARE null); ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view View.TRANSLATION_X 20f); objectAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setLayerType(View.LAYER_TYPE_NONE null);); objectAnimator.start(); // Using the Property animator view.animate().translationX(20f).withLayer().start();
另外还有几点在使用硬件层中仍需注意:
(1)在使用之后进行清理:
硬件层会占用GPU上的空间 。 在上面的 ObjectAnimator代码中 , 侦听器会在动画结束时移除图层 。 在 Property animator 示例中 , withLayers() 方法会在开始时自动创建图层并在动画结束时将其删除 。