First, thank you all for the replies!
Jonathan M Davis wrote:
Also, it could make a big difference if you use gdc or ldc
rather than dmd.
Thank you for the suggestion, I'll check that. However, I don't
expect the GCC optimizer to reduce the number of calls in this
specific test, since it did not kick in in the more obvious case
as I mentioned.
Right now, I am more concerned with the performance of the
front-end (RedBlackTree): if it currently can't be tuned to
perform fast enough, I'll just know that I should implement my
own version of a binary search tree container for my needs.
Rob T wrote:
You can check if disabling the GC just before the insert process
improves the performance. You may see 3x performance
improvement.
Disabling is safe provided you re-enable, this can be done
reliably with scope(exit) or something similar.
Hmm, it indeed performed faster, though not 3x in my setup.
However, the number of copy constructor calls stayed the same.
Steven Schveighoffer wrote:
I find the number of postblit calls excessive too.
I will have to look into why that happens.
I can say that once an element is allocated, it is not moved or
copied.
Could it be easily enforced in the library? Something like this:
when accessing data only for internal use in the data structure,
use an interface that disables assignment? Can such cases be
distinguished from the ones when the library user actively wants
to copy data?
Steven Schveighoffer wrote:
I will note that std.container.RedBlackTree is a port of
dcollections'
RBTree implementation.
Thank you for pointing that out. Perhaps I'll have to try the
test with that implementation, too.
monarch_dodra wrote:
Keep in mind that C++ and D have very different philosophies
regarding copy construction.
...
The conclusion is that the comparison is not fair: D's pass by
value is not *very* different from C++'s pass by ref (in amount
of data copied).
Well, perhaps I didn't make myself clear enough. The comparison
I posted is not intended to be a fair comparison of languages in
the general case! It is just my use case stripped to a minimal
example that still shows the number of calls correctly. In the
actual use case, I have something like
-----
struct element
{
long value;
int [] one;
int [] two;
this (this)
{
one = one.dup;
two = two.dup;
}
}
-----
Sure I could think of some other way to represent the data I need
as an object, this one just seems the most intuitive.
monarch_dodra wrote:
If you *do* want a fair-er comparison, then I'd suggest you
implement a ".dup" on your object, and see how many times THAT
gets called. Guess what: 0.
Right, but it's the copy constructor that gets called when I copy
a struct, and in these cases, I actually want it to copy the
arrays as well. Otherwise, the element object may end up in a
bad state.
Do you imply that I should implement dup for every struct I
create and then leave the copy constructor empty? As the library
makes use of the copy constructor and not dup, I fear it would be
an incorrect design, since the library will make broken copies of
my struct and pass them around.
monarch_dodra wrote:
I'm not saying D's approach is perfect, just that D's library is
optimized for D-like types.
and Rob T wrote:
I agree. There are cases where structs make a lot of sense,
usually when they are very simple simple and contain no pointers
or references, otherwise structs should be avoided in favor of
classes to avoid doing copy/move constructors and to avoid
concerns over performance optimizations. With classes, only
certain points in your code require that a duplicate copy be
made
of the class instance, the majority of code need only to pass
around a reference which is the default behavior - easy and
fast!
So, you suggest passing things by reference once they grow beyond
several bytes in size? Wouldn't that mean having to constantly
pay attention to some counter-intuitive code when I actually want
my objects to behave like values, not references (e.g., matrices
or other complex math objects)? In my example case with arrays
one and two, I do want my whole object to obey value semantics.
Once again, thank you all for attention.
-----
Ivan Kazmenko.