2016-02-29 4 views
1

В настоящее время я использую общую память с двумя сопоставленными файлами (1,9 ГБ для первого и 600 Мбайт для второго) в программном обеспечении.
Я использую процесс, который считывает данные из первого файла, обрабатывает данные и записывает результаты во второй файл.
Иногда я замечал сильную задержку (причина не в моих силах) при чтении или записи в виде отображения с функцией 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); 

The dwOffsetHigh/dwOffsetLow являются "соответствие" зернистость от информации о системе.

Процесс считывает около 300 КБ * N раз, сохраняя это в буфере, обрабатывая и затем записывая 300 Кбайт * N раз обрабатываемое содержимое предыдущего буфера во второй файл.
У меня есть два разных вида памяти (созданные/перемещенные с помощью функции MapViewOfFile) размером 10 МБ в качестве размера по умолчанию.
Для размера памяти, я тестировал 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, чтобы точно определить, где задержка, я вижу, что второй тетсру вызов всегда один принимает большую часть времени ,
Итак, до сих пор я вижу N (для теста, я использовал N = 500) звонки на memcpy, принимающие 10 секунд в худшее время при использовании этих общих воспоминаний.
Я сделал временное программное обеспечение, которое выполняло то же количество вызовов memcpy, столько же данных и не могло видеть проблему.

Для тестов я использовал следующие условия, все они показывают ту же задержку:
1/Я могу видеть это на различных компьютерах, 32 или 64 бита из окна 7 к окнам 10.
2/с использованием основной поток или многопоточность (до 8 с критическими разделами для синхронизации) для чтения/записи.
3/ОС на SATA или SSD, память отображает файлы программного обеспечения физически на жестком диске SATA или SSD, а на внешнем жестком диске тесты выполняются через USB1, USB2 или USB3.

Прошу вас, как вы думаете, моя ошибка в том, что memcpy идет медленно.

С уважением.

+1

Это нормально с картографическими файлами памяти. В какой-то момент ему необходимо физически передать данные на диски - и ваши диски связаны с IO. – SergeyA

+0

Возможно, вам понадобится профиль для изменения кода, где вы буферизируете данные и не используете файлы с отображением памяти. Измените размер буфера, чем размер входного блока, чтобы повысить производительность. –

+0

Поиск на сайте MSDN для API, который может заблокировать вашу память, чтобы предотвратить замену ОС на жесткий диск. –

ответ

0

Я нашел решение, которое работает для меня, но не может быть и для других.
Следуя за комментариями Томаса Мэтьюза, я проверил MSDN и нашел две интересные функции FlushViewOfFile и FlushFileBuffers (но не смог найти ничего интересного о блокировке памяти).
Вызов как после обновления цикла цикла для отображаемого файла.
У меня больше нет «случайной» задержки, но вместо ожидаемых 200 мс у меня в среднем 400 мс, что достаточно для моего приложения.

После выполнения некоторых тестов я видел, что слишком часто их вызов приведет к тяжелому доступу на жесткий диск и ухудшит задержку (10 секунд для каждого цикла), поэтому флеш следует использовать осторожно.

Спасибо.

Смежные вопросы