【发布时间】:2016-03-23 18:07:15
【问题描述】:
上下文
我的应用程序模型是一个对象树,其中每个对象代表磁盘上给定起始文件夹下的一个文件系统项(文件夹或文件)。
定期地,我从上到下递归地遍历这棵树,以便将它“同步”到文件系统的实际状态。也就是说,我访问模型中的每个对象并验证它所代表的文件/文件夹是否仍然存在于磁盘上的同一位置。
如果文件/文件夹已移动,我使用NSURL 书签来确定文件/文件夹的新位置,以便更新模型的状态。 (我在第一次创建模型对象时创建了一个NSURL 书签,然后将书签数据存储为对象的一个属性,以便我以后可以解决它。)
问题
NSURL 书签性能不够。我的模型图有 20,000 个嵌套对象并不少见。每个人都有一个书签。这是我在分析性能时看到的:
recursivelyValidateExistingChildItemsOfParentItem:... 方法是遍历我的模型树的方法。所涉及的 90% 时间只是解决书签(如果它们过时,则按照 Apple 文档中的说明重新创建它们)。
因此,该应用程序需要将近 2 分钟才能完成步行。所以,我需要一个更快的替代 NSURL 书签。
我的考虑
-
扩展文件属性。我可以为磁盘上的每个文件添加一个 UUID 属性。我可以遍历起始文件夹下的实际文件系统,而不是遍历我的模型图。当我找到一个新文件时,我可以查看它是否具有 UUID 扩展属性。如果是这样,我可以在我的模型图中搜索具有该 UUID 的对象以处理移动/重定位的文件。这里的问题是很多东西破坏了扩展文件的属性——它们不能保证会一直存在。
-
BDAlias或NDAlias。在迁移到NSURL书签之前,我曾经使用过BDAlias,但这并不是特别高效。
底线
我需要一个更快的替代NSURL 的书签。但是我仍然需要能够在我的应用程序启动时跟踪文件,所以简单地保持文件描述符打开或使用文件 ID 是行不通的。
我不在乎我必须达到多低的水平;我只需要表现。谢谢!
【问题讨论】:
-
定期地,我从上到下递归地遍历这棵树,以便将其“同步”到文件系统的实际状态。 这不是 NSURL 书签的性能,可能是您问题的很大一部分。您可能无法避免在每次启动时验证大型目录结构,但此后您不需要扫描整个内容 - 相反,使用FSEvents API 来通知文件系统更改,这样您就可以只扫描您需要的内容到,当你需要的时候。
-
谢谢瑞克斯特。你可以假设 FSEvents 和我亲密相识。我对该 API 的各个方面都非常熟悉。非常适合学习,“文件夹 X 中的内容已更改”。知道以前在 X 中的东西去了哪里并不是很好——这正是我需要解决的问题。即使在文件级粒度模式下,FSEvents 也不是合适的解决方案。而且,正如您所指出的,它对发布没有帮助。
-
另外:我不是故意不屑一顾的。有很好的理由需要我的全面扫描方法。 FSEvents 可以删除事件,当 FSEvents 不跟踪时用户可能会更改文件系统(例如在另一台 Mac 上的可移动 USB 密钥上),某些文件夹实际上是通过 MacFuse 安装的远程服务器,它不会处理相同的事件等。为了简洁起见,我把这些东西放在外面。我希望我不必进行全面扫描,但这是处理所有边缘情况的唯一可靠方法。
标签: objective-c macos performance cocoa nsurl