2015-08-19 14 views
5

Я использую файл с отображением памяти, который составляет ок. 100 ГБ данных. Когда я вызываю CreateViewStream в этот файл, для его создания требуется 30 минут, и кажется, что это из-за размера файла с отображением памяти, но почему он так долго? Он копирует весь файл в управляемую память?MemoryMappedFile с очень медленным CreateViewStream

Это займет намного больше времени, когда я пишу файл с файловым потоком и получаю доступ к нему без перезагрузки. (странно)

+0

Где находится файл? –

+0

на локальном диске ssd – Sebastian

+1

Вам нужен вид на весь файл? Если нет, попробуйте создать представление на требуемой части только путем передачи смещения и длины - 'using (var accessor = mmf.CreateViewAccessor (смещение, длина))' – displayName

ответ

4

Я не могу повторить эти проблемы. Вот код, который я использовал для теста:

static void Main(string[] args) 
    { 
     var sw = Stopwatch.StartNew(); 
     var mmf = MemoryMappedFile.CreateFromFile(@"f:\test.bin"); 
     var stream = mmf.CreateViewStream(); 
     for (int i = 0; i < 100000; i++) 
     { 
      stream.ReadByte(); 
     } 
     Console.WriteLine(sw.Elapsed); 
    } 

f:\test.bin является 100GB нули файла, который я создал для целей данного теста. Я могу создать MemoryMappedFile, затем запустить CreateViewStream и прочитать 100 000 байтов из него в 3.7s.

Просьба представить образец кода, демонстрирующий поведение, которое вы описали, и я буду рад разделить его и посмотреть, что происходит.

+0

Думаю, вам нужно сделать больше вещей, чем просто «ReadByte» в вашем цикле 'for'. Компилятор может оптимизировать цикл и, следовательно, вы можете запустить свой цикл за 3,7 секунды. Просто я предполагаю, что я ошибаюсь. – displayName

+1

@displayName: С тех пор я удалил тестовый файл. Я могу воссоздать его и что-то сделать, что угодно, но это не важно. Утверждение состоит в том, что вызов 'CreateViewStream()' является дорогостоящим (и занимает слишком много времени в его системе), но я продемонстрировал, что он сам по себе для большого файла не так дорог (по крайней мере, не для моей собственной системы). Ему нужно предоставить больше кода, чтобы кто-либо мог оценить его претензии. – willaien

+0

Хммм ... Похоже, OPs RAM/архитектура - проблема. – displayName

3

Трудно ответить без кода, знания вашей основной памяти и архитектуры. Поэтому я могу только догадываться о некоторых важных указателях:

  1. У вас достаточно оперативной памяти? Если вы ссылаетесь на адрес, который еще не загружен в ОЗУ, возникает ошибка страницы за кулисами и считывает данные в ОЗУ для вас. Ваша программа не замечает эту активность, потому что ваш поток приостанавливается, когда ошибка страницы обрабатывается. Хорошая статья here.
  2. Еще один важный момент из той же статьи. У вас нет контроля над , сколько MMF хранится в памяти или как долго. Это означает, что использование MMF может выталкивать другие вещи из ОЗУ, такие как страницы кода или данных, которые вам понадобятся «скоро». Это приводит к более медленному выполнению. Я особенно хочу указать любому человеку, читающему этот ответ, на another answer here, так что у нас есть четкое представление о том, как эта медленность протекает с точки зрения процессорных циклов slow.
  3. Затем вы создаете поток. Потоки подходят для последовательного доступа, хотя вы, возможно, пытаетесь читать/писать случайно.

Что касается времени выполнения конца в конец кода в FileStream против ММФ подхода, я думаю, вы должны запустить тесты заново, так как работает ваш первый подход мощь результат в прогретый кэш для второго один. Тогда результаты не будут корректными.

Согласно MSDN documentation of MMF,

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

Способ работы MMF заключается в том, что вся (или часть) файла отображается в виде виртуальной памяти, которая прозрачно выгружается в ОС и выходит из нее при доступе к частям файла.Вот почему MMF отлично подходят для работы с большими файлами.

Вы можете быть умнее и читать часть всего файла и выполнить произвольный доступ путем использования:

using (var accessor = mmf.CreateViewAccessor(offset, length)) 
{ 
    //Here you have access to a specific part of the file 
} 

, так что у вас есть доступ к представлению с указанным смещением и размера, из мамонта файла картография памяти.