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