慢速文件读取和复制到内存C++
我正在读取一个文件并将数据保存到一个向量中。我无法使用数组,因为数据大小不固定。文件大小约为300kb,最高可达600kb。目前,读取/保存大约需要5-8秒 我想知道是什么使我的读取/复制方法变慢,以及如何改进 样本数据: 0000:4000 94 45 30 39 36 39 74 00 00 50 00 00 27一些 其他信息在这里慢速文件读取和复制到内存C++,c++,arrays,file,vector,C++,Arrays,File,Vector,我正在读取一个文件并将数据保存到一个向量中。我无法使用数组,因为数据大小不固定。文件大小约为300kb,最高可达600kb。目前,读取/保存大约需要5-8秒 我想知道是什么使我的读取/复制方法变慢,以及如何改进 样本数据: 0000:4000 94 45 30 39 36 39 74 00 00 50 00 00 27一些 其他信息在这里 这似乎是意料之中的事。使用Boost::Progress或ctime隔离昂贵的指令 向量是以数组的方式使用连续内存实现的,因此如果有任何减速,您应该不会看到太
这似乎是意料之中的事。使用Boost::Progress或ctime隔离昂贵的指令 向量是以数组的方式使用连续内存实现的,因此如果有任何减速,您应该不会看到太多。在600kb的文件上,文件IO时间可能是最小的——我可以想象它是在打开时缓存到内存中的。您可以使用file.open的ios::binary mode标志将整个文件缓存到内存中,但您必须反序列化每一行,以减少getline抽象的开销
综上所述,编译器非常擅长优化IO和向量。瓶颈可能是正则表达式的构造,甚至可能是正则表达式匹配的构造,这些都是必要且复杂的。每个正则表达式都会生成一个确定性有限状态自动机:。这似乎是意料之中的。使用Boost::Progress或ctime隔离昂贵的指令 向量是以数组的方式使用连续内存实现的,因此如果有任何减速,您应该不会看到太多。在600kb的文件上,文件IO时间可能是最小的——我可以想象它是在打开时缓存到内存中的。您可以使用file.open的ios::binary mode标志将整个文件缓存到内存中,但您必须反序列化每一行,以减少getline抽象的开销
综上所述,编译器非常擅长优化IO和向量。瓶颈可能是正则表达式的构造,甚至可能是正则表达式匹配的构造,这些都是必要且复杂的。每个正则表达式都会生成一个确定性有限状态自动机:。正则表达式非常强大,但复杂且缓慢 由于您的格式是完全静态的固定位数和固定分隔符,您可以自己实现转换,逐字符读取。这不会很复杂 例如,要读取所有十六进制数并检查空格和分号:
while(getline(file,str))
{
if(str.size()>=57)
{
int sector = hexToInt(str.data(), 4);
int address = hexToInt(str.data()+5, 4);
bool ok = ok && (sector==0) && (address>=0);
ok = ok && str[4] == ':';
int bytes[16];
for(int i=0;i<16;++i)
{
bytes[i] = hexToInt(str.data()+10+3*i, 2);
ok = ok && (str[9+3*i]==' ') && (bytes[i]>=0);
}
}
//Etc...
}
用于检查和转换十六进制数字的功能:
int hexCharToDigit(char c)
{
if(c>='0' && c<='9')
{
//Decimal digit
return (int)(c-'0');
}
else if (str[i]>='a' && str[i]<='f')
{
//Hexadecimal lower case letter
return (int)(c-'a')+10;
}
else if (str[i]>='A' && str[i]<='F')
{
//Hexadecimal upper case letter
return (int)(c-'A')+10;
}
else
{
//Char is not a hex digit
return -1;
}
}
用于检查n位十六进制并将其转换为整数的函数:
int hexToInt(const char * chr, int size)
{
assert(size<8);
int result= 0;
for(int i=0;i<size;++i)
{
int hexDigit = hexCharToDigit(chr[i]);
if(hexDigit>=0)
{
//Valid hexadecimal digit
result = result << 4;
result += hexDigit;
}
else
{
//Char is not a hex digit as expected
return -1;
}
}
return result;
}
正则表达式非常强大,但复杂且缓慢 由于您的格式是完全静态的固定位数和固定分隔符,您可以自己实现转换,逐字符读取。这不会很复杂 例如,要读取所有十六进制数并检查空格和分号:
while(getline(file,str))
{
if(str.size()>=57)
{
int sector = hexToInt(str.data(), 4);
int address = hexToInt(str.data()+5, 4);
bool ok = ok && (sector==0) && (address>=0);
ok = ok && str[4] == ':';
int bytes[16];
for(int i=0;i<16;++i)
{
bytes[i] = hexToInt(str.data()+10+3*i, 2);
ok = ok && (str[9+3*i]==' ') && (bytes[i]>=0);
}
}
//Etc...
}
用于检查和转换十六进制数字的功能:
int hexCharToDigit(char c)
{
if(c>='0' && c<='9')
{
//Decimal digit
return (int)(c-'0');
}
else if (str[i]>='a' && str[i]<='f')
{
//Hexadecimal lower case letter
return (int)(c-'a')+10;
}
else if (str[i]>='A' && str[i]<='F')
{
//Hexadecimal upper case letter
return (int)(c-'A')+10;
}
else
{
//Char is not a hex digit
return -1;
}
}
用于检查n位十六进制并将其转换为整数的函数:
int hexToInt(const char * chr, int size)
{
assert(size<8);
int result= 0;
for(int i=0;i<size;++i)
{
int hexDigit = hexCharToDigit(chr[i]);
if(hexDigit>=0)
{
//Valid hexadecimal digit
result = result << 4;
result += hexDigit;
}
else
{
//Char is not a hex digit as expected
return -1;
}
}
return result;
}
最有可能是正则表达式破坏了您的性能:最好在计算if运算符时在第一位设置更简单的语句,以防&&我不知道firstAddress==-1的频率,但如果不是,它将不会运行正则表达式搜索…数据格式很简单。不要使用正则表达式。另外,您应该估计数据的大小并避免重新分配:使用vector::reserve。尝试使用一些中值大小声明向量。您可能会看到由于重新分配std::vector而造成的时间浪费。我建议450kb。@ZDF,向量重新分配不是这里的瓶颈。vector在最后提供了摊销常数时间的插入。最有可能的是正则表达式破坏了您的性能:最好在第一位设置更简单的语句来计算if运算符,以防&&我不知道firstAddress==-1的频率,但如果不是,它就不会运行正则表达式搜索…数据格式很简单。不要使用正则表达式。另外,您应该估计数据的大小并避免重新分配:使用vector::reserve。尝试使用一些中值大小声明向量。您可能会看到由于重新分配std::vector而造成的时间浪费。我建议450kb。@ZDF,向量重新分配不是这里的瓶颈。vector提供了在最后以摊销的固定时间进行插入的功能。速度慢也可能是由于std::vector重新分配内存造成的。@ThomasMatthews,可能性极低。在完成一些基准测试后,正则表达式搜索是原因。因为我知道每行中的数据位置,所以我将手动提取它。谢谢你的帮助。速度慢也可能是由于std::vector重新分配内存造成的。@ThomasMatthews,可能性极小。在做了一些基准测试之后,正则表达式搜索是原因。因为我知道每行中的数据位置,所以我将手动提取它。谢谢你的帮助。在做了一些基准测试之后,正则表达式搜索就是原因。因为我知道每行中的数据位置,所以我将手动提取它。谢谢你抽出时间。如果需要的话,我可以使用你的一些函数。在做了一些基准测试之后,正则表达式搜索就是原因。因为我知道数据 在每一行中,我将手动提取它。谢谢你抽出时间。如果需要,我可以使用你的一些功能。