Использование многопоточности для ускорения отражения .NET - PullRequest
2 голосов
/ 04 мая 2009

Мой ПК имеет двухъядерный процессор, и мне было интересно - можно ли сократить время отражения .NET в два раза, если я начну обработку в двух потоке.

Под «обработкой» я подразумевал следующее:

1. загрузка сборки 2. получение всех типов из него (.GetTypes ()) 3. обработка этих типов 4. запрашивая эти типы для методов и т.д.

Если да - какая будет наилучшая (с точки зрения производительности) стратегия:

  1. загрузить все сборки в один поток, затем обработать metainfo в двух параллельных потоках
  2. загрузка и обработка каждой сборки в отдельном потоке

Ответы [ 3 ]

3 голосов
/ 04 мая 2009

Есть несколько вещей, которые нужно иметь в виду:

  • Запуск нового потока стоит дорого, поэтому, если задача недолговечна, накладные расходы могут быть чрезмерными. Используя пул потоков вместо запуска своих собственных потоков, пул потоков обязательно использует потоки в меру своих возможностей. Однако запуск множества задач за короткое время не дает наилучшего результата при текущей реализации пула потоков.

  • Поскольку ваша конкретная задача включает в себя некоторые операции ввода-вывода, которые, вероятно, будут самой дорогой частью операции. Отключение нескольких потоков для ожидания ввода-вывода может не привести к повышению производительности. Вы не можете сказать, пока не измерите это.

  • Если вы храните данные в общем хранилище или выводите их в файл / на экран, вам придется синхронизироваться вокруг этого. Это, очевидно, уменьшает параллелизм.

1 голос
/ 04 мая 2009

Если вы не имеете дело с абсолютно массивными библиотеками, загрузка отражений не слишком медленная, по моему опыту. Вполне возможно, что это пустая трата вашего времени.

Тем не менее, ознакомьтесь с ThreadPool.QueueUserWorkItem, который упрощает эту работу

foreach (Assembly a in "folder/something") {
    ThreadPool.QueueUserWorkItem((object assem) => {
        // do work
    }, a);
}
1 голос
/ 04 мая 2009

Загрузка и обработка каждой сборки в отдельном потоке происходит быстрее. Но только немного быстрее. Например, вы получите намного лучший пробег, кэшируя MethodInfos.

Я бы поставил под сомнение необходимость такой оптимизации.

Результаты:

warm up single threaded Time Elapsed 465 ms
multi threaded Time Elapsed 173 ms
single threaded Time Elapsed 456 ms
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Diagnostics;

namespace ConsoleApplication12 {
    class Program {


        static void TimeAction(string description, Action func) {
            var watch = new Stopwatch();
            watch.Start();
            func();
            watch.Stop();
            Console.Write(description);
            Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
        }

        static void Main(string[] args) {

            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            // warm up 
            TimeAction("warm up single threaded", () =>
            {
                foreach (var assembly in assemblies) {
                    assembly.GetTypes().Select(type => type.GetMethods()).ToArray();
                }

            });

            List<Thread> threads = new List<Thread>();

            TimeAction("multi threaded", () => {
                foreach (var assembly in assemblies) {
                    Thread t = new Thread(new ThreadStart( () => 
                        assembly.GetTypes().Select(type => type.GetMethods()).ToArray()
                        ));
                    t.Start();
                    threads.Add(t);
                }

                foreach (var thread in threads) {
                    thread.Join();
                }
            });

            TimeAction("single threaded", () =>
            {
                foreach (var assembly in assemblies) {
                    assembly.GetTypes().Select(type => type.GetMethods()).ToArray();
                }

            });

            Console.ReadKey();
        }
    }
}
...