Лучший способ создать много маленьких файлов?
Я хочу как можно быстрее создать много (1 миллион) маленьких файлов, вот что я делаю сейчас:
for(long i = 0; i < veryVeryLong; i++){
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None)) {
byte[] bytes = GetFileContent(i); // no matter
fs.Write(bytes, 0, bytes.Length);
}
}
Могу ли я ускорить?
ОБНОВИТЬ
roomaroo правильно, мне нужно использовать Parallel, но я объединил его со своей функцией, и это дает намного лучший результат. Код:
Parallel.For(0, veryVeryLogn, (i) => {
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None)) {
byte[] bytes = GetFileContent(i); // no matter
fs.Write(bytes, 0, bytes.Length);
}
});
1 ответ
Как предложил ChrisBint, используйте параллельный цикл.
Я создал три метода для записи файлов (код ниже). Один использует ваш код выше, другой использует File.WriteAllBytes(...) - оба они используют традиционный цикл for.
Третья реализация использовала параллель для цикла.
Вот время, чтобы создать 1000 файлов:
FileStream: 2658мс
File.WriteAllBytes: 2555мс
Parallel.For: 617мс
Таким образом, параллельный цикл в четыре раза быстрее, чем самая медленная реализация. Очевидно, что это будет отличаться на разных аппаратных средствах, и ваши результаты будут очень сильно зависеть от вашего процессора и диска.
Вот код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;
namespace FileCreator
{
class Program
{
static void Main(string[] args)
{
string folder = @"d:\temp";
Clean(folder);
CreateWithParallelFileWriteBytes(folder);
Clean(folder);
CreateWithFileStream(folder);
Clean(folder);
CreateWithFileWriteBytes(folder);
}
private static void Clean(string folder)
{
if (Directory.Exists(folder))
{
Directory.Delete(folder, true);
}
Directory.CreateDirectory(folder);
}
private static byte[] GetFileContent(int i)
{
Random r = new Random(i);
byte[] buffer = new byte[1024];
r.NextBytes(buffer);
return buffer;
}
private static void CreateWithFileStream(string folder)
{
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
string path = Path.Combine(folder, string.Format("file{0}.dat", i));
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None))
{
byte[] bytes = GetFileContent(i);
fs.Write(bytes, 0, bytes.Length);
}
}
Console.WriteLine("Time for CreateWithFileStream: {0}ms", sw.ElapsedMilliseconds);
}
private static void CreateWithFileWriteBytes(string folder)
{
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
string path = Path.Combine(folder, string.Format("file{0}.dat", i));
File.WriteAllBytes(path, GetFileContent(i));
}
Console.WriteLine("Time for CreateWithFileWriteBytes: {0}ms", sw.ElapsedMilliseconds);
}
private static void CreateWithParallelFileWriteBytes(string folder)
{
var sw = new Stopwatch();
sw.Start();
Parallel.For(0, 1000, (i) =>
{
string path = Path.Combine(folder, string.Format("file{0}.dat", i));
File.WriteAllBytes(path, GetFileContent(i));
});
Console.WriteLine("Time for CreateWithParallelFileWriteBytes: {0}ms", sw.ElapsedMilliseconds);
}
}
}