Code: Select all
var fileBatches = PartitionFiles(Directory.EnumerateFiles(scanPath, "*", SearchOption.AllDirectories), 10000);
await ProcessFileBatchesOptimizedAsync(fileBatches, cancellationToken);
Code: Select all
private static IEnumerable PartitionFiles(IEnumerable files, int batchSize)
{
List batch = new List(batchSize);
foreach (var file in files)
{
batch.Add(file);
if (batch.Count >= batchSize)
{
yield return batch;
batch = new List(batchSize);
}
}
if (batch.Count > 0)
{
yield return batch;
}
}
private async Task ProcessFileBatchesOptimizedAsync(IEnumerable fileBatches, CancellationToken cancellationToken)
{
List tasks = new List();
foreach (var fileBatch in fileBatches)
{
tasks.Add(Task.Run(async () =>
{
await ExtractFileMetadataAndSaveToDB(fileBatch);
}, cancellationToken));
}
await Task.WhenAll(tasks);
}
< /code>
Problem: < /strong>
Die Ertragsrendite in Partitionsfiles verursacht einen Leistungs Engpass. Die Foreach in ProcessFileBatchesoptimizedAsync wartet zu lange auf den Partitioner, und ironischerweise werden die Dateiverarbeitungsaufgaben schneller abgeschlossen als Chargen. Dies führt dazu, dass Aufgaben fast nacheinander ausgeführt werden und den Zweck der Parallelität besiegen. Eine ähnliche Leistung, wie der Produzent (Batching -Dateien) langsamer ist als der Verbraucher (verarbeitet sie). Schlechtere Leistung aufgrund von zweistufiger Verzeichnisabruf und dann Dateiabruf. Leichte Verbesserung, aber hoher Speicherverbrauch, der bei Millionen von Dateien problematisch sein könnte. /> Fragen Sie: < /strong>
Was ist eine effizientere Möglichkeit, 2–3 Mio. Dateien gleichzeitig zu scannen und zu verarbeiten, und vermeiden Sie den Ertragsgutgpass, ohne alle Pfade in den Speicher zu laden.>