Windows共享内存访问时间慢

时间:2016-02-29 14:53:25

标签: c++ winapi mfc shared-memory

我目前正在使用带有两个映射文件的共享内存(第一个为1.9 GB,第二个为600 MB)。 我正在使用一个进程从第一个文件中读取数据,处理数据并将结果写入第二个文件 当用memcpy函数读取或写入映射视图时,我注意到有时会出现强烈的延迟(原因是我不知道)。

以这种方式创建映射文件:

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倍写入第二个文件。
我有两个不同的内存视图(使用MapViewOfFile函数创建/移动),默认大小为10 MB。 对于内存视图大小,我测试了10kBytes,100kB,1MB,10MB和100MB。
统计上没有区别,80%的阅读时间如下所述(~200ms),但写作过程非常慢。

通常:
 1 /阅读在~200ms内完成  2 /过程在2.9秒内完成  3 /写作在~200ms完成。

我可以看到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 /我可以在各种计算机上看到这一点,32或64位从Windows 7到Windows 10 2 /使用主线程或多线程(最多8个用于同步目的的关键部分)进行读/写 3 / SATA或SSD上的操作系统,软件的内存映射文件在SATA或SSD硬盘上,如果在外部硬盘上,则通过USB1,USB2或USB3进行测试。

我很恳请你问你认为我的错误是因为memcpy变慢了。

最好的问候。

1 个答案:

答案 0 :(得分:0)

我找到了一个对我有用的解决方案,但对其他人来说却不是这样 在Thomas Matthews评论之后,我检查了MSDN,发现了两个有趣的函数FlushViewOfFile和FlushFileBuffers(但是找不到任何有关锁定内存的信息)。
在for循环强制更新映射文件后调用两者 我没有更多&#34;随机&#34;延迟,但不是预期的200毫秒,我有平均400毫秒,这足以满足我的申请
在做了一些测试后,我发现那些经常调用它们会导致大量的硬盘访问,并且会使延迟变得更糟(每个for循环都需要10秒),所以应该小心使用刷新。

感谢。