我目前在一个软件中使用两个映射文件(第一个是1.9 GBytes,第二个是600 MBytes)的共享内存。
我正在使用从第一个文件读取数据,处理数据并将结果写入第二个文件的进程。
在使用memcpy函数读取或写入映射视图时,我注意到有时会出现强烈的延迟(原因不在我的知识范围内)。
Windows共享内存访问时间较慢
映射文件被创建这样:
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 MBytes作为默认大小。
对于内存视图大小,我测试了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/I可以看到这在各种计算机上,从窗口7 32或64位至10窗户
2 /使用主线程或多线程(最多8个用于同步目的的关键部分)用于读/写。
SATA或SSD上的3/OS,物理上位于SATA或SSD硬盘上的软件内存映射文件,如果在外部硬盘上,则通过USB1,USB2或USB3完成测试。
我很好奇地问你,我认为我的错误是memcpy变慢。
此致敬礼。
这对存储器映射文件来说是正常的。在某些情况下,它需要将数据物理提交到磁盘 - 并且您的磁盘IO绑定。 – SergeyA
您可能想要针对代码更改进行配置文件,而您正在缓存数据而不使用内存映射文件。改变缓冲区的大小而不是输入块大小以获得性能。 –
在MSDN网站上搜索可锁定内存的API,以防止操作系统将其与硬盘进行交换。 –