iPhone 启动缓慢

4
我正在调试一个iPhone应用程序(Xcode,Objective C++)的启动速度问题。这是一个基于标签栏的应用程序,有三个标签页。这三个标签页在一个NIB中加载 - 大约有20个对象。
第一轮重要的初始化发生在第一个标签的视图控制器的viewDidLoad处理程序中。然而,在main()和该方法开始时间之间需要大约1秒钟 - 大约占总加载时间的2/3。问题是 - 在那段时间内发生了什么,并且我如何调查它(除了逐步通过反汇编代码)?据我所知,在两个时刻之间没有我的代码 - 延迟完全发生在系统代码中。
也许有一些工具可以给我每个函数的时间分布情况?
捆绑包总共大约4 MB,但我将最大的文件(约3.5 MB)加载到applicationDidFinishLaunching处理程序中。从捆绑包中删除该文件并注释掉相关代码对于1秒延迟毫无作用。
更新:确实存在调试干扰。如果我在设备上运行它并观看控制台,则启动时间会显着缩短,并且延迟比例-系统代码与我的代码-也会被扭曲。但仍然存在明显的延迟,即在main和viewDidLoad之间,它约占总加载时间的50%。
顺便说一句,从捆绑包中完全将一个较大的文件加载到内存中的所有方法中,最快的方法是直接内存映射(使用POSIX mmap())。
4个回答

4
如果你真的想知道启动期间正在执行什么操作,以及每个方法运行所花费的时间,你可以创建一个自定义的DTrace脚本来跟踪这个过程。我在这篇文章的末尾描述了如何操作。该脚本会按照启动顺序显示应用程序执行的每个方法,包括在-applicationDidFinishLaunching:结束时所花费的时间。您可以将此脚本作为自定义工具在Instruments中运行,也可以作为独立脚本运行(在系统负载下,独立脚本的精度更高)。
这种方法的主要限制是它仅在模拟器中运行,在iPhone OS中目前没有对DTrace的支持。但是,您应该能够提取应用程序启动时执行的顺序,以及应用程序在每个方法中花费的相对时间。这甚至会显示在应用程序启动时进行的幕后私有API调用,这可能提供一些额外的线索。
如果需要其他启动调整建议,我建议阅读James Thomson的文章“如何使您的iPhone应用程序启动更快”

3
这里可能有两个问题。如果你正在XCode内调试你的应用程序,很可能应用程序在启动时等待附加到GDB调试器。根据我的经验,这需要大约一秒钟时间。尝试在XCode中不使用“构建并运行”来运行您的应用程序,看看结果是否有所不同。(只需从主屏幕上点击它即可)
你的NIB文件也可能是问题所在。20个对象并不算太多,但如果其他方法都失败了,你可以考虑将每个选项卡分成单独的NIB文件。从主要NIB文件引用的NIB文件的内容将被惰性加载,因此应用程序在选择它们之前不会为两个隐藏的选项卡加载视图。这可能会在启动时提高性能,但我不认为它可以解决整个问题。
苹果在iPhone SDK中有一些很棒的性能分析工具,但它们有点难找。在Run菜单中,选择“Run with Performance Tool”->“CPU Sampler”。这将启动一个名为Instruments的单独应用程序,允许您进行各种出色的运行时分析。当您选择CPU工具时,Instruments窗口的底部提供了关于您的应用程序中哪些操作占用CPU时间的详细信息。您可以双击函数来深入了解它们,并获得使用%周期的一行一行的详细信息。它应该为您提供更多关于问题具体原因的信息。

我正在程序中计时,所以调试器的干扰应该是最小的。当main()获得控制权时,调试器应该已经附加了。我知道他们建议为选项卡使用单独的NIB,但我尝试从第二个和第三个选项卡中删除所有内容-延迟几乎相同。我运行了CPU监视器。有点难以解释。:(它说72%的时间在mach_msg_trap下花费-但那不是系统的通用“等待事件”函数吗? - Seva Alekseyev
实际上,我发现调试器确实会造成很大的干扰,特别是在启动时间方面。我的建议是让你的代码将时间记录到控制台中,在设备上手动启动应用程序,并从组织者中的设备控制台日志中读取计时。 - Brad Larson
我已经在使用NSLog()记录时间了。那会出现在组织者中吗? - Seva Alekseyev
如果没有通过Xcode运行应用程序,NSLog将被转储到系统日志中,并且它们的结果在组织者中可见(我已经看到组织者有点滞后,因此您可能需要多次启动应用程序才能使它们全部显示出来)。 - Brad Larson
天啊,我简直不敢相信这就是问题所在。当调试器连接到 iPhone 时,平均会有 8 秒的暂停(您可以使用组织者窗口中的控制台日志进行验证)。谢谢 Ben! - Rob S.

0
如果你发现你的xib文件太大了,我建议你使用纯代码构建你的UI。 大的xib文件肯定会减慢你的启动时间,并且在你第一次使用xib中的对象时也会减慢你的应用程序。
我在我的项目中不使用xib,因为当有人在svn中更改xib时,你很难找到更改的内容。也就是说,xib和SVN不兼容。

0
我建议将您的应用程序拆分为三个 NIBS;第一个包含在启动时显示的选项卡栏和选项卡栏控制器,然后在用户首次切换到它们时懒加载其他两个。
我相信您可以使用 Interface Builder 中的“文件>>分解界面”功能来实现此目的。

那是官方说法。但请看本回答下面的评论。 - Seva Alekseyev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接