Ral*_*lfL 6 c# performance multithreading ipc wait-free
我是新手multitasking,IPC并且我正在尝试使用共享内存构建一种快速进程间通信的方法(起初我正在研究IPC术语,考虑到wcf sockets并且named pipes最终只发现MMF).
现在我已经通过使用Lock和EventWaitHandle信令在两个进程之间使用共享内存成功实现了一个小测试,我采用了一种实现非阻塞/无等待模式的方法.现在,我正在尝试结合Thread.MemoryBarrier()并阅读signalling Sector来自MemoryMapedFile.
问题是身份不明!第一轮通过,第二轮最后一个位于百慕大三角...超出了调试器的范围......
说过程中发送请求的突发的showMsg()来处理b.
//offset positions in mmf
MemoryMappedViewAccessor MmfAcc; const int opReady= 0, opCompleteRead = 4, .....
ReadTrd()
{
//[0,3] - Reader is stationed
//[4,7] - Read Complete successfully
//[8,11] - Data-size
//[12,15] - Reader-exiting
"format" the signals Section (write zeroes).
for(;;){if (WrTrd-StepMMF1 Confimed) break;}
MmfAcc- read DataSize val @offset[8]
MmfAcc- read Data val @offset[50]
MmfAcc Write exit to offset....
....heavy use of Thread.MemoryBarrier(); sets !!! (all over the place, on every shared variable...)
}
writeTrd()
{
heavy use of Thread.MemoryBarrier() !!!
//[15-19] - wr is stationed
//[20-23] - wr Complete successfully
//[24-27] - wrExiting
"format" the signals Section .
for(;;){if Reader-StepMMF1 is Confim break;}
MmfAcc- DataSize to offset[8]
write Data To offset[50] using the method below
for(;;){if Read StepMMF2 is Confim break;}
}
Run Code Online (Sandbox Code Playgroud)
当我第一次使用命名的管道解决方案时,与命名管道方法相比,Mmf方法(尽管Lock和事件等待处理)是很好的性能提升,但我还能以某种方式进一步使用上述方法吗?
我可以像条纹Raid那样克隆这个模式......
Reader1 + Reader2 & WriteThred1 + WriteThread2
Run Code Online (Sandbox Code Playgroud)
所以我试了一下,然后卡在那一点上.
这种有效的方法是使用全内存和共享内存进行信令吗?
如果是这样,剩下的就是看第二次迭代失败的原因,性能差异.
编辑 - 添加额外线程测试背后的逻辑
这是我用来操纵编写器线程的"桥"(读者使用相同的方法).
public void Write(byte[] parCurData)
{
if (ReadPosition < 0 || WritePosition < 0)
throw new ArgumentException();
this.statusSet.Add("ReadWrite:-> " + ReadPosition + "-" + WritePosition);
// var s = (FsMomitorIPCCrier)data;
////////lock (this.dataToSend)
////////{
Thread.MemoryBarrier();
LiveDataCount_CurIndex = dataQue.Where(i => i != null).Count();
this.dataQue[LiveDataCount_CurIndex] = parCurData;
Console.WriteLine("^^^^^" + Thread.CurrentThread.Name + " has Entered WritingThreads BRIDGE");
Console.WriteLine("^^^^^[transactionsQue] = {1}{0}^^^^^[dataQue.LiveDataASIndex = {2}{0}^^^^^[Current Requests Count = {3}{0}", "\r\n", Wtransactions, LiveDataCount_CurIndex, ++dataDelReqCount);
//this.itsTimeForWTrd2 = false;
if (Wtransactions != 0 && Wtransactions > ThrededSafeQ_Initial_Capcity - 1)
if (this.dataQueISFluded) this.DataQXpand();
if (itsTimeForWTrd2)
{
bool firstWt = true;
while (writerThread2Running)
{
if (!firstWt) continue;
Console.WriteLine("SECOND WRITERThread [2] is In The CoffeeCorner");
firstWt=false;
}
this.dataDelivery2 = this.dataQue[LiveDataCount_CurIndex];
Console.WriteLine("Activating SECOND WRITERThread [2]");
itsTimeForWTrd2 = false;
writerThread2Running = true;
//writerThread1Running = true;
writerThread2 = new System.Threading.Thread(WriterThread2);
writerThread2.IsBackground = true;
writerThread2.Name = this.DepoThreadName + "=[WRITER2]";
writerThread2.Start();
}
else
{
bool firstWt = true;
while (writerThread1Running)
{
if (!firstWt)continue;
Console.WriteLine("WRITERThread [1] is In The CoffeeCorner");
firstWt=false;
}
Console.WriteLine("Activating WRITERThread [1]");
this.dataDelivery1 = this.dataQue[LiveDataCount_CurIndex];
writerThread1Running = true;
writerThread1 = new System.Threading.Thread(WriterThread1);
writerThread1.IsBackground = true;
writerThread1.Name = this.DepoThreadName+"=[WRITER1]";
writerThread1.Start();
itsTimeForWTrd2 = true;
}
Thread.MemoryBarrier();
}
Run Code Online (Sandbox Code Playgroud)
使用写句柄读写实际数据(类似的写入代码)
public unsafe byte[] UsReadBytes(int offset, int num)
{
byte[] arr = new byte[num];
byte* ptr = (byte*)0;
this.accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
Marshal.Copy(IntPtr.Add(new IntPtr(ptr), offset), arr, 0, num);
this.accessor.SafeMemoryMappedViewHandle.ReleasePointer();
return arr;
}
Run Code Online (Sandbox Code Playgroud)
正如我所说,我已经通过非阻塞/无等待/等等研究了数据同步和共享内存的问题.信号量锁,所以我试图在每次数据事务处理过程中删除任何类型的开销进入共享内存映射文件.我在这里问一下,消除Lock和EventWaitHandle并将其替换为内存栅栏的逻辑并通过mmf发出信号可能是什么问题?
如果您计划将其用于研发以外的特定目的,最简单的方法是使用已经提供该功能的库。思考这个问题的一种方法是,无锁 = 消息传递。两种可能的方法是: 对于简约的消息传递实现,ZeroMQ IPC,它提供强大的 .Net 支持和卓越的 IPC 性能 ( http://www.codeproject.com/Articles/488207/ZeroMQ-via-Csharp-Introduction ) 和有关更完整的 Actor-Model 实现(包括对 IPC 的支持),请查看 Akka.net ( http://getakka.net/docs/#networking )。
如果目的本质上是更多的研发(也就是说,你想编写自己的实现,这很酷),我仍然建议查看这些产品的源代码(特别是 Akka.net,因为它是用 C# 编写的),有关消息传递和基于 Actor 的 IPC 的实现思路。