Je crée une méthode en C # qui génère un fichier texte pour un Google Product Feed . Le flux contiendra plus de 30 000 enregistrements et le fichier texte pèse actuellement à ~ 7 Mo.
Voici le code que j'utilise actuellement (certaines lignes ont été supprimées par souci de concision).
public static void GenerateTextFile(string filePath) {
var sb = new StringBuilder(1000);
sb.Append("availability").Append("\t");
sb.Append("condition").Append("\t");
sb.Append("description").Append("\t");
// repetitive code hidden for brevity ...
sb.Append(Environment.NewLine);
var items = inventoryRepo.GetItemsForSale();
foreach (var p in items) {
sb.Append("in stock").Append("\t");
sb.Append("used").Append("\t");
sb.Append(p.Description).Append("\t");
// repetitive code hidden for brevity ...
sb.AppendLine();
}
using (StreamWriter outfile = new StreamWriter(filePath)) {
result.Append("Writing text file to disk.").AppendLine();
outfile.Write(sb.ToString());
}
}
Je me demande si StringBuilder est le bon outil pour le travail. Y aurait-il des gains de performances si j'utilisais plutôt un TextWriter?
Je ne connais pas beaucoup les performances de IO donc toute aide ou amélioration générale serait appréciée. Merci.
Les opérations d'E/S sur les fichiers sont généralement bien optimisées dans les systèmes d'exploitation modernes. Vous ne devriez pas essayer d'assembler la chaîne entière du fichier en mémoire ... écrivez-la simplement morceau par morceau. FileStream
se chargera de la mise en mémoire tampon et d'autres considérations de performances.
Vous pouvez effectuer ce changement facilement en déplaçant:
using (StreamWriter outfile = new StreamWriter(filePath)) {
en haut de la fonction, et se débarrasser de l'écriture StringBuilder
directement dans le fichier.
Il y a plusieurs raisons pour lesquelles vous devriez éviter de créer de grandes chaînes en mémoire:
StringBuilder
doit augmenter sa capacité lorsque vous y écrivez, ce qui entraîne une réallocation et une copie de la mémoire.StringBuilder
dans un fichier, vous devez utiliser ToString()
qui double efficacement la consommation de mémoire du processus car les deux copies doivent être en mémoire pendant un certain temps. Cette opération peut également échouer si votre espace d'adressage est suffisamment fragmenté, de sorte qu'un seul bloc de mémoire contigu ne peut pas être alloué.Déplacez simplement l'instruction using
pour qu'elle englobe l'ensemble de votre code et écrivez directement dans le fichier. Je ne vois aucun intérêt à tout garder en mémoire en premier.
Écrivez une chaîne à la fois à l'aide de StreamWriter.Write plutôt que de tout mettre en cache dans un StringBuilder.