脚本.字典性能在多个进程中受到影响
本文关键字:进程 受到影响 字典 性能 脚本 | 更新日期: 2023-09-27 18:12:48
为了说明这个问题,编译一个引用Microsoft Scripting Runtime的c#项目,以及下面的代码。运行结果可执行文件的单个实例。在我的12核机器上,读取循环始终花费大约180ms。启动可执行文件的另一个实例会减慢这一速度,每个额外的可执行文件大约减少100毫秒。
知道是怎么回事吗?除了切换到不同的字典实现之外,还有其他解决方案吗?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Stopwatch stp = new System.Diagnostics.Stopwatch();
var dict = (Scripting.IDictionary)(new Scripting.Dictionary());
stp.Start();
for (int i = 1; i < 1000; ++i)
{
Object s = i.ToString();
dict.Add(ref s, ref s);
}
Console.WriteLine("After Add {0}", stp.ElapsedMilliseconds);
object q = null;
for (int j = 0; j < 1000; ++j)
{
long old = stp.ElapsedMilliseconds;
for (int i = 1; i < 10000; ++i)
{
q = null;
object s = i.ToString() as object;
q = dict.get_Item(ref s);
}
long newval = stp.ElapsedMilliseconds;
Console.WriteLine("After Retrieve {0}", newval - old);
}
}
}
}
Eric,你会很高兴听到这个问题不是脚本所特有的。字典,而不是使用Apartment线程模型。人们可以在MSDN上读到关于混合线程模型对性能的影响,但是(对我来说)令人惊讶的是进程外的影响。
我能够用一个方法创建我自己的COM对象,如下所述,取代脚本。上面示例中的Dictionary调用。然后我可以在测试中切换"公寓"answers"两者"线程模型。rgs文件,重新构建,并确认在启用mta的对象中解决了跨进程影响。
此外,附加一个调试器并暂停进程,然后使用procexp(来自Microsoft SysInternals),可以看到调用堆栈进入内核,我假设有一个队列正在管理COM编组,导致不同进程之间的瓶颈。
更糟糕的是,当编组对不同对象的调用时也会出现这种减速,这可以通过运行一个调用脚本的应用程序来观察到。字典,几个人调用DoNothing(),然后看着他们慢下来。
出于我们的目的,我们将使用另一种字典实现(尽管可以更改脚本)。字典线程模型,这似乎不明智)。
我想COM编组的进程间影响仍然是一个悬而未决的问题。建议必须尽量避免在多进程环境中使用公寓线程,除非有人有更好的答案…?
创建测试COM对象
- 在Visual Studio中创建一个新项目,使用c++ ATL模板(我使用的是VS 2008)。
- 选择服务器类型DLL
- 右键单击项目,添加类…-> ATL简单对象。
- 给它一个简短的名字,例如:"测试",确保公寓线程被选中。
- 在类视图中,右键单击接口(ITest),添加方法…
- 方法名称,例如:" dononothing ",并保留默认选项。
- 检查方法实现是否为空,然后构建。
现在可以从测试应用程序中添加COM引用并调用DoNothing()方法。