2

我的 PC 有一个双核 CPU,我想知道 - 如果我开始在两个线程中处理,是否可以将 .NET 反射时间减少两倍。

我所说的“处理”是指以下内容:

1.加载程序集 2.从中取出所有类型 (.GetTypes()) 3.处理这些类型 4.查询这些类型的方法等。

如果是 - 最好的(性能方面)策略是什么:

  1. 在一个线程中加载所有程序集,然后在两个并发线程中处理元信息
  2. 在自己的线程中加载和处理每个程序集
4

3 回答 3

3

有几件事要记住:

  • 启动一个新线程是昂贵的,所以如果任务是短暂的,开销可能会令人望而却步。通过使用线程池而不是启动您自己的线程,线程池将确保尽其所能重用线程。但是,在短时间内启动大量任务并不能产生当前线程池实现的最佳结果。

  • 由于您的特定任务涉及一些 I/O,这可能是操作中最昂贵的部分。分叉几个线程来等待 I/O 可能不会产生更好的性能。直到你测量它,你才能真正知道。

  • 如果您将数据存储在共享存储库中或输出到文件/屏幕,则必须围绕它进行同步。这显然降低了并发性。

于 2009-05-04T05:35:57.970 回答
1

在单独的线程中加载和处理每个程序集更快。但只是快一点。例如,您将通过缓存 MethodInfos 获得更好的里程数。

不过,我会质疑这种优化的必要性。

结果:

预热单线程时间经过 465 毫秒
多线程耗时 173 毫秒
单线程耗时 456 毫秒
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();
        }
    }
}
于 2009-05-04T04:19:24.550 回答
1

除非您正在处理绝对庞大的库,否则根据我的经验,反射加载并不是一件非常缓慢的事情。这可能会浪费你的时间。

尽管如此,请查看 ThreadPool.QueueUserWorkItem,让这些事情变得简单。

foreach (Assembly a in "folder/something") {
    ThreadPool.QueueUserWorkItem((object assem) => {
        // do work
    }, a);
}
于 2009-05-04T04:21:09.227 回答