【问题标题】:Why CFile + CArchive performs better than C I/O stream?为什么 CFile + CArchive 的性能优于 C I/O 流?
【发布时间】:2019-11-17 12:03:40
【问题描述】:

我正在比较 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 总是占用大约 66% 的 CStdioFile 时间。我尝试将 CStdioFile 的缓冲区增加到 1MB,但仍然得到相同的结果。

因此,我的问题是,既然两种解决方案都使用缓冲,为什么 CStdioFile 总是比 CFile + CArchive 慢?

【问题讨论】:

  • 请注意,您的代码不是 C 代码——:: 的出现次数过多(多于零),这在 C 中永远无效。您可能正在使用 MS Visual Studio 和 MFC(Microsoft Foundation类)——即 C++ 代码。
  • @JonathanLeffler,是的,我的是 C++ 代码。
  • 代码示例可以改进,那里有太多未使用的代码,令人困惑。在 TestFun1 中,CArchive 对象和其他局部变量未使用。 CMemFile 对象也未使用。

标签: c++ file stream mfc buffer


【解决方案1】:

CStdioFile 默认以文本模式打开文件。这会导致特殊字符(例如回车和换行)的翻译,这显然需要时间。

如果您想避免这种情况,可以在CStdioFile::open() 调用中将CFile::typeBinary 添加到nOpenFlags 参数中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2010-11-12
    • 2011-05-07
    • 2023-03-08
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多