Отображение памяти и производительность P/Invoke в C++/C# interop

Я разработал несколько dll некоторое время назад, чтобы P/Invoke некоторые вещи от C++ DLL до C#. Однако я работаю в жестких условиях реального времени, и P/Invoke оказался слишком медленным для выполнения определенных операций.

Поэтому я наткнулся на Memory Mapping как (предположительно) более быструю альтернативу P/Invoke, и во время моих тестов сторона C++ не выглядела слишком потрепанной:

#include "stdafx.h"

#define BUF_SIZE 256
TCHAR szName[] = TEXT("MyFileMappingObject");
char* pcTest = "Message from C++";

int _tmain()
{
    HANDLE hMapFile;
    LPCTSTR pBuf;

    hMapFile = CreateFileMapping(
                INVALID_HANDLE_VALUE,
                NULL,
                PAGE_READWRITE,
                0,
                BUF_SIZE,
                szName);

    if (hMapFile == NULL) {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
        return 1;
    }

    pBuf = (LPTSTR)MapViewOfFile(
                hMapFile,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                BUF_SIZE);

    if (pBuf == NULL) {
        _tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
        CloseHandle(hMapFile);
        return 1;
    }

    CopyMemory((PVOID)pBuf, pcTest, (strlen(pcTest) * sizeof(char*)));

    std::cin.get(); 

    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);

    return 0;
}

Я адаптировал код отсюда:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx

А вот сторона C#:

    static void Main(string[] args)
    {
        MemoryMappedFile pagedMemoryMap = MemoryMappedFile.OpenExisting("MyFileMappingObject", MemoryMappedFileRights.FullControl);

        using (MemoryMappedViewAccessor fileMap = pagedMemoryMap.CreateViewAccessor())
        {
            var array = new byte[256];
            fileMap.ReadArray(0, array, 0, 16); //Take notice on this line
            var text = Encoding.ASCII.GetString(array);
            Console.WriteLine(text);
        }

        Console.ReadKey();
    }

Он работает как задумано, но здесь есть проблема: этот фиксированный размер длины байтового массива в методе ReadArray. Я предполагаю, что мне придется записать длину фактических строк в моем реальном приложении в другой общий ресурс, а затем использовать его для чтения значения строки, но это кажется слишком громоздким. Учитывая, что то, что я на самом деле читаю из C++ в реальном приложении, это массивы структур (которые в основном содержат только строки), получу ли я какое-либо преимущество от отображения памяти с точки зрения производительности? У меня нет никаких намерений вздувать стабильный код (хотя и медленно) с альтернативой, которая может не дать ожидаемых результатов, так есть ли какие-то реальные преимущества этого подхода? Есть ли лучшая альтернатива?

1 ответ

Отображенные в память файлы хороши для обмена данными между процессами. Они бессмысленны для совместного использования между модулями в одном и том же пространстве памяти.

Просто определите свою структуру данных как тип ссылочного класса обычным способом, а затем закрепите ее. Теперь C++ может напрямую обращаться к структуре данных, используя обычный доступ с указателем.

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

Другие вопросы по тегам