SSD source I / O tests with random read / write

My laptop has an SSD with a physical disk sector size of 512 bytes and a disk size of 4096 bytes. I am working on an ACID database system that should bypass all OS caches, so I write directly from the allocated internal memory (RAM) to the SSD. I also expand the files before running the tests and do not change their size during the tests.

Now here is my problem, according to the SSD tests, random read and write should be in the range from 30 MB / s to 90 MB / s, respectively. But here is my (rather awful) telemetry from my many checks:

  • 1.2 MB / s when reading random 512 byte blocks (physical sector size)
  • 512 KB / s for writing arbitrary 512 byte blocks (physical sector size)
  • 8.5 MB / s when reading random 4,096 byte blocks (logical sector size)
  • 4.9 MB / s when writing random 4,096 byte blocks (logical sector size)

In addition to using asynchronous I / OI, also set the flags FILE_SHARE_READand FILE_SHARE_WRITEto disable all OS buffering - because our database is ACID, I have to do this, I also tried FlushFileBuffers(), but this is even worse than me. I also expect each async I / O to complete, as required by some of our code.

Here is my code, is there a problem with it, or am I sticking to this poor I / O performance?

HANDLE OpenFile(const wchar_t *fileName)
{
    // Set access method
    DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE ;

    // Set file flags
    DWORD fileFlags = FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING /*| FILE_FLAG_RANDOM_ACCESS*/;

    //File or device is being opened or created for asynchronous I/O
    fileFlags |= FILE_FLAG_OVERLAPPED ;

    // Exlusive use (no share mode)
    DWORD shareMode = 0;

    HANDLE hOutputFile = CreateFile(
        // File name
        fileName,
        // Requested access to the file 
        desiredAccess,
        // Share mode. 0 equals exclusive lock by the process
        shareMode,
        // Pointer to a security attribute structure
        NULL,
        // Action to take on file
        CREATE_NEW,
        // File attributes and flags
        fileFlags,
        // Template file
        NULL
    );
    if (hOutputFile == INVALID_HANDLE_VALUE)
    {
        int lastError = GetLastError();
        std::cerr << "Unable to create the file '" << fileName << "'. [CreateFile] error #" << lastError << "." << std::endl;
    }

    return hOutputFile;
}

DWORD ReadFromFile(HANDLE hFile, void *outData, _UINT64 bytesToRead, _UINT64 location, OVERLAPPED *overlappedPtr, 
    asyncIoCompletionRoutine_t completionRoutine)
{
    DWORD bytesRead = 0;

    if (overlappedPtr)
    {
        // Windows demand that you split the file byte locttion into high & low 32-bit addresses
        overlappedPtr->Offset = (DWORD)_UINT64LO(location);
        overlappedPtr->OffsetHigh = (DWORD)_UINT64HI(location);

        // Should we use a callback function or a manual event
        if (!completionRoutine && !overlappedPtr->hEvent)
        {
            // No manual event supplied, so create one. The caller must reset and close it themselves
            overlappedPtr->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
            if (!overlappedPtr->hEvent)
            {
                DWORD errNumber = GetLastError();
                std::wcerr << L"Could not create a new event. [CreateEvent] error #" << errNumber << L".";
            }
        }
    }

    BOOL result = completionRoutine ? 
        ReadFileEx(hFile, outData, (DWORD)(bytesToRead), overlappedPtr, completionRoutine) : 
        ReadFile(hFile, outData, (DWORD)(bytesToRead), &bytesRead, overlappedPtr);

    if (result == FALSE)
    {
        DWORD errorCode = GetLastError();
        if (errorCode != ERROR_IO_PENDING)
        {
            std::wcerr << L"Can't read sectors from file. [ReadFile] error #" << errorCode << L".";
        }
    }

    return bytesRead;
}
+4
source share
2 answers

IO /. IOPS. "1,2 / 512 " = > 20000 IOPS. . , 199% MB/sec 99% IOPS, 512 , 1024 ( ). SSD , .

, .

SSD . IO . concurrency - 1-32.

SSD concurrency, . , SSD 4 "".

FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING - , . , , . , , .

.

, , async IO, , . . IO ( , async IO), - .

+1

hdparm -I/dev/sdx, . SSD 4096 , 512 . "512 " A.K.A 512e. , 512 , 512- . SSD 4k.

4k -, , , IOPS, , SSD. 512 - .

0

Source: https://habr.com/ru/post/1539252/


All Articles