【问题标题】:Compressing strings with common parts用公共部分压缩字符串
【发布时间】:2011-10-13 07:53:23
【问题描述】:

我有一个管理大量字符串的应用程序。字符串是类似路径的格式,有很多共同的部分,但没有明确的规则。它们不是文件系统上的路径,但可以这样考虑。 我显然需要优化内存消耗,但又不能牺牲很大的性能。

我正在考虑 2 个选项:
- 实现一个compressed_string 类来存储压缩数据,但我需要一个固定的字典,我现在找不到这个库。我不想要字节上的霍夫曼,我想要文字上的霍夫曼。
- 在字符串部分实现某种flyweight 模式。

这个问题看起来很常见,我想知道最好的解决方案是什么,或者是否有人知道针对此问题的库。

谢谢

【问题讨论】:

  • 一种选择是让你的“路径”成为boost::flyweight<std::string>的向量。
  • 当我想到路径时,我通常会想到树。阻止我将其视为答案的原因是您说它们仅采用类似路径的格式,但是如何将整个数据结构实现为路径树或图形(如果它更复杂),并且仅存储实际数据的入口点和选择的路径?这样每个单词在图中只会出现一次,就是这样。当然,如果您的事件具有高度复杂的互连,则该图可能会变得难以管理,因此您应该看看这是否适合您的情况
  • 如果你有大量的单词样本,你可以构建一个 LZ77 字典,并用它进行编码。

标签: c++ algorithm compression huffman-code


【解决方案1】:

尽管针对您的问题调整特定算法可能很诱人,但这可能需要不合理的时间和精力,而标准压缩技术将立即为您解决内存消耗问题提供极大的帮助。

处理此问题的“标准”方法是将源数据分块为小块(例如 256KB),然后单独压缩它们。将数据访问到块中时,需要先对其进行解码。因此,最佳块大小实际上取决于您的应用程序,即应用程序流越多,块越大;另一方面,随机访问模式越多,块大小越小。

如果您担心压缩/解压缩速度,请使用高速算法。如果解压缩速度是最重要的指标(访问时间),像 LZ4 这样的东西将为您提供大约 1GB/s 的解码性能每个内核,因此这让您了解每秒可以处理多少块解码。

如果只看解压速度,可以使用高压缩变体LZ4-HC,压缩比提升30%左右,解压速度也有所提升。

【讨论】:

    【解决方案2】:

    字符串是类似路径的格式,有很多共同的部分,但没有明确的规则。

    从某种意义上说,它们是 name, (separator, name)* 形式的层次结构中的定位器?如果是这样,您可以使用interning:将name 部分存储为指向字符串池的char const * 元素。这样,您可以有效地将使用 n 次的名称压缩到刚好超过 n * sizeof(char const *) + strlen(name) 字节。完整路径将成为一系列实习名称,例如一个std::vector

    sizeof(char const *) 在 64 位硬件上似乎很大,但您也节省了一些分配开销。或者,如果您出于某种原因知道您永远不需要超过 65536 个字符串,您可以将它们存储为

    class interned_name
    {
        uint16_t tab_idx;
    
      public:
        char const *c_str() const
        {
            return NAME_TABLE[tab_idx];
        }
    };
    

    其中NAME_TABLEstatic std::unordered_map<uint16_t, char const *>

    【讨论】:

    • 这在概念上与享元设计模式非常接近。 +1 的想法,但它已经在 boost::flyweight 中实现了
    猜你喜欢
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    相关资源
    最近更新 更多