gpt4 book ai didi

c++ - 将文件读入结构时大小增加 10 倍

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:07:25 27 4
gpt4 key购买 nike

我正在尝试将一个 csv 文件读入一个包含字符串 vector 的结构。该文件包含约 200 万行,磁盘大小约为 350 MB。当我将文件读入 struct top 时,显示在读取完整文件时,程序现在使用了将近 3.5GB 的内存。我已经使用 vector 保留来尝试限制 push_back 上 vector 容量的增加。

#include<iomanip>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<string.h>
#include<sstream>
#include<math.h>
#include<vector>
#include<algorithm>
#include<array>
#include<ctime>
#include<boost/algorithm/string.hpp>
using namespace std;

struct datStr{
vector<string> colNames;
vector<vector<string>> data;
};

datStr readBoost(string fileName)
{
datStr ds;
ifstream inFile;
inFile.open(fileName);
string line;
getline(inFile, line);
vector<string> colNames;
stringstream ss(line);
string item;
int i = 0;
vector<int> colTypeInt;
while(getline(ss, item, ','))
{
item.erase( remove( item.begin(), item.end(), ' ' ), item.end() );
colNames.push_back(item);
vector<string> colVec;
ds.data.push_back(colVec);
ds.data[i].reserve(3000000);
i++;
}

int itr = 0;
while(getline(inFile, line))
{
vector<string> rowStr;
boost::split(rowStr, line, boost::is_any_of(","));
for(int ktr = 0; ktr < rowStr.size(); ktr++)
{
rowStr[ktr].erase( remove( rowStr[ktr].begin(), rowStr[ktr].end(), ' ' ), rowStr[ktr].end() );
ds.data[ktr].push_back(rowStr[ktr]);
}
itr++;
}
int main()
{
datStr ds = readBoost("file.csv");
while(true)
{
}
}

PS:最后的 while 只是为了让我可以在程序完成时监控内存使用情况。这是使用 vector 时预期的结果还是我在这里遗漏了什么?另一个有趣的事实。我开始计算读取循环中每个字符串的大小和容量。令人惊讶的是,它加起来只是我在 ubuntu 顶部显示的内容的 1/10?可能是 top 误报还是我的编译器分配了太多空间?

最佳答案

我用一个包含 1886850 行文本、大小为 105M 的输入文件测试了您的代码。

使用您的代码,内存消耗约为 2.5G。

然后,我开始修改数据的存储方式。

第一次测试:

datStr 更改为:

struct datStr{
vector<string> colNames;
vector<string> lines;
};

这将内存消耗减少到 206M。体积缩小了 10 倍以上。很明显,使用的惩罚

vector<vector<string>> data;

比较僵硬。

第二次测试:

datStr 更改为:

struct datStr{
vector<string> colNames;
vector<string> lines;
vector<vector<string::size_type>> indices;
};

使用 indices 跟踪 lines 中标记的开始位置。您可以使用 linesindices 从每一行中提取标记。

通过此更改,内存消耗变为 543MB,但仍比原来小五倍。

第三次测试

dataStr 更改为:

struct datStr{
vector<string> colNames;
vector<string> lines;
vector<vector<unsigned int>> indices;
};

通过此更改,内存消耗降至 455MB。如果您不希望行长或等于 UINT_MAX,这应该有效。

第四次测试

dataStr 更改为:

struct datStr{
vector<string> colNames;
vector<string> lines;
vector<vector<unsigned short>> indices;
};

通过此更改,内存消耗降至 278MB。如果您不希望您的行长于或等于 USHRT_MAX,这应该有效。对于这种情况,indices 的开销非常小,只有 72MB

这是我用于测试的修改后的代码。

#include<iomanip>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<string.h>
#include<sstream>
#include<math.h>
#include<vector>
#include<algorithm>
#include<array>
#include<ctime>
// #include<boost/algorithm/string.hpp>
using namespace std;

struct datStr{
vector<string> colNames;
vector<string> lines;
vector<vector<unsigned short>> data;
};

void split(vector<unsigned short>& rowStr, string const& line)
{
string::size_type begin = 0;
string::size_type end = line.size();
string::size_type iter = begin;
while ( iter != end)
{
++iter;
if ( line[iter] == ',' )
{
rowStr.push_back(static_cast<unsigned short>(begin));
++iter;
begin = iter;
}
}
if (begin != end )
{
rowStr.push_back(static_cast<unsigned short>(begin));
}
}

datStr readBoost(string fileName)
{
datStr ds;
ifstream inFile;
inFile.open(fileName);
string line;
getline(inFile, line);
vector<string> colNames;
stringstream ss(line);
string item;
int i = 0;
vector<int> colTypeInt;
while(getline(ss, item, ','))
{
item.erase( remove( item.begin(), item.end(), ' ' ), item.end() );
ds.colNames.push_back(item);
}

int itr = 0;
while(getline(inFile, line))
{
ds.lines.push_back(line);
vector<unsigned short> rowStr;
split(rowStr, line);
ds.data.push_back(rowStr);
}
}

int main(int argc, char** argv)
{
datStr ds = readBoost(argv[1]);
while(true)
{
}
}

关于c++ - 将文件读入结构时大小增加 10 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23934919/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com