【问题标题】:Using vector as output buffer?使用向量作为输出缓冲区?
【发布时间】:2021-04-29 12:20:47
【问题描述】:

我有相当 大量 以 Base64 编码的数据 (>1MB)。

我找到了一个不错的library,它可以帮助我尽快处理这个问题。

这里是解码语法,很基础,需要一个输出缓冲区:

int base64_decode
    ( const char  *src
    , size_t       srclen
    , char        *out
    , size_t      *outlen
    , int          flags
    ) ;

虽然我可以从他们的样本中获得输出缓冲区:

char out[1*1024*1024];

但是输入大小不是恒定的,在编译时询问这么大的大小看起来和感觉不好。另一方面,在堆栈上拥有一个不错的大缓冲区应该比在堆上存储和访问的数据具有一些速度优势 (source)。

但我想改用vector<char>。我可以将其定义为

std::vector<char> out;

然后当我有输入大小时,我可以resize它:

out.resize(input_size);

调整大小会将其所有项目初始化为 0,这对我来说似乎不切实际且不必要,因为 base64_decode 还会在下一步中初始化这些项目。

因此,resize 可能不是最好的,但调用 reserve 也无济于事,因为它不会修改向量的大小(尽管它也不会初始化项目)。

由于我没有关于数据大小的先验信息,我要么需要使用一些运行时可调整大小的缓冲区,要么进行大猜测并分配一个巨大的缓冲区。

由于库能够非常快地解码,我也想对输出缓冲区使用最快的解决方案,char arrayvector 似乎都不合适。那么我最快的选择是什么?

【问题讨论】:

  • resize 可能是您最快的解决方案。 CPU 很容易将char 归零。我的建议,使用vector 然后配置文件。如果性能好,那么你就完成了。如果不是,那么您至少有数据可以用来帮助选择更好的解决方案。
  • base64_decode 不返回它能够解码的字节数吗?然后你不断地调用它,直到它返回 0,这意味着所有的数据都被解码了。使用过大的缓冲区 (>1MB) 对 CPU 缓存不利。但是也很容易预测 Base64 解码后的大小(基本上是 ~input*3/4+4)。
  • 不,它不会以解码后的大小返回,而是将其放入outlen。关于大小估计是的,一旦我们有了输入数据的长度,我就不难了。
  • 您的堆栈数组只会在您放置它的函数调用期间消耗内存。分配/取消分配和初始化的开销为零。 std::vector 分配/解除分配的速度会相当慢。
  • 所以我应该在base64_decode前面做char buffer[input_size]

标签: c++ vector buffer


【解决方案1】:

堆栈分配确实比堆分配快得多,但是 (1) 您可能没有 1MB 的堆栈,更重要的是 (2) 解码 1MB 的 Base-64 文本比分配本身需要更多的时间,即使是快速图书馆。

请注意,Base-64 解码恰好是 4:3 的比例,如果四舍五入的话。因此,如果您知道srclen,那么(srclen+3)/4*3 就是必需的outlen。它是一个外参数的主要原因是为了舍入 - 实际长度可能短一个字节。

【讨论】:

  • 所以得出结论,你是说我很适合使用矢量?
  • 是的。主要的例外是如果您想将数据作为std::string 返回,在这种情况下,您需要直接解码为该类型的对象。但这仍然是与向量相同的堆(又名std::allocator)。
猜你喜欢
  • 2012-04-04
  • 2020-05-09
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多