Почему CFile + CArchive работает лучше, чем поток ввода-вывода C? - PullRequest
2 голосов
/ 08 июля 2019

Я сравниваю производительность между классами MFC:

  • CFile + CArchive (использует буфер)

и

  • CStdioFile (использует буферизованный поток ввода / вывода)

Оба используют буфер.

Ниже приведены мои коды:

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();
    }
}

Результаты:

Button1:

TestFun1: 18174
TestFun2: 375
TestFun1: 18330
TestFun2: 375

Button2:

TestFun1: 546
TestFun2: 530
TestFun1: 530
TestFun2: 531

Согласно моему тесту, CFile + CArchive всегда занимает около 66% времени CStdioFile. Я пытаюсь увеличить буфер до CStdioFile до 1 МБ, но все равно получаю тот же результат.

Поэтому мой вопрос таков: поскольку оба решения используют буферизацию, почему CStdioFile всегда будет работать медленнее, чем CFile + CArchive?

1 Ответ

4 голосов
/ 08 июля 2019

CStdioFile открывает файлы в текстовом режиме по умолчанию.Это вызывает перевод специальных символов, таких как возврат каретки и перевод строки, что, очевидно, займет время.

Если вы хотите избежать этого, вы можете добавить CFile::typeBinary к параметру nOpenFlags вCStdioFile::open() Звоните.

...