我通过端口和接收器将15个异步操作链接在一起。这让我非常关心线程间消息传递时间,特别是在任务发布数据到端口之间花费的时间,并且新任务开始在不同线程上处理同一数据。假设每个线程在启动时都处于空闲状态,我已经生成了一个测试,它使用stop watch类来测量两个不同调度器的时间,每个调度器使用单个线程以最高优先级运行。线程通信时间
我发现令我吃惊的是,我的开发平台是运行Windows 7 x64的Q6600四核2.4 Ghz计算机,我测试的平均上下文切换时间为5.66微秒,标准偏差为5.738微秒,最大值为接近1.58毫秒(282倍!)。秒表频率是427.7纳秒,所以我仍然远离传感器噪音。
我想要做的就是减少线程间通讯的时间尽可能多地,同样重要的是,减少上下文切换的标准偏差。我意识到Windows不是一个实时操作系统,并没有保证,但Windows调度器是一个公平的基于轮询优先级的时间表,并且这个测试中的两个线程都处于最高优先级(唯一的线程应该是高),所以不应该在线程上进行任何上下文切换(通过1.58 ms最大时间显而易见......我相信windows quanta是15.65 ms?)我唯一能想到的是操作系统调用时间的变化到CCR用于在线程之间传递消息的锁定机制。
请让我知道是否有人在那里已经测量线程间通讯的时间,并且对如何改善它的任何建议。
这里是我的测试的源代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Microsoft.Ccr.Core;
using System.Diagnostics;
namespace Test.CCR.TestConsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting Timer");
var sw = new Stopwatch();
sw.Start();
var dispatcher = new Dispatcher(1, ThreadPriority.Highest, true, "My Thread Pool");
var dispQueue = new DispatcherQueue("Disp Queue", dispatcher);
var sDispatcher = new Dispatcher(1, ThreadPriority.Highest, true, "Second Dispatcher");
var sDispQueue = new DispatcherQueue("Second Queue", sDispatcher);
var legAPort = new Port<EmptyValue>();
var legBPort = new Port<TimeSpan>();
var distances = new List<double>();
long totalTicks = 0;
while (sw.Elapsed.TotalMilliseconds < 5000) ;
int runCnt = 100000;
int offset = 1000;
Arbiter.Activate(dispQueue, Arbiter.Receive(true, legAPort, i =>
{
TimeSpan sTime = sw.Elapsed;
legBPort.Post(sTime);
}));
Arbiter.Activate(sDispQueue, Arbiter.Receive(true, legBPort, i =>
{
TimeSpan eTime = sw.Elapsed;
TimeSpan dt = eTime.Subtract(i);
//if (distances.Count == 0 || Math.Abs(distances[distances.Count - 1] - dt.TotalMilliseconds)/distances[distances.Count - 1] > 0.1)
distances.Add(dt.TotalMilliseconds);
if(distances.Count > offset)
Interlocked.Add(ref totalTicks,
dt.Ticks);
if(distances.Count < runCnt)
legAPort.Post(EmptyValue.SharedInstance);
}));
//Thread.Sleep(100);
legAPort.Post(EmptyValue.SharedInstance);
Thread.Sleep(500);
while (distances.Count < runCnt)
Thread.Sleep(25);
TimeSpan exTime = TimeSpan.FromTicks(totalTicks);
double exMS = exTime.TotalMilliseconds/(runCnt - offset);
Console.WriteLine("Exchange Time: {0} Stopwatch Resolution: {1}", exMS, Stopwatch.Frequency);
using(var stw = new StreamWriter("test.csv"))
{
for(int ix=0; ix < distances.Count; ix++)
{
stw.WriteLine("{0},{1}", ix, distances[ix]);
}
stw.Flush();
}
Console.ReadKey();
}
}
}
你为什么说“线程中不应该有任何上下文切换”?我能做到的唯一方法就是如果你能以某种方式保证线程独占使用核心。从我对CCR文档的简要介绍中,我没有发现任何可以做到这一点的功能。 – sipwiz 2009-09-02 07:04:02
你是对的 - 它不是保证,但是以最高优先级运行,唯一可能中断线程的是内核中断,或者以最高优先级运行的另一个进程(本应该不是这样)... – Superman 2009-09-02 15:06:02
您无法明确更改上下文切换的标准偏差。这取决于太多因素。内核也会使用CPU和其他进程。 – user224579 2009-09-30 07:55:24