我正在寻找高性能的 /bin/sort 替代品。我知道有 pbzip2 可以使用多核,但是有没有类似的 /bin/sort 产品?
我找到了 distsort.sh,但我想要一些不那么耗费 IO 的东西。我希望能够非常频繁地对 60 GB 的数据进行排序。
答案1
GNUsort
有 -m 可能可以帮到你。假设你有 200 个 .gz 文件需要排序和合并。然后你可以使用 GNU Parallel 来做:
seq 1 200 | parallel mkfifo /tmp/{}
ls *.gz | nice parallel -j200 'zcat {} | sort >/tmp/$PARALLEL_SEQ' &
seq 1 200 | parallel -X sort -m /tmp/{} >/tmp/sorted
如果 I/O 是问题而内存不是问题,则首先使用 -Ssort
以确保所有内容都保留在内存中。此外,lzop
每次写入磁盘时,您可能都想使用 (--compress-program=lzop):磁盘通常是限制因素,因此动态 lzopping 可以为您提供额外的速度。或者您可以制作一个 RAM 磁盘并将 -T 设置为该目录。
编辑 2023
其中一些想法现在parsort
,其测试结果也比上面的更好。
答案2
在搜索过程中,我发现了很多关于学术论文的参考资料,以及一款名为排序。我对此一无所知,只知道他们的网站声称:
Nsort 是一个排序/合并程序,可以快速对大量数据进行排序,并行使用大量处理器和磁盘。Nsort 的 CPU 效率独一无二,是唯一一款具有以下特点的商业排序程序:
- 1TB 排序(33 分钟)
- 1 GB/秒的文件读写速率
Nsort 在对海量生产数据集进行排序方面有着悠久的历史,例如:
- 高流量网站的网络日志
- 电话记录
- 政府机构数据
答案3
嗯。我想你会在这里遇到一些问题。首先,你的输入数据将对排序性能产生很大影响(不同的算法根据输入的分布表现更好或更差)。然而,前面一个更大的问题是 60GB 的数据量太大了。
此外,排序不像压缩那样容易并行化,因为没有接近性保证。换句话说,使用压缩/解压缩,您可以将输入分解为离散块,并分别独立地对它们进行操作。处理完每个块后,只需将它们连接在一起即可。使用排序,您需要执行多个步骤,因为您不能只连接结果(除非您进行一些预处理),您必须合并结果(因为在排序后,60GB 开头的条目可能会与 60GB 末尾的条目相邻)。
我基本上可以想到几个通用的解决方案:
- 以有利于排序和重组的方式对数据进行预分区。例如,如果您要进行简单的字母排序,您可以将数据存储在 26 个存储桶中,每个存储桶对应一个字母。然后,您可以单独对每个存储桶进行排序,最后重新组合它们。预分区数据的具体方法取决于数据本身、您当前的存储方法等。有些设置可能比其他设置更适合这种情况。
- 编写自己的排序前端,它基本上可以完成我上面写到的那些工作,但可以即时完成。换句话说,您将有一个脚本,它读取输入,并基于一些非常快速的操作(例如读取第一个字母,或任何适合您的数据的操作),然后将该数据分配到适当的排序存储桶中。每个排序都独立运行,直到处理完所有数据,然后将它们重新组合在一起。这实际上非常类似于使用 MapReduce 进行排序的特殊情况。
- 使用基于 MapReduce 的排序解决方案。有一个名为 Hadoop 的开源项目提供了许多子项目,其中一个是开源 MapReduce 实现。我从未使用过它,只是读过它。我不知道它是否适用于您的特定问题。
- 您能索引数据,然后对其进行排序吗?整个 60GB 是排序键的一部分吗?还是您要排序的是一个较小的部分,然后每个部分都有一堆额外的数据?如果是后者,那么只索引和排序某种键值,然后根据需要查找其他数据,可能是可行的方法。
- 也许您可以完全预先对数据进行排序,并将其保持在排序状态。每次添加或更新数据时,您都会从排序的角度进行更正。此解决方案高度依赖于您如何存储数据,以及排序更新对性能的影响是否可以接受。
- 最后,你可以放弃整个事情。将数据转储到 RDBMS(我自己喜欢 PostgresSQL),然后让数据库为你处理排序。
在不太了解您的数据和您正在做的事情的具体细节的情况下,这是我能提供的最佳建议。
[注意:我不是排序专家,所以比我聪明的人可能会指出我的逻辑中的错误,或者提出改进建议。]
答案4
编辑:嗯,这篇文章是关于 Perl 排序性能调优的。从我的理解来看,它基本上更像是一个最佳实践指南,比较了糟糕的排序代码如何使你的程序变得非常慢,以及相反,如何使它更快。
马虎的编程,马虎的性能。