December 03, 2012
On 12/1/2012 3:43 PM, Jonathan M Davis wrote:
> Any struct which contains reference types needs them. For instance, a struct
> containing int[] needs to dup that array if it doesn't want to have the copy
> referring to the same elements as the original and therefore risk having them
> be mutated. Arrays with immutable elements don't have that problem, but those
> with mutable elements (and to some extent those with const) do have such a
> problem, as to structs with classes or structs which are reference types, etc.
> I'm surprised that you'd think that postblit constructors were only useful for
> implementing reference counting types. IMHO, the language would be crippled
> without a postblit or copy constructor for structs.

On the other hand, I'd say you have a pretty expensive design if it required you to allocate memory in order to do a copy. Making copies ought to be a cheap operation.

It's not hard to implement copy-on-write for the referenced data. In fact, with reference counting, you shouldn't need to make those dups.

December 05, 2012
Hum...

Hust wanted to add that "Appender" also suffers from this issue. It will, on _each_and_every_ append, check if its payload has been initialized :/

That's far from ideal behavior for a function that's supposed to squeeze as much performance as possible out of array manipulation...
December 05, 2012
Hum...

Just wanted to add that "Appender" also suffers from this issue. It will, on _each_and_every_ append, check if its payload has been initialized :/

That's far from ideal behavior for a function that's supposed to squeeze as much performance as possible out of array manipulation...
December 09, 2012
On Monday, 3 December 2012 at 22:34:08 UTC, Walter Bright wrote:
> Making copies ought to be a cheap operation.


Beg to differ here.

Copying pointers ought to be cheap. Copying objects ought to be expensive.
December 09, 2012
On 12/8/2012 5:00 PM, Mehrdad wrote:
> Copying objects ought to be expensive.

I don't understand the rationale for that.
December 09, 2012
On Sunday, December 09, 2012 10:58:45 Walter Bright wrote:
> On 12/8/2012 5:00 PM, Mehrdad wrote:
> > Copying objects ought to be expensive.
> 
> I don't understand the rationale for that.

I can see an argument that there's no requirement that copying objects be cheap, since there are plenty of objects where it's _not_ cheap to copy them and where it can't be cheap to copy them, but I don't see any argument for them _supposed_ to be being expensive to copy. I suspect that Merhdad just phrased it incorrectly.

D and Phobos seem to be trying to take the tact that copying objects is supposed to be cheap and expect it to be cheap. But I honestly don't see how anyone can expect that to be relied upon. There are things that can be done to reduce the cost of copying an object (like COW), but l think that if you honestly expect that people aren't going to do stuff like

this(this)
{
    a = a.dup;
}

then you're deluding yourself. That's kind of the point of having posblits in the first place, and it's basically the example that TDPL gives as to what postblits do. And depending on the type of a's elements, that copy could be far worse than O(1). And even if it weren't, there's nothing stopping the programmer from doing other expensive operations in a postblit constructor (e.g. doing a deep copy of a red-black tree by recursively copying the whole thing).

I'm fine with saying that various algorithms will be far more expensive if your struct defines an expensive postblit and that defining an expensive postblit is best avoided if possible, but there _will_ be plenty of expensive postblits in real world code. The only way that you can guarantee that copying structs is cheap is if you make it impossible to do a deep copy (i.e. get rid of postblit), which would be _far_ too limiting. Even stuff like ref-counted structs would become impossible in that case, because it's postblit which makes them possible as well.

- Jonathan M Davis
December 09, 2012
On Sunday, 9 December 2012 at 19:17:06 UTC, Jonathan M Davis wrote:
> On Sunday, December 09, 2012 10:58:45 Walter Bright wrote:
>> On 12/8/2012 5:00 PM, Mehrdad wrote:
>> > Copying objects ought to be expensive.
>> 
>> I don't understand the rationale for that.
>
> I can see an argument that there's no requirement that copying objects be cheap, since there are plenty of objects where it's _not_ cheap to copy them and where it can't be cheap to copy them, but I don't see any argument for them _supposed_ to be being expensive to copy. I suspect that Merhdad just phrased it incorrectly.


+1 yup, sorry if it was confusing but Jon's clarification i what I meant.
December 09, 2012
To elaborate... what's the point of making everything cheap to copy?

Copying of an object is _not_ an operation like swap() or "move", which are essential to many algorithms.

Indeed, an object might not want to be copyable at all, or it might need to perform some expensive operation (as in Jon's example) in order for the copy to behave like a copy is supposed to.


The only thing that the arbitrary requirement "copies are supposed to be cheap" would do is that it would slow down everything else, forcing checks on operations that shouldn't need to be checked. And it's completely unnecessary unless you're working with reference types, in which case copying is already cheap anyways.


So basically, algorithms should _expect_ copying of arbitrary objects to be expensive, and there's no need for them to be otherwise. C++'s swap() illustrates the lack of the need for copying beautifully -- often times the only objects I copy "generically" in C++ are iterators. I never find the need to copy other objects... and I believe D has no such need, either.
December 09, 2012
On Sunday, 9 December 2012 at 20:02:15 UTC, Mehrdad wrote:
> I never find the need to copy other objects...


Correction:

I _rarely_ find the need to copy other objects for _generic_ (er, templated) types (iterators being the exception I mentioned).

But obviously copying is essential for many concrete classes, e.g. vector. And I have never had the need for copying a vector to be "cheap" in any sense... in fact, I feel it _should_ be expensive, because of what it's doing. So it works out perfectly.
December 09, 2012
On Sunday, December 09, 2012 21:02:14 Mehrdad wrote:
> So basically, algorithms should _expect_ copying of arbitrary objects to be expensive, and there's no need for them to be otherwise. C++'s swap() illustrates the lack of the need for copying beautifully -- often times the only objects I copy "generically" in C++ are iterators. I never find the need to copy other objects... and I believe D has no such need, either.

It's been a debate for some time whether Phobos should be able to rely on copying being cheap. Algorithms end up copying all the time, and it greatly simplifies things if you don't have to worry about copying being expensive. Being able to rely on copying being O(1) is something that Andrei has tried to push for, but I don't see how we really can given simple things like the need to dup arrays - though I can see arguing that it's up to the caller to make copying cheap if they want certain algorithms to be more efficient.

The whole reason that the move* primitives were introduced was to try and combat expensive copying, but they complicate things a fair bit and rarely get used, even if they should be.

D's move semantics also help, but ultimately, some things are just plain going to be expensive to copy, and I don't see how you can get around that without disallowing certain idioms, which would then cause a different set of problems.

- Jonathan M Davis