【问题标题】:improve find performance提高查找性能
【发布时间】:2012-01-27 02:53:44
【问题描述】:

我有一个 bash 脚本,它可以根据用户输入压缩文件名。它运行良好,虽然速度很慢,因为我有时需要解析多达 50K 个文件。

find "$DIR" -name "$USERINPUT" -print | /usr/bin/zip -1 SearchResult -@

这里的 @ 符号表示 zip 将接受来自 STDIN 的文件名。有没有办法让它跑得更快?

我正在考虑创建一个 cron 作业来每晚更新定位数据库,但我不是 root,所以即使值得我​​也不这样做。

欢迎提出任何建议。

【问题讨论】:

  • 首先我到美分:type -d 将使find 只查找文件夹,所以原则上它应该有所作为。难道zip 是这里的瓶颈?我会使用tar czf insted 做一个测试来压缩文件,看看性能是否更好。
  • zip 很可能是问题所在:我选择它是因为数据上的用户严格来说是窗口用户。我不知道 GZIP 或 TAR 是否可以在 MS Windows 上创建任何可读的内容。欢迎任何意见。
  • 很难说你的瓶颈是什么。您确实应该首先分析这两个步骤,通过与压缩分开生成文件列表,将其放入临时文件而不是管道中。然后在每一步之前和之后调用date
  • 尝试使用 -0 作为参数而不是 -1 只是为了看看差异。 -0 表示根本没有压缩,因此您应该尽量减少 CPU 负载/瓶颈的影响。正如@mvds 建议的那样,将作业分成两部分,看看查找需要多长时间,以及压缩需要多长时间。
  • 鉴于进入 zip 文件的数据量很小,zip 不应该成为瓶颈。 zip 将在查找搜索中等待磁盘访问。根据下面的答案,在可用 CPU 允许的情况下,在单独的子目录结构路径上运行多个查找。

标签: bash find


【解决方案1】:

我建议你在 xargs 命令中使用并行处理来加快你的整个进程。使用这样的命令:

find "$DIR" -name "$USERINPUT" -print0 | xargs -0 -P10 zip -1 SearchResult -@

以上命令将使 xargs 运行 10 个并行子进程。

请像这样记录上述命令的时间:

time find "$DIR" -name "$USERINPUT" -print0 | xargs -0 -P10 zip -1 SearchResult -@

看看这是否能提高性能。

【讨论】:

  • 哇,好主意。我会尝试一下并更新这个线程。谢谢。
【解决方案2】:

正如 Mattias Ahnberg 所指出的,find 的这种使用将在调用 zip 之前生成匹配文件的完整列表。如果您要处理超过 50,000 个文件,则需要一些时间。也许更合适的方法是使用find-exec <cmd> {} \; 功能:

find "$DIR" -name "$USERINPUT" -exec /usr/bin/zip -1 {} \;

这样,find 会在每个匹配的文件上调用 zip 本身。您应该获得与原始版本相同的最终结果,但如果文件的绝对数量是您的瓶颈(如果文件都很小,则很可能是瓶颈),这将在开始查找匹配项后立即开始运行 zip ,而不是在找到所有匹配项时。

注意:我建议阅读手册页以了解此选项的详细信息。请注意,必须对分号进行转义,以防止您的 shell 解释它而不是将其传递给 find。

【讨论】:

    【解决方案3】:

    听起来您正在遍历文件系统,为 50,000 个文件中的每一个运行查找。

    为什么不执行一次 find 来记录文件系统中所有文件的名称,然后直接从该日志文件中提取它们的位置?

    或者,将工作分解为单独的作业,尤其是在您有多个文件系统和多个 CPU 的情况下。在你的方法中不需要是单线程的。

    【讨论】:

    • 他的 find-oneliner 在一个块中生成所有匹配的文件名,并且不会逐个文件调用 zip。他使用 -@ 参数将该列表通过管道传输到 zip 中(从 STDIN 获取文件列表),并且还利用 -1 进行最小压缩(尽管有一个 -0 表示不压缩可能尝试)。
    猜你喜欢
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 2012-04-30
    • 2021-08-03
    • 2013-02-17
    相关资源
    最近更新 更多