【问题标题】:Performance of deleting folder with lots of files on iOS在 iOS 上删除包含大量文件的文件夹的性能
【发布时间】:2014-04-01 18:31:41
【问题描述】:

假设我的 iOS 应用程序的数据目录中有一个文件夹,其中包含数千个小文件。删除此文件夹(通过[NSFileManager removeItemAtPath])需要很长时间。但在 OS X 上,删除具有相同内容的文件夹非常快。它似乎只是从文件系统中取消链接文件夹。那么为什么iOS需要这么长时间呢?有什么区别?

编辑:在 iPad 3 上,删除 3 个包含 5,000 到 9,000 个文件的文件夹大约需要 35 秒。在旧版 Retina MBP 上运行的模拟器上,大约需要 1.5 秒。

【问题讨论】:

    标签: ios performance delete-file nsfilemanager


    【解决方案1】:

    你看到的层次结构不是“真实的”——目录 不是它们似乎包含的文件的物理容器。 目录层次结构是精心维护的虚构。

    无关紧要:原来的 Mac 文件系统迈出了这一步 进一步——它使目录结构完全是一种视觉虚构 -- 所有文件都在 (3.5") 软盘的根目录下,只有 似乎 被安排在文件夹中。谢天谢地,这是 被HFS取代。

    最好将目录/文件夹视为一种特殊的文件 包含一组文件的索引,假装 包含。

    从概念上讲,这很像经典的 Cocoa 内存管理。 每个(目录/对象)通过引用“拥有”一组(文件/对象) (“保留”(文件/对象))。

    当您从目录中删除文件时,它被“释放”。如果没有其他 目录对该文件有所有权声明,它是“dealloc'ed”。

    您的(文件夹/对象)不包含它“拥有”的对象。它 甚至没有真正“拥有”它们——它只是有一个“所有权要求” 他们。

    来自维基百科关于硬链接的文章:

    “硬链接是将名称与文件系统上的文件相关联的目录条目。目录本身就是一种特殊类型的文件, 包含此类条目的列表。”

    请注意,由于使用了硬链接,因此可能只有一个 可以出现在多个目录中的物理文件。每一个 这些目录拥有对“真实”文件的引用。每个参考 和其他任何东西一样“真实”。所有引用都必须“取消链接” 要标记为已删除的文件。

    “文件”甚至可以在不同的地方有不同的“名称” 目录!

    硬链接是文件系统功能的链锯——功能强大,但 可能相当危险。请注意,OSX GUI 不提供任何方法 产生硬链接,甚至符号链接。

    来自this email list item

    现在关于 iOS

    [NSFileManager removeItemAtPath:error:],它在 引擎盖是他们遍历子目录和文件并删除 他们先。这需要一些时间。如果有可能,我很感兴趣 立即执行此操作,甚至无需隐式递归。只需删除 目录和文件和子目录会消失吗?

    你能做的就是

    1. 如果您担心这会花费时间并且您需要即时结果,您可以重命名文件夹(这几乎是即时的),然后删除重命名的文件夹及其在后台线程中的内容。

    2. 如果时间有限,如果没有问题,请尝试在后台线程中运行删除进程。

    【讨论】:

    • 先重命名是个好主意。而且我已经通过 GCD 在后台线程上进行了删除。我只是好奇为什么差异如此之大。
    • @harsh,不,不可能删除目录并隐式删除文件。 unlink(2) 当除 root 以外的任何人在目录上调用时,删除指向 inode 链接的低级文件系统操作将因 EPERM 而失败。如果目录不为空,rmdir(2) 将失败并返回 ENOTEMPTY。
    • 大部分内容抄袭自this Apple email list item。请注明您的来源并在这种情况下使用块引用。
    【解决方案2】:

    不要在主线程上执行长时间运行的任务。考虑您要删除文档目录的所有内容。

    - (void) deleteDocumentsDirectoryContents
    {
        NSString *folderPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSError *error = nil;
        for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error])
        {
            [[NSFileManager defaultManager] removeItemAtPath:[folderPath stringByAppendingPathComponent:file] error:&error];
        }
    }
    

    像这样调用上面的函数。

    [self performSelectorInBackground:@selector(deleteDocumentsDirectoryContents) withObject:nil];
    

    【讨论】:

    • 谢谢。我已经在后台线程上做,但我很好奇为什么差异如此之大。
    【解决方案3】:

    您是在设备和 Mac 上进行测试,还是在模拟器和 Mac 上进行测试。
    在第一种情况下,差异是由于硬件造成的,iphone 比 mac 慢。
    在第二种情况下,您应该认为这是一个模拟器,因此内部机制可能会有所不同。
    这两个进程在sec上有什么区别?

    【讨论】:

    • 在 iPad 3 上,删除(实际上是删除 3 个文件夹,每个文件夹包含 5,000 到 9,000 个文件)大约需要 35 秒。在模拟器上(即 OS X 文件系统,在这种情况下是在较旧的 Retina MBP 上)大约需要 1.5 秒。
    • 正常情况下,您无法将 iPhone/iPad 硬件与 Mac 硬件进行比较。正如有人所说,您应该在后台运行该任务
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 2011-01-15
    • 1970-01-01
    • 2012-07-24
    • 2016-12-26
    • 2015-09-14
    相关资源
    最近更新 更多