2015-08-19 4 views
5

J'utilise un fichier mappé en mémoire d'env. 100 Go de données. Quand j'appelle le CreateViewStream sur ce dossier il prend 30 minutes pour le créer et semble que c'est à cause de la taille du dossier mappé de mémoire mais, pourquoi le prend si longtemps? Copie-t-il le fichier entier dans la mémoire gérée?MemoryMappedFile avec très lent CreateViewStream

Cela prend beaucoup plus de temps lorsque j'écris le fichier avec un flux de fichier et y accéder sans redémarrage. (étrangement)

+0

Où se trouve le fichier? –

+0

sur un lecteur ssd local – Sebastian

+1

Avez-vous besoin de la vue sur l'ensemble du fichier? Sinon, essayez de créer la vue sur la partie requise en passant un offset et une longueur - 'using (var accessor = mmf.CreateViewAccessor (décalage, longueur))' – displayName

Répondre

4

Je suis incapable de reproduire ces problèmes. Voici le code que j'utilisé pour tester:

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 est un fichier rempli de zéros que je 100Go établis aux fins de ce test. Je suis en mesure de créer le MemoryMappedFile, puis exécutez CreateViewStream et lire 100 000 octets à partir de ce dans 3.7s.

Veuillez fournir un exemple de code qui présente le comportement que vous avez décrit et je serai ravi de le distinguer et de voir ce qui se passe.

+0

Je pense que vous devriez faire plus de choses que juste un 'ReadByte' dans votre boucle' for'. Le compilateur a peut-être optimisé la boucle et vous pouvez donc exécuter votre boucle en 3,7 secondes. À mon avis, j'ai peut-être tort. – displayName

+1

@displayName: J'ai depuis supprimé le fichier de test. Je peux le recréer et faire quelque chose, n'importe quoi, mais ce n'est pas important. L'affirmation est qu'un appel à 'CreateViewStream()' est coûteux (et prend énormément de temps sur son système), mais, j'ai démontré que, en soi, pour un gros fichier, n'est pas si cher (au moins pas pour mon propre système). Il doit fournir plus de code pour que quiconque puisse évaluer ses réclamations. – willaien

+0

Hmmm ... Il semble que OPs RAM/architecture est le problème. – displayName

3

Il est difficile de répondre sans le code, la connaissance de votre mémoire principale et de votre architecture. Par conséquent je ne peux que deviner quelques pointeurs importants:

  1. Avez-vous assez de RAM? Directement, si vous faites référence à une adresse qui n'a pas encore été chargée dans la RAM, une erreur de page se produit dans les coulisses et lit les données dans la RAM pour vous. Votre programme ne remarque pas cette activité car votre thread est suspendu pendant le traitement de l'erreur de page. Bon article here.
  2. Un autre point important du même article - Vous n'avez aucun contrôle sur combien de MMF est conservé en mémoire ou pendant combien de temps. Cela signifie que l'utilisation d'un fichier MMF peut faire sortir d'autres éléments de la RAM, tels que du code ou des pages de données dont vous aurez besoin "bientôt". Cela entraîne une exécution plus lente. Je tiens particulièrement à pointer toute personne lisant cette réponse à another answer here, de sorte que nous avons une idée claire de la façon dont lente cette lenteur est en termes de cycles de processeur.
  3. Ensuite, vous créez un flux. Streams bon pour l'accès séquentiel pendant que vous pourriez être en train d'essayer de lire/écrire au hasard.

En ce qui concerne la course de bout en bout le temps de votre code dans FileStream vs approche MMF, je pense que vous devriez exécuter les tests à nouveau parce que l'exécution de votre première approche pourrait résultat dans un cache réchauffé pour la deuxième un. Les résultats ne seront pas corrects alors.

Selon le MSDN documentation of MMF,

fichiers mappés en mémoire permettent aux programmeurs de travailler avec de très grands fichiers parce que la mémoire peut être géré en même temps, et ils permettent un accès complet, aléatoire dans un fichier sans avoir besoin de cherchant.

La façon dont fonctionne le MMF est que l'ensemble (ou une partie) du fichier est mappé en tant que mémoire virtuelle, qui est recherchée dans et hors de la mémoire par le système d'exploitation transparente que vous accéder aux portions du fichier.C'est pourquoi les fichiers MMF sont bons pour travailler avec des fichiers volumineux en premier lieu.

Vous pouvez être plus intelligent et lire une partie de l'ensemble du dossier et effectuer un accès aléatoire en utilisant:

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

afin que vous ayez accès à une vue avec décalage spécifié et la taille, de votre fichier mammouth de cartographie de la mémoire.