2017-04-18 120 views
1

在我的应用程序中,我有几个简单的场景(一个单一的80段球体,500px乘1000px纹理,每分钟旋转一次)立即显示。当我打开应用程序时,一切都很顺利。我的内存使用量不到50mb,CPU使用率在30%左右,可以达到120fps。但是,如果我最小化应用程序并在一分钟后回到应用程序,或者停止与应用程序交互一段时间,则场景都会严重滞后,并且可能会出现4 fps左右,尽管Xcode报告30fps,正常的内存使用情况,以及超低(〜3%)的CPU使用率。SceneKit场景滞后恢复应用程序

在真正的iPhone 7 iOS 10.3.1上测试时,我得到这种行为,我不确定这种行为是否存在于其他设备或仿真器上。 这里是一个示例项目,我一起来展示这个问题。 (link here)我在这里做错了什么?如何让场景唤醒并恢复使用尽可能多的cpu来维持良好的fps?

+0

我现在已经确认这个问题不会发生在iPhone SE上的iOS 10.2上。 – Timestretch

回答

0

因此,我终于想出了一个部分功能的解决方案,即使它不是我认为的那样。

我尝试的第一件事就是将所有节点保留在Sander的答案建议的单个全局场景中,并根据the second answer to this question.中的建议在其中一个SCNViews上设置委托也许这用于工作或在不同的上下文中工作,但它不适合我。

桑德最终如何帮助我的是使用我不知道存在的表现统计数据。我为他们制作了一个场景,并且对我的表现非常满意: 在运行的前几秒内,在应用程序获得戏剧性的帧丢失之前,性能显示读取240fps。 “这是为什么?”,我想。在60Hz显示屏的手机上,谁需要240 fps,尤其是当SceneKit默认为60时。那么它会打我:60 * 4 = 240.

我猜想的是每个场景中的更新触发了“金属冲洗”,意味着每个场景每秒刷新240次。我猜想这会缓慢地填充gpu缓冲区(或内存?我不知道),最终SceneKit需要开始清除它,并且4个视图中的240 fps仅仅是太多而无法跟上。 (这解释了为什么它最初在完全丢弃之前获得良好性能)。

我的解决方案(这就是为什么我说“部分解决方案”),是将每个SceneView的preferredredFramesPerSecond设置为15,总共为60(我也可以在手机上获得30,但我'米不知道这是否支撑在较弱的设备上)。不幸的是15fps显然是波涛汹涌,但比我最初的糟糕表现要好得多。

也许未来苹果将启用每个SceneView的独特刷新。

TL; DR:设置preferredFramesPerSecond在所有SceneView中总和为60。

+0

此外,我为表格视图中无限数量的场景解决此问题的方法是将prefferedFramesPerSecond设置为不可见的单元格上的0,当它们可见时设置15。 – Timestretch

3

我不会回答你直接询问的问题,但可以给你一些想法。

  1. 我发起你演示我的iPod上6个根(64位),iOS版10.3.1应用程序,它从一开始就落后多达约与FPS 2-3分钟。过了一段时间后,它开始顺利旋转。去背景前景后也是如此。它可以通过一些纹理缓存来解释。

  2. 我调整了一个SCNView的大小,使它适合屏幕,其他视图留下。设置v4.showsStatistics = true 在这里,我得到了什么 enter image description here

,你可以看到金属冲洗大约需要18.3毫秒的一帧,其只对一个SCNView。 根据这一answer on Stackoverflow

所以,如果我的理解是正确的,这将意味着“金属 冲洗”措施的CPU花在等待上显存的时间 腾出所以它可以把更多的数据和请求对GPU的操作。

所以我们可能会怀疑问题出在4个不同的SCNViews同时使用GPU。

  • 让我们检查它。与第2点相比,我已经删除了3个SCNViews,并将3个行星从这些视图移到前面。所以一个SCNView同时拥有4颗行星。这里是截图
  • enter image description here

    ,正如你可以看到金属冲它从一开始就占据了5毫秒,并且一切进展顺利。另外你可能会注意到,三角形的数量(右上图标)是我们在第一个屏幕截图上看到的数量的四倍。

    总结一下,试着在一个SCNView上合并所有的SCNNode,并且可能会加快速度。

    +0

    虽然这个答案很深入,但不幸的是我需要有多个SCNViews:我所显示的是UITableView中的单元格。如果我维护一个单一的全局场景对象,并将所有行星作为不同位置的节点添加到单独的摄像机中,并且每个SCNview都使用场景中的不同摄像机进行显示,这是否会提高性能而不是维护许多场景?我想这一切都归结为Metal如何刷新场景:如果每个相机一次或每个场景对象一次。 – Timestretch

    +0

    @Timestretch不幸的是,我不认为有一个SCNView的情况下,你必须显示几个UITableViewCells是适当的。可能您可能会通过减小图像大小来降低性能开销。尽管资源密集型的另一种方法是制作一个SCNView,并在需要使用的设计中制作,例如类似于UITableView。我记得Apple使用SCNKit做了关于Scene Kit的整个WWDC演示。 – Sander

    +0

    授予你赏金,因为我相当肯定你的答案让我找到正确的解决方案。希望我能在几天内得到答案 – Timestretch