简体   繁体   English

使用多线程加速.NET反射

[英]Using multi-threading to speed up .NET reflection

My PC have a dual core CPU and I was wondering - would it be possible to reduce .NET reflection times by two, if I start processing in a two thread. 我的PC具有双核CPU,我想知道-如果我开始在两个线程中进行处理,是否可以将.NET反射时间减少两个。

By "processing" I have meant the following: “处理”指的是:

1.loading the assembly 2.getting all types out of it (.GetTypes()) 3.processing these types 4.querying these types for methods etc. 1.加载程序集2.从中获取所有类型(.GetTypes())3.处理这些类型4.查询这些类型以获取方法等

If yes - what would be the best (performance-wise) strategy: 如果是,那么最佳的(性能方面)策略是什么:

  1. load all of the assemblies in a one thread then process metainfo in a two concurent threads 在一个线程中加载所有程序集,然后在两个并发线程中处理metainfo
  2. load and process each assembly in its own thread 在自己的线程中加载和处理每个程序集

There are a couple of things to keep in mind: 有两件事要牢记:

  • Starting a new thread is expensive, so if the task is short lived the overhead may be prohibitive. 启动新线程的开销很大,因此如果任务寿命短,那么开销可能会过高。 By using the Thread pool instead of starting your own threads, the thread pool will make sure to reuse threads to the best of its abilities. 通过使用线程池而不是启动自己的线程,线程池将确保最大程度地重用线程。 However, launching a lot of tasks in a short time doesn't yield the best result with the current thread pool implementation. 但是,使用当前的线程池实现,在短时间内启动许多任务并不能获得最佳结果。

  • Since your specific task involves some I/O that is probably going to be the most expensive part of the operation. 由于您的特定任务涉及一些I / O,因此可能会成为操作中最昂贵的部分。 Forking off several threads to wait for I/O may not yield better performance. 分叉多个线程以等待I / O可能不会产生更好的性能。 You can't really tell until you measure it. 在测量之前,您无法真正分辨出来。

  • If you're storing the data in a shared repository or outputting to a file/the screen, you'll have to synchronize around that. 如果要将数据存储在共享存储库中或输出到文件/屏幕,则必须进行同步。 This obviously reduces the concurrency. 这显然减少了并发性。

Loading and processing each assembly in a seperate thread is faster. 在单独的线程中加载和处理每个程序集更快。 But only a bit faster. 但是只有更快一点。 For example you will get much better milage by caching MethodInfos. 例如,通过缓存MethodInfos,您将获得更好的里程。

I would question the need for such an optimisation though. 我会质疑这种优化的必要性。

results: 结果:

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();
        }
    }
}

Unless you are dealing with absolutely massive libraries, reflection loading is not a terribly slow thing, in my experiences. 根据我的经验,除非您要处理绝对大量的库,否则反射加载并不是一件非常缓慢的事情。 It's possible that it would be a waste of your time. 可能会浪费您的时间。

Nonetheless, check out ThreadPool.QueueUserWorkItem, makes this stuff easy. 尽管如此,请签出ThreadPool.QueueUserWorkItem,使此操作变得容易。

foreach (Assembly a in "folder/something") {
    ThreadPool.QueueUserWorkItem((object assem) => {
        // do work
    }, a);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM