首页 > 解决方案 > 在 Swift 线程中限制 CPU 使用率

问题描述

我想遍历文件树以查找 macOS 应用程序中可能很大的目录。如果我只是这样做,我的示例案例大约需要 3 分钟,但在这 3 分钟内 CPU 会飙升至 80% 左右。

我可以负担得起在后台线程上更慢地执行此操作,但不确定最好的方法是什么。

我想在循环中插入 1 毫秒睡眠,但我不确定这不会对调度/磁盘 IO 等产生负面影响。另一种方法是做 1 秒的工作,然后等待 2-3 秒,但我猜还有更优雅的东西?

我想要的核心功能是以嵌套方式遍历目录检查文件属性:

let enumerator = FileManager.default.enumerator(atPath: filePath)
while let element = enumerator?.nextObject() as? String {
     // do something here
 }

标签: swiftmacos

解决方案


通常,在短时间内使 CPU 达到峰值比在较长时间内以低电平运行 CPU 是最节能的。只要您的进程的优先级低于其他进程,即使在短时间内以 100% 的速度运行 CPU 也不是问题(特别是如果它没有打开风扇)。现代 CPU 希望在短时间内非常努力地运行,然后完全空闲。较长时间的“有点忙”会更糟,因为 CPU 无法关闭任何子系统。

即便如此,当用户看到高 CPU 使用率时,他们还是会非常沮丧。我曾经从事系统管理软件的工作,我们与 Apple 讨论了限制我们的 CPU 使用率的问题。他们告诉我们以上。我们说“是的,但是当用户看到我们在 100% 运行时,他们会向 IT 投诉并尝试卸载我们的应用程序。” Apple 的答案是使用sleep,就像您所描述的那样。如果它使您的过程花费更长的时间,那么它可能会对总能源使用产生负面的整体影响。但我不认为它会引起任何其他麻烦。

也就是说,如果您多次扫描同一个目录树,您应该查看文件系统事件文件元数据搜索,它们可以更有效地执行此操作。

另请参阅:Mac 应用程序能效指南中的计划后台活动。我强烈推荐整个文档。近年来,macOS 中添加了许多可能对您的问题有用的工具。我还建议从 WWDC 2017编写节能应用程序。

如果您确实需要使用枚举器直接扫描所有内容,则可以通过使用基于 URL 的 API而不是基于字符串的 API 来极大地改进事情。它允许您预取某些值(包括attributeModificationDateKey,可能在此处使用)。另外,请注意fileAttributesDirectoryEnumerator 的属性,它缓存最后读取文件的属性(因此您无需再次查询它们)。

三分钟是很长的时间;有可能你做的工作比需要的多。使用命令行工具运行您的操作,find并将其用作应该花费多少时间的基准。


推荐阅读