std.container.RedBlackTree versus C++ std::set

Steven Schveighoffer schveiguy at yahoo.com
Thu Feb 14 14:21:53 PST 2013


On Thu, 14 Feb 2013 15:33:19 -0500, Ivan Kazmenko <gassa at mail.ru> wrote:

> Rob T wrote:
>> When I look at the std.container source code, it seems that the payload  
>> element is passed by value multiple times unnecessarily, so to minimize  
>> copy construction you'll have to implement element as a class and  
>> implement a dup function for it.
>
> Thank you all for assistance, I've finally pinned it down!  It's the  
> default magic "a < b" that devours the most copies of my precious  
> structs!  Once I change the declaration:
>
> -----
> alias RedBlackTree !(element) container;
> -----
>
> to
>
> -----
> bool lessfun (ref element a, ref element b)
> {
> 	return a < b;
> }
>
> alias RedBlackTree !(element, lessfun) container;
> -----
>
> ... I get only exactly 3 * LIMIT postblit constructor calls, which is  
> 300,000 instead of 11,389,556.  While I still want to find where the  
> excess 200,000 calls originate from, this is definitely asymptotically  
> better than before: O (n) versus O (n log n) calls.  And it is now less  
> of a bottleneck in my original program.
>
> This raises the question to the default behavior of  
> std.functional.binaryFun.  Sure, for integers, class references and  
> small types, the current way is the best.  On the other hand, for large  
> structs and maybe some other complex objects that obey value semantics,  
> it seems it would be beneficial to, given a string like "a < b", produce  
> a function taking arguments by reference and not by value.  Maybe there  
> is some simple criterion (size of type greater than size_t - seems bad?  
> type is a struct - better?) which can be used with static if to generate  
> "(ref a, ref b)" instead of "(a, b)" version by default.  Of course, all  
> that could only work if there is a more detailed hierarchy of binary  
> functions, at least a binaryFunConst taking const arguments.

It is great that you found this!

Again, the issue here is D has restrictions on ref parameters.  There are  
no such restrictions on pass-by-value parameters.  So by default, the  
predicate tries by-value.

In this case, RedBlackTree is always assured of having lvalues for the  
predicate, so I can probably make the default use pass-by-ref.  If you  
could file a bug, that would be most helpful.

http://d.puremagic.com/issues/enter_bug.cgi?product=D

-Steve


More information about the Digitalmars-d-learn mailing list