Search code examples
c++performancestreamqueuestandard-library

string producer/consumer in C++: std::deque<char> or std::stringstream?


In our application we have a class that produces characters, and another that consumes them. The current implementation dynamically allocates characters as they are produced (using new) and delete them (with delete) as they are consumed. This is all terribly slow, and I am looking at ways to replace that implementation to improve its performance.

The semantic I need is that of the standard class queue: push at the front, pop at the back. The default implementation uses a deque IIRC. deque is typically implemented using "blocks" or "chunks" of memory, so I expect far less calls to the OS memory allocator, and a significant speed-up, with little additional memory usage.

However, since the data queued is characters (possibly wide characters), an alternative would be to use the standard input/output stream class, namely the character stream stringstream. AFAIK, their behaviour is queue-like too.

Is there a better choice a priori? Would both classes have similar allocation patterns? I can try and measure performance of both, but perhaps it doesn't really matter and either would be good enough. In that case, which would be easiest/safest to use?

A secondary matter is concurrency between the producer and the consumer. I can restrict access to be sequential (on the same thread), but a thread-safe implementation is likely to be beneficial performance-wise with current multi-core hardware.

Thanks for your wisdom before I dive in and start coding.


Solution

  • std::stringstream isn't a queue, since reading characters doesn't consume them. You can simply seekg(0) and read the same characeters all over again. Thus, the more you write, the more memory you will consume.

    Stick with std::queue. The default choice of std::deque as the underlying implementation is almost certainly the right one.

    Regarding concurrency, it is categorically unsafe to write to std::queue while any other thread is reading or writing to it. If you want an efficient blocking queue implementation, you'll have to write or borrow one specifically built for the purpose.