Travailler avec des fichiers mappés en mémoire dans .Net

L'accès aux fichiers est une opération gourmande en ressources. L'accès à un fichier à partir du disque pour une application est une opération qui prend du temps et l'accès aux données à partir de la mémoire principale est toujours plus rapide. Alors, que se passe-t-il si les fichiers disque que votre application a besoin de lire ou d'écrire résidaient en mémoire? C'est exactement là que s'inscrit le concept de fichiers mappés en mémoire. Dans cet article, nous allons explorer comment nous pouvons travailler avec des fichiers mappés en mémoire dans .Net.

Présentation des fichiers mappés en mémoire

Un fichier mappé en mémoire est un objet noyau utilisé pour mapper un fichier de votre disque sur une région de la mémoire principale. Les fichiers mappés en mémoire peuvent avoir des gains de performances importants par rapport à l'accès direct au disque lorsque vous travaillez avec une grande quantité de données ou de grandes images. Les fichiers mappés en mémoire faisaient partie de l'API Win32, mais jusqu'à récemment, vous étiez limité à l'utilisation de C ++ ou PInvoke pour écrire du code qui exploite les fichiers mappés en mémoire dans votre application. Cependant, avec .Net Framework 4, vous pouvez désormais travailler avec des fichiers mappés en mémoire directement à partir de vos applications .Net - le runtime vous fournit désormais un wrapper géré avec toutes les classes wrapper nécessaires pour appeler l'API Win32. Le MSDN indique: «Un fichier mappé en mémoire contient le contenu d'un fichier dans la mémoire virtuelle. Ce mappage entre un fichier et l'espace mémoire permet à une application, y compris plusieurs processus,pour modifier le fichier en lisant et en écrivant directement dans la mémoire. "

Pourquoi avez-vous besoin de fichiers mappés en mémoire?

Les fichiers mappés en mémoire sont un bon choix lorsque vous avez besoin de travailler avec une grande quantité de données et que vous souhaitez éviter le coût associé au marshaling et à la déconstruction tout en partageant des données au-delà des limites du processus. Les fichiers mappés en mémoire sont parfaits pour traiter un fichier volumineux - la lecture d'un fichier volumineux est une opération intensive en ressources. Avec les fichiers mappés en mémoire, vous pouvez mapper une partie spécifique de votre fichier en mémoire et effectuer des opérations d'E / S avec ce bloc pour accélérer l'accès.

Un fichier mappé en mémoire vous permet de réserver une plage d'adresses mémoire et d'utiliser un fichier disque comme stockage physique pour l'adresse réservée. En d'autres termes, cela vous permet de réserver un espace dans la mémoire, puis de valider le stockage physique dans cette région. Cela vous permet d'accéder aux données sur le disque sans avoir besoin d'effectuer une opération d'E / S de fichier. Les fichiers mappés en mémoire vous permettent également de partager des données entre plusieurs processus. Le système d'exploitation prend en charge la gestion de la mémoire pour les fichiers mappés en mémoire - vous n'avez pas à vous soucier de la façon dont le fichier est partitionné en pages et géré. Vous pouvez également appliquer la sécurité dans votre fichier mappé en mémoire à l'aide de l'énumération MemoryMappedFileAccess comme paramètre lors de la création du fichier mappé en mémoire. 

Fichiers mappés en mémoire persistante et non persistante

Il existe essentiellement deux types de fichiers mappés en mémoire. Ceux-ci sont:

Persistant : les fichiers mappés en mémoire persistante sont ceux qui sont associés à un fichier source sur le disque de votre système. Lorsque vous travaillez avec ces types de fichiers mappés en mémoire, les données sont conservées sur le disque une fois que le dernier processus travaillant sur le fichier a terminé son activité.

Non persistant : les fichiers mappés en mémoire non persistants sont ceux qui ne sont pas associés à un fichier disque. Lorsque vous travaillez avec ces types de fichiers mappés en mémoire, les données ne sont pas conservées une fois que le dernier processus travaillant sur le fichier a terminé son travail. Les fichiers mappés en mémoire non persistante sont parfaits pour le partage de mémoire pour les communications entre processus.

Création de fichiers mappés en mémoire persistante

Pour créer un fichier mappé en mémoire persistante, vous devez utiliser la méthode CreateFromFile de la classe MemoryMappedFile. La classe MemorymappedFile est présente dans l'espace de noms System.IO.MemoryMappedFiles.

L'extrait de code suivant utilise la méthode CreateFromFile pour créer un fichier mappé en mémoire. Il crée ensuite une vue mappée en mémoire sur une partie du fichier.

static long offset = 0x10000000; // 256 megabytes

static long length = 0x20000000; // 512 megabytes

        static void Main()

        {

            using (var memoryMappedFile = MemoryMappedFile.CreateFromFile("F:\\ImageData.png", FileMode.Open, "PartitionA"))

            {

                using (var accessor = memoryMappedFile.CreateViewAccessor(offset, length))

                {

                    //Other code

                }

            }

        } 

L'extrait de code donné ci-après montre comment vous pouvez lire des données à partir d'un fichier mappé en mémoire.

using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateFromFile("F:\\LargeData.dat"))

            {

                using (MemoryMappedViewStream memoryMappedViewStream = memoryMappedFile.CreateViewStream(0, 1204, MemoryMappedFileAccess.Read))

                {

                    var contentArray = new byte[1024];

                    memoryMappedViewStream.Read(contentArray, 0, contentArray.Length);

                    string content = Encoding.UTF8.GetString(contentArray);

                }

            }

Création de fichiers mappés en mémoire non persistante

Pour créer des fichiers mappés en mémoire non persistants, c'est-à-dire des fichiers qui ne sont pas mappés à un fichier existant sur le disque, vous devez tirer parti des méthodes CreateNew et CreateOrOpen.

L'extrait de code suivant illustre comment un fichier mappé en mémoire non persistante peut être créé.

using(MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateNew("idg.txt", 5))

            {

                using(MemoryMappedViewAccessor memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor())

                {

                var data = new[] { (byte)'I', (byte)'D', (byte)'G'};

                for (int i = 0; i < data.Length; i++)

                    memoryMappedViewAccessor.Write(i, data[i]);

                memoryMappedViewAccessor.Dispose();

                memoryMappedFile.Dispose();

                }

            }

Vous pouvez en savoir plus sur les fichiers mappés en mémoire à partir de cet article MSDN.