我有一个巨大的文本文件加载到CMemFile
对象中,并希望逐行解析(由换行符分隔)。
最初它是磁盘上的zip文件,我将其解压缩到内存中来解析它,因此是CMemFile。
逐行读取的一种工作方式是(m_file是指向CMemFile
的智能指针):
CArchive archive(m_file.get(), CArchive::load);
CString line;
while(archive.ReadString(line))
{
ProcessLine(string(line));
}
由于花了很多时间,我试着编写自己的例程:
const UINT READSIZE = 1024;
const char NEWLINE = '\n';
char readBuffer[READSIZE];
UINT bytesRead = 0;
char *posNewline = NULL;
const char* itEnd = readBuffer + READSIZE;
ULONGLONG currentPosition = 0;
ULONGLONG newlinePositionInBuffer = 0;
do
{
currentPosition = m_file->GetPosition();
bytesRead = m_file->Read(&readBuffer, READSIZE);
if(bytesRead == 0) break; // EOF
posNewline = std::find(readBuffer, readBuffer + bytesRead, NEWLINE);
if(posNewline != itEnd)
{
// found newline
ProcessLine(string(readBuffer, posNewline));
newlinePositionInBuffer = posNewline - readBuffer + 1; // +1 to skip \r
m_file->Seek(currentPosition + newlinePositionInBuffer, CFile::begin);
}
} while(true);
测量性能表明两种方法大约需要同时...
你能想到任何性能改进或更快的解析方法吗?
感谢您的任何建议
答案 0 :(得分:2)
可能有用的一些注释和评论:
ProcessFile()
函数是一个nop。如果你的解析只花费总时间的1%,那么你就不会从尝试优化1%中获得太多。这是您的代码会告诉您的分析。答案 1 :(得分:1)
使用分析器显示,在这行代码中浪费了75%的处理时间:
ProcessLine(string(readBuffer, posNewline));
主要是临时字符串的创建造成了很大的开销(很多分配)。 ProcessLine函数本身不包含代码。通过更改声明:
void ProcessLine(const std::string &);
为:
inline void ProcessLine(const char*, const char*);
使用的处理时间减少了五倍。
答案 2 :(得分:0)
您可以在单独的线程中运行解压缩和解析。每次解压缩产生一些数据时,您应该使用消息机制将其传递给解析线程进行解析。
这允许两者并行运行,并且还因为您使用块而不是整个解压缩文件(这将导致更少的页面错误和交换到虚拟内存)而导致更小的内存开销。
答案 3 :(得分:0)
我认为你的问题可能是因为你读得太多并且正在寻找新的一线。
如果您提交的是
foo
bar
etc
说一行平均10个字节。您将阅读10行...并再次阅读9行。