#filtering #unique #logging #text-input #command-line #command-line-tool #command-line-utilities

bin+lib runiq

一种高效地从输入中过滤重复行的方法,类似于 uniq

10 个稳定版本

2.0.0 2024 年 1 月 5 日
1.2.2 2022 年 4 月 4 日
1.2.1 2021 年 1 月 1 日
1.2.0 2020 年 9 月 26 日
1.0.0 2018 年 5 月 7 日

#371文本处理

Download history 23/week @ 2024-03-11 31/week @ 2024-04-01 1/week @ 2024-05-20 28/week @ 2024-05-27 16/week @ 2024-06-03 16/week @ 2024-06-10 13/week @ 2024-06-17 11/week @ 2024-06-24

每月 62 次下载

MIT 许可证

32KB
395

runiq

Build Status Crates.io

该项目提供了一种高效的方法(在时间和空间上)从文本输入中过滤重复条目(行)。该项目是从 neek 发展而来,但优化了速度和内存。根据您的数据和您希望在速度和内存使用之间进行的权衡,支持几种过滤选项。有关更详细的说明,请参阅相关的 博客文章

安装

Runiq 将通过 Crates.io 提供,因此可以直接从那里安装。您可以使用 Runiq 作为命令行工具或直接通过程序化 API 使用它。

如果您希望将 Runiq 作为命令行工具安装,您可以在终端中使用简单的单行命令进行安装

# install as a binary
$ cargo install runiq

如果您希望将其用作库,您可以将其添加到您的 Cargo.toml 中,作为您应用程序的依赖项

[dependencies]
runiq = { version = "2.0", default-features = false }

您应该禁用默认功能,因为它包含一些依赖项,这些依赖项是 CLI 用例所必需的。当禁用这些功能时,这些依赖项不会包含在您的应用程序中。

示例

以下是使用 Runiq CLI 从输入文本中过滤重复内容的几个示例。

$ cat << EOF >> input.txt
this is a unique line
this is a duplicate line
this is another unique line
this is a duplicate line
this is a duplicate line
EOF

$ cat input.txt
this is a unique line
this is a duplicate line
this is another unique line
this is a duplicate line
this is a duplicate line

$ runiq input.txt
this is a unique line
this is a duplicate line
this is another unique line

有关程序化 API 的示例,请参阅 示例

过滤器

Runiq 包含几个“过滤器”,这些过滤器控制了唯一性的验证方式。每个过滤器都有不同的用例,并且以不同的方式表现出色。

  • 快速
    • 快速 过滤器的工作方式与 naive 过滤器相同,只是预先对值进行了哈希处理。
    • 这比 naive 的内存开销要低得多,并且吞吐量相当。
    • 根据您的输入长度,吞吐量实际上可能比 naive 更快。
  • 简单
    • 《naive》过滤器使用基本的《Set》实现来判定唯一性。
    • 在保证准确性的同时,提供了相当好的吞吐量。
    • 由于所有输入都被存储,内存需求与输入大小呈线性关系。
  • 排序
    • 《sorted》过滤器与标准的《uniq》工具作用类似,只检测连续重复项。
    • 资源消耗极低,内存开销非常小。
    • 显然需要输入值是有序的。
  • 紧凑
    • 《compact》过滤器(嘿)使用缩放Bloom过滤器来判定唯一性。
    • 由于结构小巧,性能非常快,内存开销最小。
    • 不再保证完美准确;可能会有极少数的误报。
    • 最适合用于文件统计,尽管对于数百万条记录来说,仍然接近完美。
    • 下面比较中提供了关于此过滤器准确性的注意事项。

比较

为了获取《runiq》与其他过滤唯一值方法的一些粗略比较,我们可以使用一些样本数据。这些数据是通过Jen使用相应目录中提供的模板生成的。您可以根据自己的用例创建模板以获得更好的比较。

首先,我们将使用basic模板生成一个包含2500万个JSON文档的样本数据集。在这个规模下,模板将导致大约20%的重复率(在文件中随机分布)。请注意,对于较长的输入,您可以调整模板内部的《rp》值来引起字段的重复。

$ jen templates/basic.tera -l 25000000 > 25000000.jsonl

File Size:     1,913,658,811 (~1.9 GB)
Total Count:      25,000,000
Unique Count:     19,832,571
Dup Offset:        5,167,429
Dup Rate:             20.67%

然后,我们可以将这些样本数据集通过《runiq》的各种过滤器以及一些其他工具来运行,以评估我们的表现。这些数字不是用来竞争的。它们只是我在测试改进时的一个参考点。其他工具可能更适合您的数据形状。

工具 标志 时间(未排序) 内存(未排序) 时间(排序) 内存(排序)
uniq N/A N/A N/A 24.9s 1.6MB
sort -u 380.2s 8.33GB 58.7s 8.15GB
uq N/A 22.6s 2.34GB 21.0s 2.34GB
huniq N/A 11.9s 298.5MB 11.6s 300.7MB
runiq -f quick 12.1s 298.7MB 11.8s 298.5MB
runiq -f simple 19.7s 2.33GB 18.2s 2.33GB
runiq -f sorted N/A N/A 10.3s 1.3MB
runiq -f compact 17.8s 162.2MB 16.2s 162.3MB

为了进行另一次比较,我们将使用1000万个JSON文档的样本重复这些测试(是第一次测试的4倍)。在这种情况下,重复率将上升到大约55%,使用相同的模板

$ jen templates/basic.tera -l 100000000 > 100000000.jsonl

File Size:     7,654,658,706 (~7.7 GB)
Total Count:     100,000,000
Unique Count:     44,305,712
Dup Offset:       55,694,288
Dup Rate:             55.69%
工具 标志 时间(未排序) 内存(未排序) 时间(排序) 内存(排序)
uniq N/A N/A N/A 105.8s 1.6MB
sort -u 2529.9s 12.70GB 373.0s 12.42GB
uq N/A 76.4s 5.03GB 57.9s 5.03GB
huniq N/A 31.2s 586.3MB 28.4s 587.4MB
runiq -f quick 34.7s 586.8MB 30.5s 586.6MB
runiq -f simple 67.4s 5.00GB 49.0s 5.00GB
runiq -f sorted N/A N/A 24.9s 1.3MB
runiq -f compact 66.3s 338.3MB 49.0s 338.3M

所有这些数字都是在工具输出写入/dev/null的情况下得到的。其中一些工具(包括《runiq》)有标志来计数/报告而不是打印输出;这些用例将始终比上面的数字快得多。

还值得注意的是,在上述情况下,compact 过滤器给出的精度;在我的两个测试集中,结果与其他过滤器类型的结果相同,表明 compact 过滤器通常对相当大量的输入相当准确(尽管并非总是如此)。

依赖项

~0.6–9.5MB
~81K SLoC