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;
}
}
Code: Select all
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);
}
Die Ertragsrendite In Partitionfiles verursacht einen Leistungs Engpass. Die Foreach in ProcessFileBatchesoptimizedAsync wartet zu lang auf den Partitioner, und ironischerweise werden die Dateiverarbeitungsaufgaben schneller als Chargen erzeugt. 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 Methode, um 2–3 Millionen Dateien gleichzeitig zu scannen und zu verarbeiten, und vermeiden Sie den Ertragsgnett, ohne alle Pfade in das Gedächtnis zu laden? ExtractFilemetadataandsavetoDB Ich verarbeite hauptsächlich jede Stapel für 10K -Dateien, um die Metadaten von Dateien zu erhalten, wie, nennen, erstellen, modifiziertes Datum erstellen, modifiziertes Datum erstellen, usw. Ich verwende BulkcopyAsync , um sie in einer Stapel von 5k auf DB zu drücken.