Улучшит ли буферизация данных производительность записи в IStream? - PullRequest
0 голосов
/ 15 января 2020

Я пытаюсь создать IStream из файла на диске, а затем записать в него много блоков данных. Каждый блок имеет размер 4096 байт. Поскольку нужно записать много блоков, я просто думаю о буферизации нескольких блоков в один большой буфер, а когда большой буфер заполнен, я выполняю фактическую запись в IStream. Повысит ли это производительность записи?

Я пытаюсь создать небольшое приложение для проверки:

    CFile SrcFile;
    LPSTREAM lpStreamFile = NULL;
    BYTE lpBuf[4096];
    BYTE lpLBuf[65536];
    BYTE* lpCurBuf;

    UINT uRead;
    DWORD uStart, uStop;

    uStart = ::GetTickCount();

    if (SrcFile.Open(_T("D:\\1GB.dat"), CFile::modeRead | CFile::shareExclusive | CFile::typeBinary))
    {
        SrcFile.SeekToBegin();

        ::DeleteFile(_T("F:\\1GB.dat"));

        if (SUCCEEDED(SHCreateStreamOnFileEx(_T("F:\\1GB.dat"), STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DIRECT,
            FILE_ATTRIBUTE_NORMAL, TRUE, NULL, &lpStreamFile)) && (lpStreamFile != NULL))
        {
            lpCurBuf = lpLBuf;

            while (TRUE)
            {
                uRead = SrcFile.Read(lpBuf, 4096);

                if ((lpCurBuf + uRead) > (lpLBuf + 65536))
                {
                    lpStreamFile->Write(lpLBuf, lpCurBuf - lpLBuf, NULL);
                    lpCurBuf = lpLBuf;
                }

                ::memcpy(lpCurBuf, lpBuf, uRead);
                lpCurBuf += uRead;

                //  lpStreamFile->Write(lpBuf, 4096, NULL);

                if (uRead < 4096)
                    break;
            }

            if (lpCurBuf > lpLBuf)
            {
               lpStreamFile->Write(lpLBuf, lpCurBuf - lpLBuf, NULL);
            }

            lpStreamFile->Commit(STGC_DEFAULT);

            if (lpStreamFile != NULL)
            {
                //  Release the stream
                lpStreamFile->Release();
                lpStreamFile = NULL;

            }
        }

        SrcFile.Close();
    }

    uStop = GetTickCount();

    CString strMsg;

    strMsg.Format(_T("Total tick count = %u."), uStop - uStart);

    AfxMessageBox(strMsg);

Большой размер буфера 65536, 16 раз по 4096. Я использую файл данных 1 ГБ чтобы сделать тест.

К моему удивлению, когда большой буфер не используется, то общее время всегда составляет около 10se c.

Однако, когда используется большой буфер, первый run займет 30se c, затем оставшийся run займет 10se c.

Так что кажется, что IStream уже имеет внутренний записанный буфер, так что мой большой буфер не приносит никакой пользы. Тем не менее, я не могу найти документ, подтверждающий это. Также я не могу найти документ, рассказывающий мне, как управлять, например, установить размер буфера.

...