CppCon2018 icon indicating copy to clipboard operation
CppCon2018 copied to clipboard

Use of std::queue instead of std::vector for outgoing messages

Open Olernov opened this issue 6 years ago • 7 comments

More natural for this task and more efficient when removing the first element.

Olernov avatar Jan 17 '19 03:01 Olernov

I got a question for you, how much memory does std::queue allocate when you insert the first element?

vinniefalco avatar Jan 17 '19 14:01 vinniefalco

According to https://en.cppreference.com/w/cpp/container/deque: "deques typically have large minimal memory cost; a deque holding just one element has to allocate its full internal array (e.g. 8 times the object size on 64-bit libstdc++; 16 times the object size or 4096 bytes, whichever is larger, on 64-bit libc++)". But is it a problem here? According to another study (https://www.codeproject.com/Articles/5425/An-In-Depth-Study-of-the-STL-Deque-Container) std::deque still shows better performance on push_back()'s and pop_front()'s than std::vector.

Olernov avatar Jan 18 '19 05:01 Olernov

@pdimov what do you think about this? queue looks correct on paper but vector has its own simplistic charm...

vinniefalco avatar Jan 22 '19 13:01 vinniefalco

deque/queue is probably better.

#include <vector>
#include <deque>
#include <chrono>
#include <memory>
#include <iostream>

template<class T> void pop_front( std::deque<T> & v )
{
	v.pop_front();
}

template<class T> void pop_front( std::vector<T> & v )
{
	v.erase( v.begin() );
}

template<class V> void test( V&& v, int N, int M )
{
	for( int i = 0; i < M; ++i )
	{
		v.push_back( std::make_shared<int>() );
	}

	auto tp1 = std::chrono::high_resolution_clock::now();

	for( int i = 0; i < N; ++i )
	{
		auto w = v.front();
		pop_front( v );
		v.push_back( w );
	}

	auto tp2 = std::chrono::high_resolution_clock::now();

	std::cout << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms\n";
}

int main()
{
	int const N = 1000000;
	int const M = 10;

	std::cout << "vector: "; test( std::vector<std::shared_ptr<int>>(), N, M );
	std::cout << " deque: "; test( std::deque<std::shared_ptr<int>>(), N, M );
}

pdimov avatar Jan 22 '19 14:01 pdimov

Well don't keep me in suspense, where's the output?

vinniefalco avatar Jan 22 '19 14:01 vinniefalco

N=1000000, M=1:
vector: 31 ms
 deque: 33 ms

N=1000000, M=10:
vector: 52 ms
 deque: 34 ms

N=1000000, M=100:
vector: 282 ms
 deque: 34 ms

N=1000000, M=1000:
vector: 2516 ms
 deque: 33 ms

N=1000000, M=10000:
vector: 25852 ms
 deque: 37 ms

pdimov avatar Jan 22 '19 15:01 pdimov

Yeah we should use deque/queue... thanks

vinniefalco avatar Jan 22 '19 15:01 vinniefalco