Re: [boost] Performance comparison between ptr_vector and vector<cow_ptr<Shape> >, vector<copy_ptr<Shape> >

"Thorsten Ottosen" <tottosen@dezide.com> wrote in message news:<dpgu8s$e6k$1@sea.gmane.org>...
Thorsten Ottosen wrote:
axter wrote:
This is a continuation on a thread discussion advocating replacing the boost pointer containers with cow_ptr as the default pointer containers.
Test performance for initializing and copying container of pointers.
vector<copy_ptr<Shape> > 0.42 s
boost::ptr_vector<Shape> 0.42 s
vector<cow_ptr<Shape> > 0.09 s
>>>>>>>>>>>>>>
cow_ptr seems to win here. I can't figure out why cow_ptr is so much faster. ptr_vector uses cloning, of course, whereas cow_ptr does something else.
I further tried to add the proper return type to the functions, such that ptr_vector<T> returns by auto_ptr< ptr_vector<T> > and vector<T> as vector<T>. On top of this, I save the return-value and called size() on it.
This gave:
Test performance for initializing and copying container of pointers.
vector<copy_ptr<Shape> > 1.42 s
boost::ptr_vector<Shape> 0.81 s
vector<cow_ptr<Shape> > 0.13 s
But this test is a bit unfair: we create copies of the vector, but we never mutate that copy. A fair test would mutate all the elements.
The cow_ptr is like a clone pointer and a shared pointer put together. It shares the pointer, until an attempt is made to access it via non-constant operator-> or operator*. If non-constant access is made, then it checks to see if it's reference counter is larger then one. If so, it then performs the deep-copy, and releases the reference count. This is very efficient, because there's a good chance that the using code will never access all or any of the container objects in a non-constant manner. The difference in efficiency will show up even more, when you have a more complex type that takes more time to construct. The test code uses a simple Shape class, which doesn't have much to it, but if you added more data members, and made the construction more complex, then the above test will be drastically different and it would show cow_ptr having a very high performance ratio. By the way, I believe you could add this type of COW logic to the existing boost pointer containers, and increase their efficiency. But there is an overhead to this logic, and you might have notice that some of the test show copy_ptr out performming cow_ptr. You could consider adding a policy option to the boost pointer containers, that would allow choosing between COW method and Clone-Always method.

David Maisonave wrote:
"Thorsten Ottosen" <tottosen@dezide.com> wrote in message news:<dpgu8s$e6k$1@sea.gmane.org>...
This gave:
Test performance for initializing and copying container of pointers.
vector<copy_ptr<Shape> > 1.42 s
boost::ptr_vector<Shape> 0.81 s
vector<cow_ptr<Shape> > 0.13 s
But this test is a bit unfair: we create copies of the vector, but we never mutate that copy. A fair test would mutate all the elements.
The cow_ptr is like a clone pointer and a shared pointer put together.
right.
It shares the pointer, until an attempt is made to access it via non-constant operator-> or operator*. If non-constant access is made, then it checks to see if it's reference counter is larger then one. If so, it then performs the deep-copy, and releases the reference count.
This is very efficient, because there's a good chance that the using code will never access all or any of the container objects in a non-constant manner.
well, if no objects are being mutated, we don't have to make a copy. In practice I don't have a good estimate of how much data is touched, but imgaine that it can easily be it all. In that case I expect ptr_vector to win again (like it did in the other three categories).
The difference in efficiency will show up even more, when you have a more complex type that takes more time to construct.
right, the above results has another string data member of size 100.
The test code uses a simple Shape class, which doesn't have much to it, but if you added more data members, and made the construction more complex, then the above test will be drastically different and it would show cow_ptr having a very high performance ratio.
it would also increase the likelihood that we would mutate the objects.
By the way, I believe you could add this type of COW logic to the existing boost pointer containers, and increase their efficiency.
It depends somewhat of the situation at hand AFAICT.
But there is an overhead to this logic,
right. ptr_vector uses vector<void*> internally to minimize binary size too. and runtime-space-wise, its optimal. whether that matters depends on the situation.
and you might have notice that some of the test show copy_ptr out performming cow_ptr. You could consider adding a policy option to the boost pointer containers, that would allow choosing between COW method and Clone-Always method.
perhaps, but I do fear such a thing would greatly complicate the implementation. I also have some concerns on performance of COW in multi-threaded environments. As for cow_ptr requiring copy-semantics, then I think that is a very poor idea. It must be possible to call new_clone() or similar. Good luck with the article, let us know when it is done. -Thorsten
participants (2)
-
David Maisonave
-
Thorsten Ottosen