我正在学习C#异步套接字编程,并且我了解到重用某种池中的字节缓冲区是一个好主意,然后在从套接字接收数据时根据需要检出一个字节缓冲区。
但是,我看到了两种不同的字节数组池方法:一种使用简单的队列系统,只需根据需要在队列中添加/删除它们。如果请求了一个字节数组,并且队列中没有更多的字节数组,则会创建一个新的字节数组。
我见过的另一种方法使用了一个大的字节数组来存储整个程序。队列的概念仍然适用,但它是一个整数队列,用于确定要使用的字节数组的片(偏移量)。如果请求了一个数组,并且队列中没有剩余的数组,则必须调整数组的大小。
对于高度可扩展的服务器,以下哪种解决方案更好?我的直觉是,只使用多字节数组会更便宜,因为我认为根据需要调整数组的大小(即使我们将其分配为大块)将是非常昂贵的,特别是当它变大的时候。使用多个数组似乎也更直观--使用一个我没有考虑到的大型数组有什么好处吗?
发布于 2009-02-24 06:43:05
你的直觉是正确的。每次需要使数组更大时,都需要重新创建数组并复制现有的字节。由于我们在这里讨论的是字节,因此数组的大小可能很快就会变大。因此,您将每次请求一块连续的内存,这取决于您的程序使用内存的方式,这可能是可行的,也可能是不可行的。可以说,这实际上也将成为一个虚拟池。根据定义,池具有一组由不同客户端管理和共享的多个项目。
单数组解决方案的实现也要复杂得多。好消息是,一个数组解决方案允许您分配可变大小的块,但这是以本质上重新实现malloc为代价的:处理碎片等,这是您不应该涉及的。
多阵列解决方案允许您使用N个缓冲区初始化池,并以简单的方式轻松管理它们。这绝对是我推荐的方法。
发布于 2009-02-24 06:44:11
我不建议调整大小的选项。从简单开始,一路向上。一个字节缓冲区队列,当字节缓冲区耗尽时,将一个新的字节缓冲区添加到队列的末尾,这将是一个好的开始。您可能必须注意线程问题,所以我的建议是使用其他人的线程安全队列实现。
接下来,你可以看看更复杂的“指针”到一个大的字节数组块中,除了我的建议是有一个4k/16k (页面大小的两倍的幂)块的队列,索引到其中,当它满时,你添加另一个大的块到队列中。实际上,我根本不推荐这样做,因为它很复杂,而且在性能上的收益也有问题。
从简单开始,一路向上。缓冲池,使其线程安全,看看你是否需要更多。
发布于 2009-02-24 06:50:01
再次投票支持多个缓冲区,但由于您是异步处理,因此需要确保您的队列是线程安全的。默认的Queue<T>
集合绝对不是threadsafe。
因此,用户和MS员工JaredPar在这里有一个很好的线程安全队列实现:
http://blogs.msdn.com/jaredpar/archive/2009/02/16/a-more-usable-thread-safe-collection.aspx
https://stackoverflow.com/questions/581936
复制