Konsolenanwendung hat 3 Threads: Main, T1, T2. Ziel ist es, ‚Signal‘ sowohl T1, T2 (und lassen Sie sie einige Arbeit tun) aus dem Haupt-Thread in der niedrigsten Latenzzeit wie möglich (us)Kommunikation mit niedriger Latenz zwischen Threads im selben Prozess
HINWEIS:
- bitte ignorieren Bammel , GC usw. (ich kann damit umgehen)
- ElapsedLogger.WriteLine Anrufkosten unter 50 ns (Nano sec)
einen Blick auf den Code unten haben:
Probe 1
class Program
{
private static string msg = string.Empty;
private static readonly CountdownEvent Countdown = new CountdownEvent(1);
static void Main(string[] args)
{
while (true)
{
Countdown.Reset(1);
var t1 = new Thread(Dowork) { Priority = ThreadPriority.Highest };
var t2 = new Thread(Dowork) { Priority = ThreadPriority.Highest };
t1.Start();
t2.Start();
Console.WriteLine("Type message and press [enter] to start");
msg = Console.ReadLine();
ElapsedLogger.WriteLine("Kick off!");
Countdown.Signal();
Thread.Sleep(250);
ElapsedLogger.FlushToConsole();
}
}
private static void Dowork()
{
string t = Thread.CurrentThread.ManagedThreadId.ToString();
ElapsedLogger.WriteLine("{0} - Waiting...", t);
Countdown.Wait();
ElapsedLogger.WriteLine("{0} - Message received: {1}", t, msg);
}
}
Output:
Type message and press [enter] to start
test3
20141028 12:03:24.230647|5 - Waiting...
20141028 12:03:24.230851|6 - Waiting...
20141028 12:03:30.640351|Kick off!
20141028 12:03:30.640392|5 - Message received: test3
20141028 12:03:30.640394|6 - Message received: test3
Type message and press [enter] to start
test4
20141028 12:03:30.891853|7 - Waiting...
20141028 12:03:30.892072|8 - Waiting...
20141028 12:03:42.024499|Kick off!
20141028 12:03:42.024538|7 - Message received: test4
20141028 12:03:42.024551|8 - Message received: test4
In der obigen Code 'Latenz' ist 40-50μs herum. CountdownEvent Signalisierungsaufruf ist sehr billig (weniger als 50ns), aber T1, T2-Threads sind ausgesetzt und es braucht Zeit, um sie aufzuwecken.
Probe 2
class Program
{
private static string _msg = string.Empty;
private static bool _signal = false;
static void Main(string[] args)
{
while (true)
{
_signal = false;
var t1 = new Thread(Dowork) {Priority = ThreadPriority.Highest};
var t2 = new Thread(Dowork) {Priority = ThreadPriority.Highest};
t1.Start();
t2.Start();
Console.WriteLine("Type message and press [enter] to start");
_msg = Console.ReadLine();
ElapsedLogger.WriteLine("Kick off!");
_signal = true;
Thread.Sleep(250);
ElapsedLogger.FlushToConsole();
}
}
private static void Dowork()
{
string t = Thread.CurrentThread.ManagedThreadId.ToString();
ElapsedLogger.WriteLine("{0} - Waiting...", t);
while (!_signal) { Thread.SpinWait(10); }
ElapsedLogger.WriteLine("{0} - Message received: {1}", t, _msg);
}
}
Output:
Type message and press [enter] to start
testMsg
20141028 11:56:57.829870|5 - Waiting...
20141028 11:56:57.830121|6 - Waiting...
20141028 11:57:05.456075|Kick off!
20141028 11:57:05.456081|6 - Message received: testMsg
20141028 11:57:05.456081|5 - Message received: testMsg
Type message and press [enter] to start
testMsg2
20141028 11:57:05.707528|7 - Waiting...
20141028 11:57:05.707754|8 - Waiting...
20141028 11:57:57.535549|Kick off!
20141028 11:57:57.535576|7 - Message received: testMsg2
20141028 11:57:57.535576|8 - Message received: testMsg2
Diesmal 'Latenz' ist 6-7μs herum. (aber hohe CPU) Dies ist, weil T1, T2 Threads sind gezwungen, aktiv zu sein (sie tun nichts nur CPU-Zeit zu verbrennen)
In 'echten' Anwendung kann ich CPU so drehen (Ich habe zu viele aktive Threads und es würde es schlimmer machen/langsamer oder sogar den Server töten).
Ist es etwas, was ich stattdessen verwenden kann, um die Latenz auf etwas um 10-15 μs zu reduzieren? Ich denke, mit Producer/Consumer-Muster ist es nicht schneller als mit CountdownEvent. Wait/Pulse ist auch teurer als CountdownEvent.
Was habe ich in Probe 1 die beste, die ich erreichen kann?
Irgendwelche Vorschläge?
Ich werde rohe Sockets auch versuchen, wenn ich eine Zeit habe.
Haben Sie 'ManualResetEventSlim' und' SemaphoreSlim' untersucht? Was ist mit "Monitor.Wait" und "Monitor.Pulse"? –
@JimMischel: Ich habe alle von ihnen versucht und das Ergebnis ist ziemlich das Gleiche. – Novitzky