c++ - Windows共享内存访问时间慢

标签 c++ winapi mfc shared-memory

我目前在一个软件中使用共享内存和两个映射文件(第一个 1.9 GB,第二个 600 MB)。
我正在使用从第一个文件读取数据、处理数据并将结果写入第二个文件的过程。
我注意到在使用 memcpy 函数读取或写入映射 View 时,有时会出现严重的延迟(原因不明)。

映射文件是这样创建的:

m_hFile = ::CreateFileW(SensorFileName, 
                        GENERIC_READ | GENERIC_WRITE,
                        0,
                        NULL,
                        CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);

m_hMappedFile = CreateFileMapping(m_hFile,
                                  NULL,
                                  PAGE_READWRITE,
                                  dwFileMapSizeHigh,
                                  dwFileMapSizeLow,
                                  NULL);

内存映射是这样完成的:

m_lpMapView = MapViewOfFile(m_hMappedFile, 
                            FILE_MAP_ALL_ACCESS,
                            dwOffsetHigh,
                            dwOffsetLow,
                            m_i64ViewSize);

dwOffsetHigh/dwOffsetLow 是来自系统信息的“匹配”粒度。

该进程正在读取大约 300KB * N 次,将其存储在缓冲区中,进行处理,然后将前一个缓冲区的已处理内容的 300KB * N 次写入第二个文件。
我有两个不同的内存 View (使用 MapViewOfFile 函数创建/移动),默认大小为 10 MBytes。
对于内存 View 大小,我测试了 10kBytes、100kB、1MB、10MB 和 100MB。
统计上没有区别,80% 的读取过程如下所述(~200 毫秒),但写入过程真的很慢。

通常:
1/读取在约 200 毫秒内完成。
2/过程在 2.9 秒内完成。
3/写入在约 200 毫秒内完成。

我可以看到 80% 的时间,读取或写入(在最坏的情况下两者都很慢)将花费 2 到 10 秒。

例子:为了写作,我使用下面的代码

for (unsigned int i = 0 ; i < N ; i++)  // N = 500~3k
{
    // Check the position of the memory view for ponderation
    if (###)
        MoveView(iOffset);

    if (m_lpMapView)
    {
        memcpy((BYTE*)m_lpMapView + iOffset, pANNHeader, uiANNStatus);
        // uiSize = ~300 kBytes
        memcpy((BYTE*)m_lpMapView + iTemp, pLine[i], uiSize);
    }
    else
        return uiANNStatus;
}

在使用 GetTickCount 函数查明延迟时间后,我发现第二次 memcpy 调用总是占用大部分时间。
所以,到目前为止,我看到 N(为了测试,我使用了 N = 500)次调用 memcpy 在使用这些共享内存时花费了 10 秒
我制作了一个临时软件,它执行相同数量的 memcpy 调用、相同数量的数据,但看不到问题。

为了测试,我使用了以下条件,它们都显示相同的延迟:
1/我可以在从 Windows 7 到 Windows 10 的 32 位或 64 位计算机上看到这个。
2/使用主线程或多线程(最多 8 个线程用于同步目的的临界区)进行读/写。
3/SATA 或 SSD 上的操作系统,软件的内存映射文件物理存储在 SATA 或 SSD 硬盘上,如果在外部硬盘上,则通过 USB1、USB2 或 USB3 进行测试。

请问您认为我的错误是什么让 memcpy 运行缓慢。

最好的问候。

最佳答案

我找到了适合我的解决方案,但可能不适用于其他人。
根据 Thomas Matthews 的评论,我查看了 MSDN,发现了两个有趣的函数 FlushViewOfFile 和 FlushFileBuffers(但找不到任何关于锁定内存的有趣信息)。
在映射文件的 for 循环强制更新之后调用两者。
我没有更多的“随机”延迟,但不是预期的 200 毫秒,而是平均 400 毫秒,这对我的应用程序来说已经足够了。

在做了一些测试后,我发现过于频繁地调用它们会导致大量的硬盘访问,并且会使延迟更糟(每个 for 循环 10 秒),因此应谨慎使用刷新。

谢谢。

关于c++ - Windows共享内存访问时间慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35702593/

相关文章:

c++ - Opengl 纹理有时会在窗口调整大小时闪烁/移动

c++ - 在 MFC 中填充下拉列表

c++ - MFC 对话框按钮显示为黑框

visual-c++ - Visual Studio 2012 上的 vc++ 项目缺少 mfc110ud.dll

c++ - `std::multimap` 是否保证每个键的实际值在相等范围内?

c++ - 包含来自每个 k 列表的至少 1 个元素的最小元素范围的时间复杂度

c# - 来自窗口句柄的 .net 类名

winapi - 在 Windows 10 上浏览 NTFS 更改日志

c++ - 为什么使用 LLVM 时 std::ifstream "break"std::getline 的缓冲?

javascript - 将 JavaScript Array.slice + 隐式扩展转换为 C++ vector