2012-10-03 52 views
2

在我们的应用程序中,我们有一个产生字符的类,另一个消耗它们。当前的实现动态分配字符(使用new),并在消耗时删除它们(使用delete)。这一切都非常缓慢,我正在寻找方法来取代该实现以提高其性能。C++中的字符串生产者/消费者:std :: deque <char>或std :: stringstream?

我需要的语义是标准类queue的语义:推在前面,在后面弹出。默认实现使用deque IIRC。 deque通常是使用内存的“块”或“块”来实现的,所以我期望调用OS内存分配器的次数少得多,而且速度显着提高,并且只需很少的额外内存使用量。

但是,由于排队的数据是字符(可能是宽字符),所以可以使用标准输入/输出流类,即字符流stringstream。 AFAIK,他们的行为也像队列一样。

先验是否有更好的选择?这两个类是否有类似的分配模式?我可以尝试和衡量两者的表现,但也许它并不重要,或者是足够好的。在那种情况下,哪个最简单/最安全?

次要问题是生产者和消费者之间的并发。我可以将访问限制为顺序的(在同一个线程上),但对于当前的多核硬件,线程安全的实现可能在性能方面是有益的。

感谢您的智慧,然后再潜入并开始编码。

+0

我可能会去'std :: deque',因为它是专门为处理这种情况而设计的。另一种可能性是固定大小的队列,当队列满时就会阻塞。通过适当的大小,阻塞通常实际上是可取的(如果一方太落后,阻塞可以给它更多的CPU时间,以便有机会赶上)。 –

+0

std :: deque的连续内存需求可能会影响性能,消费者的一些大型realloc不够快。虽然尝试它可能是最好的答案 –

+1

我不认为'std :: deque'具有连续的内存要求。事实上,Josuttis说的相反。 –

回答

1

std::stringstream不是队列,因为阅读字符不会消耗它们。你可以简单地seekg(0)并重新阅读相同的字符。因此,你写得越多,你消耗的内存就越多。

坚持std::queue。作为底层实现的默认选择std::deque几乎肯定是正确的。

关于并发性,当任何其他线程正在读取或写入时,写入std::queue是绝对不安全的。如果你想要一个有效的阻塞队列实现,你必须编写或借用专门为此目的而构建的一个。

+0

std :: deque没有要求释放内存到操作系统,即使它是空的 - 这可能是OP –

+0

@AdrianCornish的考虑:好点。很难想象一个理智的实现不会释放或重复使用掉落在链条末端的块。但是,这当然不是一个保证。在C++ 11中,我想可以明智地使用['std :: deque :: shrink_to_fit'](http://en.cppreference.com/w/cpp/container/deque/shrink_to_fit)。 –

+0

@MarceloCanton - 酷 - 不知道存在 - 谢谢。虽然我有新的标准 - 从头到尾阅读它还没有发生;-) –

1

很多年前我读过这本书(我认为,没有再读过),他们实际上是在他们开始在他们破产之前开始要求为它购买杂志之前寄给我的杂志的:-)。

这可能有助于

http://www.drdobbs.com/parallel/lock-free-queues/208801974

作为一个方面说明我的实时系统的工作处理金融数据 - 我们用固定长度队列通常扔掉,将不适合在如果队列数据消费者无法处理它 - 旧数据比错过的数据更糟糕。当然你的要求可能会有所不同。

+1

就像这样的一个注释:如果你打算使用一个固定长度的队列,你通常会将它实现为一个循环缓冲区。 –

+0

实际上,我们使用SystemV IPC队列 - 但是,如果您可以阻止生产者覆盖消费者当前正在阅读的数据,则循环更好。 –

+0

我看过那篇文章,还有赫伯萨特的后续。 TL; DR:很难!至少作为第一步,我会放弃线程... –