在Windows中使用IOCP时cachingOVERLAPPED结构

我在Windows中使用I / O完成端口,我有一个名为“Stream”的对象,类似于抽象HANDLE(因此它可以是套接字,文件等)。

当我调用Stream :: read()或Stream :: write()(如此,在文件的情况下为ReadFile()/ WriteFile(),在套接字的情况下为WSARecv()/ WSASend()),新的OVERLAPPED结构为了做一个挂起的I / O请求,将由一些其他线程在IOCP循环中完成。

然后,当OVERLAPPED结构将由IOCP循环完成时,将在那里销毁。 如果是这样的话,Stream :: read()或者Stream :: write()再次从IOCP循环中被调用,他们将实例化新的OVERLAPPED结构,并且它将永远持续下去。

这工作得很好。 但是现在我想通过添加OVERLAPPED对象的caching来改善这一点:当我的Stream对象进行大量的读写操作时,cachingOVERLAPPED结构是绝对有意义的。

但是现在出现了一个问题:当我释放一个Stream对象时,我必须释放caching的OVERLAPPED结构,但是我怎么知道它们是否已经完成或者仍然处于待处理状态,并且最近会有一个IOCP循环完成? 所以,这里需要一个primefaces引用计数,但是现在问题是如果我使用一个primefacesref计数器,我必须增加每个读或写操作的ref计数器,并减lessOVERLAPPED结构的每个IOCP循环完成或stream删除,在服务器上是很多的操作,所以我会通过增加/减less很多primefaces计数器很多次。

这会不会影响multithreading的并发? 这是我唯一的担心,阻止我把这个primefaces引用计数器为每个OVERLAPPED结构。

我的担心是没有根据的吗?

我认为这是一个重要的话题要指出,关于这个问题,看看别人的想法和用IOCPcachingOVERLAPPED结构的方法是值得的。 我希望find一个聪明的解决scheme,如果可能的话,不使用primefaces参考计数器。

假设你将一个带有OVERLAPPED结构的数据缓冲区作为“每个操作”数据对象进行绑定,那么将它们合并以避免过度的分配/释放和堆碎片是一个好主意。

如果你只使用这个对象进行I / O操作,那么不需要引用计数,只需从池中取出一个,使用WSASend / WSARecv,然后在完成后将其释放到池中IOCP完成处理程序。

但是,如果你想更复杂一点,并允许这些缓冲区被传递给其他代码,那么你可能要考虑参考它们,如果这使得它更容易。 我在我当前的框架中这样做,它允许我为通信的网络端提供通用代码,然后将读取完成的数据缓冲区传递给客户代码,并且可以做他们想要的事情,当他们完成时,他们回到游泳池。 这目前使用裁判计数,但我正在从一个小的性能调整远离。 引用计数仍然存在,但在大多数情况下,它只能从0 – > 1,然后再次到0,而不是在我的框架内的各层操纵(这是通过将缓冲区的所有权传递给用户代码使用智能指针)。

在大多数情况下,我认为引用计数不太可能是您最昂贵的操作(即使在NUMA硬件中,您的缓冲区正从多个节点使用)。 将这些东西放回池中的锁定更可能是你的瓶颈; 我已经解决了这个问题,所以我正在转向下一个更高的水果;)

您还会讨论您的“每个连接”对象,并在本地缓存您的“每个操作”数据(这是我将它推回到分配器之前所做的),而“操作”数据并不严格要求参考计数,“每个连接”数据至少需要一个原子可修改的“正在进行的数量操作”计数,以便您可以分辨何时可以释放IT。 同样,由于我的框架设计,这已成为客户代码可以容纳参考以及主动I / O操作的正常参考计数。 我还没有在通用框架中解决这个问题。