我正在使用 7z 提供的最佳压缩率压缩一组 120 MB 的文件,并注意到它在峰值时消耗了近 600MB 的 RAM。
为什么这些压缩程序即使在处理非常小的数据集时也会占用如此多的内存,甚至消耗的内存是其数据集未压缩大小的数倍?
只是好奇,我对它的技术方面更感兴趣。
答案1
从未从技术上涉足过压缩,但让我们开始搜索......
7z 帮助文件提到:
左心室舒张功能是一种基于 Lempel-Ziv 算法的算法。它提供非常快的解压缩速度(比压缩快 10-20 倍)。压缩和解压缩的内存要求也不同(有关详细信息,请参阅 d={Size}[b|k|m] 开关)。
(请注意 LZ 算法文章维基百科做不是提及有关内存需求的任何信息。
d={大小}[b|k|m] 集合LZMA 的字典大小。您必须以字节、千字节或兆字节为单位指定大小。字典大小的最大值为 1 GB = 2^30 字节。LZMA 的默认值在正常模式下为 24 (16 MB),在最大模式 (-mx=7) 下为 25 (32 MB),在超级模式 (-mx=9) 下为 26 (64 MB)。如果您未从集合 [b|k|m] 中指定任何符号,则字典大小将计算为 DictionarySize = 2^Size 字节。要解压缩使用 LZMA 方法压缩且字典大小为 N 的文件,您需要大约 N 字节的可用内存 (RAM)。
继续关注维基百科关于字典编码器该算法的工作原理似乎是将要压缩的数据与“字典”中的一组数据进行比较,而该字典必须基于要压缩的原始数据。
不管这个字典是如何构建的,由于它必须保存在内存中,因此 RAM 需求取决于这个字典。而且由于这个字典不是原始数据,而是某种未压缩的数据结构,因此它将(可能)比处理的原始数据更大。说得通?
答案2
如果另一个答案包含大量技术术语,让人难以阅读,我会提供我的答案。
文件存储在硬盘或固态驱动器中。您可能会问什么是文件?我的回答是,一堆按特定顺序排列的 1 和 0,从外部看起来像一个文件。什么是可执行程序*.exe
?它是机器代码可执行文件,也是一堆 1 和 0。它也存储在您的磁盘驱动器中。当您单击文件压缩可执行文件时,代码指令算法会从*.exe
磁盘驱动器加载到 RAM 中。只有这样它才能运行。计算机的 CPU 运行程序并读取/写入数据。它不能直接从磁盘驱动器获取任何东西。它必须先将所有内容加载到 RAM 内存中,RAM 内存充当 CPU 和存储所有数据的磁盘驱动器之间的中间人。
现在文件压缩程序正在由 CPU 在 RAM 中运行。代码指令告诉 CPU 做什么?它们告诉 CPU 将实际文件本身从磁盘驱动器加载到 RAM 内存中,以便程序可以使用它。所以现在 RAM 内存中有两样东西:程序本身和文件。
您告诉此文件压缩程序压缩文件。但是它无法神奇地做到这一点。要进行压缩,文件必须按特定顺序排列,尽可能紧密。也许在压缩之前,文件有点杂乱无章,就像您的文件柜一样。文件压缩程序必须尽可能整齐、紧密地组织文件。为此,它必须暂时将文件置于更杂乱的状态,以便找到所有部分所属的位置。
想想如何压缩文件。首先,你可以将它们散布在桌子上,这样你就能看到它们,然后按类别排序,并开始将文件放入文件夹中。
因此,现在 RAM 内存中有三样东西:1. 程序指令本身。2. 从磁盘驱动器加载的原始文件。3. 原始文件的临时副本,处于被拆开并重新组合的状态。也许在 RAM 中制作了整个文件甚至部分文件的多个临时副本,以便程序更容易组织和压缩此文件。现在您是否明白文件压缩程序在运行时会占用比磁盘驱动器中原始文件大小多得多的 RAM?
在此过程中消耗的 RAM 量取决于设计应用程序的程序员的技能。有聪明而有效的方法来编写代码,以最大限度地减少 RAM 的消耗。然后有蛮力的方法来实现相同的任务,但运行速度较慢,占用更多 RAM。如果程序有内存泄漏,RAM 甚至可能被浪费。内存泄漏可以想象为对相同数据进行多份复制,然后将其留在桌面上,甚至从不费心清理。
但最终所有临时副本都会被压缩为文件的压缩版本。不过它仍然在 RAM 内存中,因此该文件的压缩版本必须一路发送回硬盘,并永久保存。
主要思想是,为了达到低熵状态,你应该暂时经历高熵状态。这当然是用最笼统的术语来表达的。