android - 无法跟踪从另一个线程呈现的帧
问题描述
我们公司为包括Android在内的移动平台开发了几款游戏。我们将 OpenGL 用于所有视觉项目,包括 UI(更多技术细节如下)。
我们在发布前报告中收到了来自 Google Play 控制台的一些奇怪警告,例如“您的应用启动时间为 20764 毫秒”。在此报告提供的视频中,游戏大约需要一秒钟才能开始。
经过一番调查,我们发现 Android Systrace 无法检测到来自另一个线程的 OpenGL 绘图。所以发布前测试(错误地)认为我们的游戏超级慢。
是否有某种方法可以通知系统绘制了框架?似乎 eglSwapBuffers() 还不够。
Cocos2d 有相同问题的链接:https ://discuss.cocos2d-x.org/t/frozen-frames-warnings-by-google-play-pre-launch-report-for-3-17-cocos-演示应用程序/42894
一些细节
当新版本发布到 Google Play 控制台时,会在不同的设备上执行一些自动化测试。这些测试的结果可在 Google Play 管理中心的发布前报告部分中找到。
从 4 月初开始,我们在某些设备上收到了奇怪的性能警告(总是相同的)。两个例子:
- 启动时间:您的应用启动时间为 20764 毫秒……</li>
- 冻结帧:33.33% 的帧渲染时间超过 700 毫秒
这两个问题听起来都很可怕——如果它们是真的。但是当我们查看测试视频时,我们看不到任何问题。所有游戏都开始得很快,运行时没有视觉卡顿。
系统跟踪报告
这是 systrace 的图片,显示了我们游戏开始的 5 秒(矩形是我画的)。
如您所见,systrace 仅发现渲染了 4 帧(粉红色矩形),这些帧是从 RenderThread 中绘制的。但由于某种原因,Android 无法检测到我们在另一个线程中执行的 GL 绘制调用(蓝色矩形)。
预发布报告也只显示 3 到 4 帧,每帧 300-400 毫秒长。
初始化代码
我们的游戏引擎在单独的线程中运行所有游戏逻辑和渲染代码。这是简化的初始化代码。
工作线程是从我们 Activity 的 onStart() 覆盖方法创建的。
public class MyActivity extends Activity
{
protected Thread worker = null;
private native void Run();
@Override
protected void onStart()
{
super.onStart();
if(worker == null)
{
worker = new Thread()
{
public void run()
{
Run();
}
};
worker.start();
}
}
}
线程唯一做的就是 Run() 本机函数。这个函数可以解析成这样的:
void MyActivity::Run()
{
initApp();
while(!destroyRequested())
{
// Process the game logic.
if (activated && window != NULL)
{
time->process();
input->process();
sound->process();
logic->process();
graphics->draw();
}
}
clearApp();
}
如您所见,工作线程不断地旋转更新和绘制循环。Vsync 可防止循环过度执行。诸如资源加载之类的繁重操作是异步完成的,以避免冻结。
从用户方面来看,这种方法效果很好。游戏加载速度快,运行顺畅。
解决方案
推荐阅读
- asp.net-core - asp.net核心路由参数始终为空
- python - 比较 Pandas DataFrame 中的 2 列并填充第 3 列
- angular7 - TypeError:无法读取 Angular 7 中未定义的属性“值”
- ios - 如何调整 Xcode 中的值以取决于播放的设备(iPhone 与 iPad)
- c# - Azure Function 将队列消息的 ISO 8601 UTC DateTime 格式修改为 Local DateTime 格式
- c# - 我在哪个文件中插入了 Azure 机器人服务的 Microsoft 文档中的示例代码?
- arraylist - 如何修复我的代码,以便在购买后返回更新的值
- google-apps-script - 尝试更新动态下拉代码以支持依赖于同一列的两列
- javascript - 我需要什么才能让一个使用 html/css ui 离线运行的小应用程序?
- javascript - 构建失败的 Cordova