我目前在一個軟件中使用兩個映射文件(第一個是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,以防止操作系統將其與硬盤進行交換。 –