. NET PLINQ против Asyn c Производительность - PullRequest
0 голосов
/ 27 апреля 2020

Учитывая этот код PLINQ:

        public static IEnumerable<Tuple<string, string>> PlinqFileProcessingLimitedCores(int nr_of_cores) 
    {
        string archiveDirectory = @"C:\Dotnet46Examples";

        return (from file in Directory.EnumerateFiles(archiveDirectory, "*.cs", SearchOption.AllDirectories)
                from line in File.ReadLines(file).AsParallel().WithDegreeOfParallelism(nr_of_cores)
                where line.Contains("Console")
                select new Tuple<string, string>(file, line));
    }

, который возвращает все строки всех файлов, содержащих слово Console.

Я пытался писать более быстрые асинхронные версии, однако все они оказались значительно медленнее, чем PLINQ, например:

        public static async Task<ConcurrentBag<Tuple<string, string>>> FileProcessingAsync()
    {
        string archiveDirectory = @"C:\Dotnet46Examples";
        var bag = new ConcurrentBag<Tuple<string, string>>();
        var tasks = Directory.EnumerateFiles(archiveDirectory, "*.cs", SearchOption.AllDirectories)
               .Select(file => ProcessFileAsync(bag, file));
        await Task.WhenAll(tasks);  
        return bag;
    }

        static async Task ProcessFileAsync(ConcurrentBag<Tuple<string, string>> bag, string file)
    {
        String line;
        using (StreamReader reader = File.OpenText(file))
        {
            while (reader.Peek() >= 0)
            {
                line = await reader.ReadLineAsync(); 
                if (line != null)
                {
                    if (line.Contains("Console"))
                    {
                        bag.Add(new Tuple<string, string>(file, line));
                    }
                }
            }        
        }
    }

Почему асин c код намного медленнее (коэффициент 1000 на моем ноутбуке)? Как выглядит лучший код? Проблема не подходит для asyn c? ТНХ

1 Ответ

3 голосов
/ 27 апреля 2020

Ваш параллельный пример (синхронно) - чтение файла в память по одной строке за раз и (параллельно) поиск текста. Это, пожалуй, самое быстрое из доступных решений, потому что часто синхронный файловый ввод / вывод на Windows выполняется быстрее, чем асинхронный.

Я пытался писать более быстрые версии асинхронного

"Асинхронный "не означает" быстрее ". Это означает «не блокирует вызывающий поток». Есть дополнительные издержки с асинхронным кодом, поэтому он обычно медленнее . Преимущество асинхронного кода не в скорости; это освобождает темы. Это только преимущество, если у этих потоков есть другая работа; например, в серверной среде они могут обрабатывать другие запросы.

Существует также проблема, заключающаяся в том, что такие методы, как File.OpenText, фактически не разрешают асинхронный доступ, поэтому на самом деле ReadLineAsync выполняет синхронную работу над пул потоков, а затем обрабатывать его асинхронно. Но даже если бы у вас была правильная асинхронная реализация, это не было бы быстрее, чем синхронное чтение файла.

...