为什么 CFile + CArchive 的性能优于 C I/O 流?
Why CFile + CArchive performs better than C I/O stream?
我正在比较 MFC 类:
之间的性能
CFile
+ CArchive
(使用缓冲区)
和
CStdioFile
(使用缓冲的 I/O 流)
两者都使用缓冲区。
以下是我的代码:
void TestFun1(CFile& File, BOOL bIsMemFile)
{
CArchive Archive(&File, CArchive::store);
CString strLine, strOutput;
UINT uSize;
BYTE* lpBuf;
ULONGLONG uStart, uStop;
uStart = ::GetTickCount64();
for (UINT nIndex = 0; nIndex < 500; nIndex ++)
{
// Reset the file to empty
File.SetLength(0);
strLine.Format(_T("This is line %u."), nIndex);
for (UINT j = 0; j < 5000; j++)
File.Write((LPCTSTR)strLine, strLine.GetLength() * sizeof(TCHAR));
File.Flush();
}
uStop = ::GetTickCount64();
CString strMsg;
strMsg.Format(_T("Total time(TestFun1): %I64u."), uStop - uStart);
AfxMessageBox(strMsg);
}
void TestFun2(CFile& File, BOOL bIsMemFile)
{
CArchive Archive(&File, CArchive::store);
CString strLine, strOutput;
UINT uSize;
BYTE* lpBuf;
ULONGLONG uStart, uStop;
uStart = ::GetTickCount64();
for (UINT nIndex = 0; nIndex < 500; nIndex ++)
{
// Reset the file to empty
File.SetLength(0);
strLine.Format(_T("This is line %u."), nIndex);
for (UINT j = 0; j < 5000; j++)
Archive.WriteString(strLine);
Archive.Flush();
}
uStop = ::GetTickCount64();
CString strMsg;
strMsg.Format(_T("Total time(TestFun2): %I64u."), uStop - uStart);
AfxMessageBox(strMsg);
}
void CTestMemFileDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CFile File;
CMemFile MemFile;
if (File.Open(_T("E:\Temp\testfile.dat"), CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone))
{
TestFun1(File, FALSE);
TestFun2(File, FALSE);
TestFun1(File, FALSE);
TestFun2(File, FALSE);
File.Close();
}
}
void CTestMemFileDlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
CStdioFile File;
CMemFile MemFile;
if (File.Open(_T("E:\Temp\testfile.dat"), CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone))
{
int nVal;
nVal = setvbuf(File.m_pStream, NULL, _IOFBF, 1024768);
TestFun1(File, FALSE);
TestFun2(File, FALSE);
TestFun1(File, FALSE);
TestFun2(File, FALSE);
File.Close();
}
}
结果是:
按钮 1:
TestFun1: 18174
TestFun2: 375
TestFun1: 18330
TestFun2: 375
按钮 2:
TestFun1: 546
TestFun2: 530
TestFun1: 530
TestFun2: 531
根据我的测试,CFile + CArchive 总是占用 CStdioFile 大约 66% 的时间。我尝试将 CStdioFile 的缓冲区增加到 1MB,但仍然得到相同的结果。
因此,我的问题是,既然两种解决方案都使用缓冲,为什么 CStdioFile 总是比 CFile + CArchive 慢?
CStdioFile
默认以文本模式打开文件。这会导致特殊字符的翻译,例如回车 returns 和换行,这显然需要时间。
如果您想避免这种情况,可以将 CFile::typeBinary
添加到 CStdioFile::open()
调用中的 nOpenFlags
参数。
我正在比较 MFC 类:
之间的性能CFile
+CArchive
(使用缓冲区)
和
CStdioFile
(使用缓冲的 I/O 流)
两者都使用缓冲区。
以下是我的代码:
void TestFun1(CFile& File, BOOL bIsMemFile)
{
CArchive Archive(&File, CArchive::store);
CString strLine, strOutput;
UINT uSize;
BYTE* lpBuf;
ULONGLONG uStart, uStop;
uStart = ::GetTickCount64();
for (UINT nIndex = 0; nIndex < 500; nIndex ++)
{
// Reset the file to empty
File.SetLength(0);
strLine.Format(_T("This is line %u."), nIndex);
for (UINT j = 0; j < 5000; j++)
File.Write((LPCTSTR)strLine, strLine.GetLength() * sizeof(TCHAR));
File.Flush();
}
uStop = ::GetTickCount64();
CString strMsg;
strMsg.Format(_T("Total time(TestFun1): %I64u."), uStop - uStart);
AfxMessageBox(strMsg);
}
void TestFun2(CFile& File, BOOL bIsMemFile)
{
CArchive Archive(&File, CArchive::store);
CString strLine, strOutput;
UINT uSize;
BYTE* lpBuf;
ULONGLONG uStart, uStop;
uStart = ::GetTickCount64();
for (UINT nIndex = 0; nIndex < 500; nIndex ++)
{
// Reset the file to empty
File.SetLength(0);
strLine.Format(_T("This is line %u."), nIndex);
for (UINT j = 0; j < 5000; j++)
Archive.WriteString(strLine);
Archive.Flush();
}
uStop = ::GetTickCount64();
CString strMsg;
strMsg.Format(_T("Total time(TestFun2): %I64u."), uStop - uStart);
AfxMessageBox(strMsg);
}
void CTestMemFileDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CFile File;
CMemFile MemFile;
if (File.Open(_T("E:\Temp\testfile.dat"), CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone))
{
TestFun1(File, FALSE);
TestFun2(File, FALSE);
TestFun1(File, FALSE);
TestFun2(File, FALSE);
File.Close();
}
}
void CTestMemFileDlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
CStdioFile File;
CMemFile MemFile;
if (File.Open(_T("E:\Temp\testfile.dat"), CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone))
{
int nVal;
nVal = setvbuf(File.m_pStream, NULL, _IOFBF, 1024768);
TestFun1(File, FALSE);
TestFun2(File, FALSE);
TestFun1(File, FALSE);
TestFun2(File, FALSE);
File.Close();
}
}
结果是:
按钮 1:
TestFun1: 18174
TestFun2: 375
TestFun1: 18330
TestFun2: 375
按钮 2:
TestFun1: 546
TestFun2: 530
TestFun1: 530
TestFun2: 531
根据我的测试,CFile + CArchive 总是占用 CStdioFile 大约 66% 的时间。我尝试将 CStdioFile 的缓冲区增加到 1MB,但仍然得到相同的结果。
因此,我的问题是,既然两种解决方案都使用缓冲,为什么 CStdioFile 总是比 CFile + CArchive 慢?
CStdioFile
默认以文本模式打开文件。这会导致特殊字符的翻译,例如回车 returns 和换行,这显然需要时间。
如果您想避免这种情况,可以将 CFile::typeBinary
添加到 CStdioFile::open()
调用中的 nOpenFlags
参数。