我有多个线程需要使用来自TCP流的数据。我希望在共享内存中使用循环缓冲区/队列从TCP套接字中读取。TCP接收将直接写入循环队列。消费者将从队列中读出信息。
这种设计应该允许零拷贝和零锁.然而,这里有两个不同的问题。
我在低层TCP中有点生疏,不太清楚如何判断消息何时完成。我是在寻找\0,还是它是特定于实现的?
ty
发布于 2012-07-02 21:18:59
不幸的是,TCP不能传输消息,只能传输字节流。如果要传输消息,则必须在顶部应用协议。高性能的最佳协议是那些使用指定消息长度的正常检查头的协议,这允许您直接将正确的数据量读取到合适的缓冲区对象中,而无需逐字节迭代数据字节以寻找消息结束字符。然后,可以将缓冲区指针排队到另一个线程,并为下一条消息创建/释放一个新的缓冲区对象。这避免了对大量数据的任何复制,对于大型消息来说,效率足够高,因此对消息对象指针使用非阻塞队列是毫无意义的。
下一个优化方法是将对象*缓冲区池起来,以避免连续的新/处置,回收使用者线程中的*缓冲区,以便在网络接收线程中重用。这对于ConcurrentQueue来说相当容易,最好是阻塞以允许流控制,而不是数据损坏或分段故障/AV(如果池暂时清空)。
接下来,在每个*缓冲区数据成员的开头添加一个“死区”大小,以防止任何线程与任何其他线程错误地共享数据。
结果应该是一个高带宽的完整消息流到使用者线程中,并且没有太大的延迟、CPU浪费或高速缓存。你所有的24个核心都可以在不同的数据上运行。
在多线程应用程序中复制大量数据是对糟糕设计和失败的承认。
跟进..。
听起来,由于不同的协议,您需要迭代数据:(
错误共享的PDU缓冲区对象,例如:
typedef struct{
char deadZone[256]; // anti-false-sharing
int dataLen;
char data[8388608]; // 8 meg of data
} SbufferData;
class TdataBuffer: public{
private:
TbufferPool *myPool; // reference to pool used, in case more than one
EpduState PDUstate; // enum state variable used to decode protocol
protected:
SbufferData netData;
public:
virtual reInit(); // zeros dataLen, resets PDUstate etc. - call when depooling a buffer
virtual int loadPDU(char *fromHere,int len); // loads protocol unit
release(); // pushes 'this' back onto 'myPool'
};
loadPDU被传递到原始网络数据的指针、长度。它返回0-意味着它还没有完全组装一个PDU,或者它从原始网络数据中得到的字节数来完全组装一个PDU,在这种情况下,将它排队,去池另一个PDU,然后用未使用的原始数据调用loadPDU(),然后继续下一个原始数据。
如果需要,您可以使用不同派生缓冲区类的不同池来服务不同的协议--一个TbufferPoolEprotocols数组。TbufferPool可能只是一个BlockingCollection队列。管理几乎变得琐碎--缓冲区可以发送到系统周围的队列中,发送到GUI以显示统计数据,然后可能发送给记录器,只要在队列链的末尾,有什么东西可以调用release()。
显然,一个“真实的”PDU对象会加载更多的方法、数据联合/结构、迭代器和运行协议的状态引擎,但这是基本的想法。主要是易于管理和封装,而且由于没有任何两个线程可以在同一个缓冲区实例上操作,所以解析/访问数据不需要锁/同步器。
哦,是的,由于没有任何队列必须保持锁定超过推送/弹出一个指针所需的时间,实际争用的可能性非常低--即使是传统的阻塞队列也几乎不需要使用内核锁定。
发布于 2014-01-20 05:11:10
如果您使用的是Windows 8或Windows 2012,则可以使用注册I/O,这可以为较低CPU提供比常规IOCP更高的带宽;它可以通过减少内核转换、零拷贝等方式来实现这一点
API:http://msdn.microsoft.com/en-us/library/windows/desktop/ms740642%28v=vs.85%29.aspx
背景信息:http://www.serverframework.com/asynchronousevents/rio/
https://stackoverflow.com/questions/11295474
复制相似问题