以下代码大约运行 2.5 秒:
static void Main(string[] args)
{
var service = new Service();
Parallel.For(0, 100, i => {
dynamic user = new ExpandoObject();
user.data = new ExpandoObject();
user.data.id = i;
user.data.name = "User Name";
var parsed = service.Parse(user);
});
}
public class Service
{
public User Parse(dynamic dynamicUser)
{
if (dynamicUser.data != null)
{
return new User
{
Id = dynamicUser.data.id,
Name = dynamicUser.data.name
};
}
return null;
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
但是,如果我将 Parallel.For() 循环更改为简单的 For 循环,它会在大约 200 毫秒内运行:
for (var i = 0; i < 100; i++)
所以我的问题是,为什么并行运行时会慢很多?
我的理论是,解析每个线程完成一次的动态对象会产生一些开销。在简单循环中,DLR 第一次执行它的操作,然后不需要为每个后续调用执行操作。
但同时,DLR 的开销发生在每次调用中。
这是一个正确的假设,还是我离题太远了?
最佳答案
我怀疑您被诊断误导了。特别是,如果运行一个循环 100 次需要 2.5 秒,那真的非常非常慢。这是在调试器下吗?
这是我的盒子上的结果,代码是用 /o+
编译的,然后在控制台中运行。请注意,我在每个测试中运行 1,000,000 次循环迭代。
Void ExecuteParallel(): 00:00:00.7311773
Void ExecuteSerial(): 00:00:02.0514120
Void ExecuteParallel(): 00:00:00.6897816
Void ExecuteSerial(): 00:00:02.0389325
Void ExecuteParallel(): 00:00:00.6754025
Void ExecuteSerial(): 00:00:02.0653801
Void ExecuteParallel(): 00:00:00.7136330
Void ExecuteSerial(): 00:00:02.0477593
Void ExecuteParallel(): 00:00:00.6742260
Void ExecuteSerial(): 00:00:02.0476146
它并没有像您对四核 i7 的期望那样那么并行,但我怀疑这是由于 Servy 提到的上下文切换等 - 也可能是对执行缓存的争用在 DLR 中。不过,它比串联运行要快。
亲自尝试代码,看看您在机器上得到了什么 - 但不是在调试器下。
代码:
using System;
using System.Diagnostics;
using System.Dynamic;
using System.Threading.Tasks;
class Test
{
const int Iterations = 1000000;
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
RunTest(ExecuteParallel);
RunTest(ExecuteSerial);
}
}
static void RunTest(Action action)
{
var sw = Stopwatch.StartNew();
action();
sw.Stop();
Console.WriteLine("{0}: {1}", action.Method, sw.Elapsed);
}
static void ExecuteParallel()
{
var service = new Service();
Parallel.For(0, Iterations, i => {
dynamic user = new ExpandoObject();
user.data = new ExpandoObject();
user.data.id = i;
user.data.name = "User Name";
var parsed = service.Parse(user);
});
}
static void ExecuteSerial()
{
var service = new Service();
for (int i = 0; i < Iterations; i++)
{
dynamic user = new ExpandoObject();
user.data = new ExpandoObject();
user.data.id = i;
user.data.name = "User Name";
var parsed = service.Parse(user);
}
}
}
public class Service
{
public User Parse(dynamic dynamicUser)
{
if (dynamicUser.data != null)
{
return new User
{
Id = dynamicUser.data.id,
Name = dynamicUser.data.name
};
}
return null;
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
关于c# - 动态对象的并行性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12981692/