使用Boost iostreams处理大数据时出现问题



我需要处理内存中的大量数据(不使用文件/fstream(,我知道streambuf的VS实现不允许这样做,因为它使用32位计数器(https://github.com/microsoft/STL/issues/388)。我以为Boost可能会帮助我,但显然它处理得不好(或者我错过了什么(。

#include <vector>
#include <iostream>
#include <boost/iostreams/stream.hpp>
namespace bs = boost::iostreams;
int main()
{
uint64_t mb1 = 1024 * 1024;
uint64_t gb1 = 1024 * mb1;
uint64_t mbToCopy = 2048;
std::vector<char> iBuffer(mb1);
std::vector<char> oBuffer(4 * gb1);
bs::stream<bs::array_sink> oStr(oBuffer.data(), oBuffer.size());
for (int i = 0; i < mbToCopy; i++) {
oStr.write(iBuffer.data(), iBuffer.size());
}
std::cout << oStr.tellp() << std::endl; // (1)
oStr.seekp(0, std::ios_base::beg);
std::cout << oStr.tellp() << std::endl; // (2)
}

只要mbToCopy不大于2048并且输出为:,此代码就可以正常工作

2147483648
0

当我将mbToCopy更改为2049时,输出为:

2148532224
4294967296

正如您所看到的,当我试图移回流的开头时(这是示例用法,但我需要能够重新定位到流中的任何位置(,它会使我远远超出流的当前大小,流变得不可靠。更重要的是,当我将mbToCopy设置为2049并将oBuffer的大小减小到3GBoStr.seekp开始崩溃时。

你知道Boost是否提供了其他可以帮助我的解决方案吗?

我建议这里根本不要使用流。他们似乎引入了不必要的开销:

#include <cassert>
#include <iostream>
#include <vector>
static inline auto operator""_kb(unsigned long long v) { return v << 10ull; }
static inline auto operator""_mb(unsigned long long v) { return v << 20ull; }
static inline auto operator""_gb(unsigned long long v) { return v << 30ull; }
int main()
{
std::vector<char> iBuffer(1_mb);
std::vector<char> oBuffer(12_gb);
auto pos = oBuffer.begin();
for (size_t i = 0; i < 8192; i++) {
assert(std::next(pos, iBuffer.size()) <= oBuffer.end());
pos = std::copy_n(iBuffer.begin(), iBuffer.size(), pos);
}
auto tellp = [&] { return std::distance(oBuffer.begin(), pos); };
auto seekp = [&](size_t from_beg) { pos = std::next(oBuffer.begin(), from_beg); };
std::cout << tellp() << std::endl; // (1)
seekp(0);
std::cout << tellp() << std::endl; // (2)
}

在我的系统上打印,没有任何问题:

8589934592
0

当然,我引入tellp()/seekp()助手只是为了使代码尽可能相似。你也可以写:

auto const beg = oBuffer.begin();
auto       pos = beg;
for (size_t i = 0; i < 8192; i++) {
assert(std::next(pos, iBuffer.size()) <= oBuffer.end());
pos = std::copy_n(iBuffer.begin(), iBuffer.size(), pos);
}
std::cout << (pos-beg) << std::endl; // (1)
pos = beg;
std::cout << (pos-beg) << std::endl; // (2)

输出完全相同。

最新更新