| Главная | Журнал | Форум | Wiki | DRKB | Страны мира |
Введение в Memory-Mapped FilesАвтор: Vipul Patel ВведениеВ .NET Framework есть API-интерфейсы для редактирования файла, однако API, поставляемые в версиях до .NET Framework 4.0 не предназначены для работы с очень большими файлами. В потоковом классе MemoryStream (в отличие от FileStream) нет буферизации инкапсулированных данных и они напрямую помещаются в память. При отсутствии резервной копии данных, MemoryStream может оказаться полезным в качестве временного буфера. Memory-Mapped Files описываются в MSDN как способ, позволяющий приложениям работать с файлами так же как они работают с динамической памятью. Полная статья по Управлению отображаемыми в память файлами находится на сайте . Типы отображаемых в памяти файловВ библиотеке .NET framework 4.0 классы для работы с memory-mapped files находятся в пространстве имён System.IO.MemoryMappedFiles. Есть два основных типа отображаемых в память файлов: - Persisted Files (Сохраняемые файлы) - Эти файлы имеют связанный с ними физический файл на диске. Эти типы файлов используются при работе с очень большими объёмами. При этом в память загружается только часть такого файла. - Non-persisted files (Не сохраняемые файлы) - Эти файлы не имеют связанного с ними физического файла на диске, и при завершении процесса их содержимое теряется. Обычно такие файлы используются для взаимодействия между процессами и называются IPC. Преимущества отображаемых в памяти файловОдним из основных преимуществ использования memory-mapped files, это увеличение производительности при операциях чтения/записи в загруженный в память файл. Доступ к памяти происходит быстрее, чем дисковые операции ввода/вывода, следовательно, повышение производительности достигается и при работе с очень большими файлами. Отображаемые в памяти файлы также предлагают отложенную загрузку, что требует использрования небольшого количества оперативной памяти даже для больших файлов. В таких случаях приложение работает с данными в файле через так называемые отображения (вьюхой), которые физически загружают с диска всего одну страницу данных в текущий момент. Способность создавать представления позволяет значительно уменьшить потребление памяти в приложении. Недостатки Memory-Mapped FilesЕсли представление для работы с файлом будет создано непродуманно с загрузкой большого количества данных, то это может сказаться на стартовой производительности приложения. Работа с отображаемыми в память файламиРабота с отображаемыми в память файлами происходит путём создания представления части или полного содержимого файла. В 32-битных операционных системах, так как использование оперативной памяти ограничено двумя гигабайтами, может потребоваться создание несколько представлений. Если для чтения последовательности данных из физического файла Вы используете потоковое чтение в память, то необходимо будет воспользоваться потоком MemoryMappedViewStream, который можно создать вызовом метода CreateViewStream объекта MemoryMappedFile. Для IPC, Ваш отображаемый в память файл потребует отображение MemoryMappedViewAccessor имеющее доступ к оперативной памяти, и может быть создано вызовом метода CreateViewAccessor в экземпляре MemoryMappedFile. Пример приложения с использованием Сохраняемого Memory Mapped FileВ нижеприведённом фрагменте кода мы создаем сохраняемый файл, связанный с соответствующим физическим файлом на диске, доступ к которому осуществляется последовательно:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.MemoryMappedFiles;
namespace PersistentMemoryMappedFile
{
class Program
{
static string LargeString = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000.";
static void Main(string[] args)
{
CreateLargeFile();
CreateMemoryMappedFile("largetextfile.txt");
}
private static void CreateMemoryMappedFile(string fileName)
{
FileInfo fInfo = new FileInfo(fileName);
long length = fInfo.Length;
MemoryMappedFile mySequentialMMF = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, "MySequentialMap");
for (long i = 0; i < length; i = i + 100000)
{
MemoryMappedViewStream myMMFViewStream = mySequentialMMF.CreateViewStream(0, 100000, MemoryMappedFileAccess.ReadWrite);
myMMFViewStream.WriteByte((byte)'A');
Console.WriteLine("We changed a bit");
}
}
private static void CreateLargeFile()
{
using (StreamWriter sw = new StreamWriter("largetextfile.txt", false))
{
for (int i = 0; i < 500000; i++)
sw.WriteLine(LargeString);
}
File.Copy("largetextfile.txt", "largetextfileoriginal.txt");
}
}
}
Листинг 1 В приведенном выше фрагменте кода сперва создаётся большой файл, а затем с помощью MemoryMappedFile меняется каждый стотысячный байт в потоке на "А". Если у вас есть программы умеющие работать с большими файлами, то Вы заметите разницу. Пример MemoryMappedFile для межпроцессного взаимодействияДавайте посмотрим пример использования отображаемой памяти файлов для связи между процессами. В примере приведены два приложения: одно записывает, а другое считывает. Листинг записывающего приложения:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.MemoryMappedFiles;
using System.IO;
using System.Threading;
namespace NonPersistedMemoryMappedFileA
{
class Program
{
static void Main(string[] args)
{
MemoryMappedFile myNonPersisterMemoryMappedFile = MemoryMappedFile.CreateNew("myNonPersisterMemoryMappedFile", 100);
bool IsmutexCreated;
Mutex mymutex = new Mutex(true, "NonPersisterMemoryMappedFilemutex", out IsmutexCreated);
Console.WriteLine("Start NonPersisterMemoryMappedFileB now");
Console.ReadLine();
StreamWriter sw = new StreamWriter(myNonPersisterMemoryMappedFile.CreateViewStream());
sw.WriteLine("Process A says Hi");
sw.Close();
mymutex.ReleaseMutex();
}
}
}
Листинг 2 - NonPersistedMemoryMappedFileB.cs Компилируется вышеприведённый код в NonPersistedMemoryMappedFileA.exe с помощью следующей команды: C:\windows\microsoft.net\frame work\v4.0.30319\csc.exe NonPersistedMemoryMappedFileA.cs Теперь листинг читающего приложения:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.MemoryMappedFiles;
using System.IO;
using System.Threading;
namespace NonPersistedMemoryMappedFileB
{
class Program
{
static void Main(string[] args)
{
MemoryMappedFile myNonPersisterMemoryMappedFile = MemoryMappedFile.OpenExisting("myNonPersisterMemoryMappedFile");
Mutex mymutex = Mutex.OpenExisting("NonPersisterMemoryMappedFilemutex");
mymutex.WaitOne();
StreamReader sr = new StreamReader(myNonPersisterMemoryMappedFile.CreateViewStream());
Console.WriteLine(sr.ReadLine());
sr.Close();
mymutex.ReleaseMutex();
StreamWriter sw = new StreamWriter(myNonPersisterMemoryMappedFile.CreateViewStream());
sw.WriteLine("Process B says Hi");
sw.Close();
}
}
}
Листинг 3 - NonPersistedMemoryMappedFileB.cs Этот код компилируется в NonPersistedMemoryMappedFileB.exe с помощью следующей команды: C:\windows\microsoft.net\framework\v4.0.30319\csc.exe NonPersistedMemoryMappedFileB.cs После компиляции откройте командную строку и выполните NonPersistedMemoryMappedFileA.exe. После появления просьбы запустите NonPersistedMemoryMappedFileB.exe и нажмите Enter в окне NonPersistedMemoryMappedFileA.exe. После этого будет видно как приложение NonPersistedMemoryMappedFileB.exe выводит сообщения посылаемы ему из NonPersistedMemoryMappedFileA.exe. Статьи по Теме• Введение в Code Access Security в .NET Framework СкачатьMemoryMappedFilesDemo.zip (78кб) |
Основные разделы сайта
|
|
|