Как оптимизировать производительность одновременной записи файлов в C#
Я пытаюсь оптимизировать производительность, создавая множество маленьких файлов на SSD-диске.
ConcurrentBag<string[]> cb = new ConcurrentBag<string[]>();
cb.AsParallel().ForAll(fa => File.WriteAllText(fa[0], fa[1]));
Общее количество ConcurrentBag<string[]>
= 80048, cb.Sum(gbc => Encoding.UTF8.GetByteCount( gbc[1] ) );
возвращает 393441217 байт.
Где-то еще я делаю xml.Save();
, который создает файл ~750MB.
Первая ситуация занимает 3 минуты и 30 секунд. Вторые 20 секунд.
Я понимаю, что есть некоторые накладные расходы для обработки всех отдельных операций записи, но 3 минуты и 30 секунд все еще кажутся немного длинными. Я уже пробовал распараллеливание с помощью forall, что помогло довольно хорошо (до этого требовалось 6-8 минут). Какие еще модификации я могу добавить в свой код, чтобы оптимизировать производительность массового создания файла?
2 ответа
На самом деле, несколько одновременных операций ввода-вывода могут сильно замедлить процесс, особенно на традиционных дисках. Я рекомендую использовать ConcurrentQueue
для записи нескольких файлов.
Также вы можете переключиться на StreamWriter
и контролировать размер буфера для увеличения скорости записи:
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]);
}
}
}
Вы должны также попытаться использовать ForEach вместо ForAll. Вы можете найти некоторые веские причины в посте http://reedcopsey.com/2010/02/03/parallelism-in-net-part-8-plinqs-forall-method/
почтовая директива
Метод расширения ForAll следует использовать только для обработки результатов параллельного запроса, возвращаемого выражением PLINQ.