2015-08-04 1 views
0

J'essaie d'optimiser les performances de création de nombreux petits fichiers sur un disque SSD.Comment optimiser les performances d'écriture de fichiers simultanés C#

ConcurrentBag<string[]> cb = new ConcurrentBag<string[]>(); 
cb.AsParallel().ForAll(fa => File.WriteAllText(fa[0], fa[1])); 

Nombre total de ConcurrentBag<string[]> = 80048, cb.Sum(gbc => Encoding.UTF8.GetByteCount(gbc[1])); retourne 393441217 octets.

Quelque part, je fais un xml.Save();, ce qui crée un fichier ~ 750MB.

La première situation prend 3 minutes et 30 secondes. Les 20 secondes suivantes. Je comprends qu'il y a une surcharge pour gérer toutes les opérations d'écriture séparées, mais 3 minutes et 30 secondes semblent encore un peu longues. J'ai déjà essayé la parallélisation avec forall, ce qui a aidé assez bien (auparavant cela prenait entre 6 et 8 minutes pour terminer). Quelles autres modifications puis-je ajouter à mon code pour optimiser les performances de la création de fichiers en bloc?

Répondre

1

En fait, plusieurs opérations E/S simultanées peuvent ralentir considérablement les choses, en particulier sur les disques traditionnels. Je recommande d'utiliser ConcurrentQueue pour écrire plusieurs fichiers.

Aussi, vous pouvez passer à StreamWriter et la taille de la mémoire tampon de commande pour augmenter la vitesse d'écriture:

ConcurrentQueue<string[]> concurrentQueue = new ConcurrentQueue<string[]>(); 

    // populate with some data 
    for (int i = 0; i < 5000; i++) 
    { 
     concurrentQueue.Enqueue(new string[] { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }); 
    } 

    while (true) 
    { 
     string[] currentElement; 
     bool success = concurrentQueue.TryDequeue(out currentElement); 
     if (success) 
     { 
      const int BufferSize = 65536; // change it to your needs 
      using (var sw = new StreamWriter(currentElement[0], true, Encoding.UTF8, BufferSize)) 
      { 
       sw.Write(currentElement[1]); 
      } 
     } 
    } 
+0

Comment déterminer la taille de tampon appropriée? Ce n'est pas un disque traditionnel mais un SSD, si cela devait être déterminé en premier ... Avez-vous un exemple de concurrence avec File.WriteAllText ou StreamWriter? J'ai aussi essayé avec buffersize = 16384 (4 * par défaut) mais cela a causé une exception à la mémoire négative – BigChief

+1

Je vous encourage toujours à passer à ConcurrentQueue, je mettrai à jour ma réponse avec un exemple. Les SSD sont également affectés (mais beaucoup moins). Voir https://technet.microsoft.com/en-us/library/cc938632.aspx et http://stackoverflow.com/questions/8803515/optimal-buffer-size-for-write2 –

+1

J'ai modifié ma réponse –

1

vous devriez aussi essayer d'utiliser ForEach au lieu du PourTout. vous pouvez trouver quelques bonnes raisons dans le poste http://reedcopsey.com/2010/02/03/parallelism-in-net-part-8-plinqs-forall-method/

la ligne directrice de poste est

La méthode d'extension PourTout ne doit être utilisé pour traiter les résultats d'une requête parallèle, retourné par une expression PLINQ

+0

Nice post , J'ai aussi essayé foreach mais forall semble être un peu plus rapide ... – BigChief