AlexMelanFromRingo/dedup-giant-files

GitHub: AlexMelanFromRingo/dedup-giant-files

基于磁盘哈希分区与流式合并的海量文本文件去重工具,峰值内存恒定且不受输入规模影响。

Stars: 0 | Forks: 0

# Giant Dedup **快速、内存受限的海量文本文件和词表去重。** `dedup_giant_files` 可以移除*任何*大小的文本文件中的重复行——包括远大于 RAM 的文件——它通过使用磁盘哈希分区、内存映射桶以及流式 k 路合并来实现。无论输入包含多少唯一行,峰值内存都保持平稳,因此它既不会在庞大的唯一集合上发生 OOM,也不会在病态的重度重复输入上发生 OOM。 ## 为什么需要另一个去重工具? 简单的 `sort -u` 需要对整个文件进行排序;哈希集合工具会将每个唯一的行保留在 RAM 中。这两者在处理数百 GB 的词表时都会崩溃。Giant Dedup 的设计使得**峰值内存仅受限于单个分区的工作集**,而不是输入大小或唯一行的数量: - **不会因为高唯一性而 OOM** —— 唯一行被流式传输到输出,永远不会收集到一个巨大的内存向量中。 - **不会因为重度/倾斜的重复而 OOM** —— 分区使用内存映射(基于文件、可回收)而不是读取到堆上,并且去重哈希表是容量受限的,因此重复繁重的桶无法预留巨大的空表。 - **跨核心扩展** —— 分区和每个桶的去重完全并行(Rayon),无共享。 ## 功能 - 在单次处理中**合并多个文件并去重**。 - **`--keep-order`** —— 保留首次出现的顺序(输入文件顺序,然后是行位置)。通过流式 k 路合并实现,因此保持内存受限。 - **`--sort-length`** —— 输出按从短到长排序的唯一行(适用于破解字典),同样通过受限的合并实现。 - **`--buckets N`** —— 调整分区数量(内存/并行度权衡)。 - **跨平台** —— 纯 Rust 编写;使用 `memmap2` 实现可移植的内存映射。 ## 安装 需要最新的 [Rust 工具链](https://rustup.rs/)。 ``` git clone https://github.com/AlexMelanFromRingo/dedup-giant-files cd dedup-giant-files cargo build --release # 位于 ./target/release/dedup_giant_files 的 binary ``` ## 用法 ``` # 基础 deduplication ./target/release/dedup_giant_files wordlist.txt -o cleaned.txt # 合并 + dedup 多个字典 ./target/release/dedup_giant_files dict1.txt dict2.txt dict3.txt -o mega.txt # 保留首次出现顺序(文件顺序,然后是位置) ./target/release/dedup_giant_files priority.txt common.txt -o merged.txt --keep-order # 按长度对 unique 行进行排序(短 → 长) ./target/release/dedup_giant_files massive.txt -o sorted.txt --sort-length # 调整 partition 数量(更多 buckets = 每个 bucket 更小的 working set) ./target/release/dedup_giant_files huge.txt -o out.txt --buckets 1024 ``` | 标志 | 默认值 | 描述 | | :-- | :-- | :-- | | `-o, --output ` | `dedup_out.txt` | 输出路径。 | | `--keep-order` | 关闭 | 保持首次出现的顺序。 | | `--sort-length` | 关闭 | 将唯一行按从短到长排序(平局:按字节顺序)。 | | `--buckets ` | `256` | 磁盘哈希分区的数量。 | ## 工作原理 1. **分区** —— 输入以 64 MB 为块进行流式传输;每一行都被哈希(XXH3)并路由到 *N* 个磁盘桶之一。顺序元数据(`file_idx`, `offset`)**仅**在设置了 `--keep-order` 时写入,否则会将短行的临时磁盘使用量减半。 2. **按桶去重** —— 每个桶都进行内存映射,并使用容量受限的哈希集合(`AHashSet<&[u8]>`)进行去重。桶以并行方式处理。 3. **输出** —— - *默认:* 每个桶将其唯一行直接流式传输到输出; - *有序:* 每个桶写入一个排序后的结果文件,然后**流式 k 路合并**使用每个桶一个缓冲行来生成全局排序的输出。 完整的说明,包括对两种 OOM 失败模式的根本原因分析及修复方法,请参见 [`docs/METHODOLOGY.md`](docs/METHODOLOGY.md)。 ## 内存行为(实测) 在流式重写前后,AMD Ryzen 5 5500 (6C/12T)、WSL2 环境下的峰值**匿名堆**(实际导致 OOM-kill 的内存): | 场景 | 模式 | 重写前 | 重写后 | | :-- | :-- | --: | --: | | 4000 万唯一行(约 920 MB) | 默认 | 3163 MB | **427 MB** | | 4000 万唯一行(约 920 MB) | `--keep-order` | 4681 MB | **421 MB** | | 1 个热点行 × 3000 万 + 200 万唯一行 | 默认 | (易发生 OOM) | **182 MB** | 重写后,峰值堆内存大致**恒定** —— 它取决于每个桶的工作集和合并缓冲区,而不是唯一行的数量。重写前的设计随着唯一性的增加呈线性增长(在数十亿唯一行时约为 100 GB+)。 ## 生成测试数据 一个辅助二进制程序可以生成用于实验的大型低熵文件: ``` cargo run --release --bin generate_data # writes large_test_file.txt ``` ## 许可证 根据您的选择,采用 [MIT](LICENSE-MIT) 或 [Apache-2.0](LICENSE-APACHE) 双重许可。
标签:Rust, SOC Prime, 内存映射, 可视化界面, 开发工具, 文本去重, 网络流量审计, 通知系统