Re: Cost of .dup vs. instantiation
On Wednesday, 28 May 2014 at 17:33:19 UTC, monarch_dodra wrote: On Wednesday, 28 May 2014 at 14:36:25 UTC, Chris wrote: I use Appender to fill an array. The Appender is a class variable and is not instantiated with each function call to save instantiation. However, the return value or the function must be dup'ed, like so: Appender!(MyType[]) append; public auto doSomething() { scope (exit) { // clear append } // ... do something append ~= item; return (append.data).dup } My question is whether I save anything with Appender as a class variable here. I have to .dup the return value (+ clear the Appender). If I had a new Appender with each function call, it might be just as good. public auto doSomething() { Appender!(MyType[]) append; // return append.data. } Right or wrong? You might save a little because you avoid the cost of growing your appender repeatedly: Once the appender has come to maturity, it will very likely stop growing. At that point, you only pay for *1* allocation per call to doSomething. Further advantages include: - dup has APPENDABLE info (whereas appender.data does not). - less wasted memory: dup uses no more memory than it has to, whereas Appender may over-allocate, depending on how you fill it. The downside to your approach is that you keep a handle on a buffer that can grow, but never shrink. If a at a certain point, you have to process some particularly large input, then you'll consume excessive amounts of memory. monarch_dodra: Hm. This last point might be an issue. If I process a large input (text in this case) then I might run into trouble with append as a class variable. I also had a weird bug, because I didn't clear the memory for overwrite. TheFlyingFiddle: append is a class variable in _my_ program, not Appender, like so: class A { Appender!(MyType[]) append; // ... }
Re: Cost of .dup vs. instantiation
On Thursday, 29 May 2014 at 08:49:10 UTC, Chris wrote: monarch_dodra: Hm. This last point might be an issue. If I process a large input (text in this case) then I might run into trouble with append as a class variable. I also had a weird bug, because I didn't clear the memory for overwrite. You can always implement an upper bound approach, where if your input data becomes larger than a certain size, you return the data directly, and reset your appender. EG: Appender!(MyType[]) append; public auto doSomething() { scope (failure) { append.clear; } // ... do something append ~= item; MyType[] ret; if (append.data.length 10_000) { ret = append.data).dup; append.clear; //clears buffer, keeps memory. } else { ret = append.data; append = appender!(MyType[])(); //jettison old appender data. } return ret; }
Re: Cost of .dup vs. instantiation
On Thursday, 29 May 2014 at 12:04:35 UTC, monarch_dodra wrote: On Thursday, 29 May 2014 at 08:49:10 UTC, Chris wrote: monarch_dodra: Hm. This last point might be an issue. If I process a large input (text in this case) then I might run into trouble with append as a class variable. I also had a weird bug, because I didn't clear the memory for overwrite. You can always implement an upper bound approach, where if your input data becomes larger than a certain size, you return the data directly, and reset your appender. EG: Appender!(MyType[]) append; public auto doSomething() { scope (failure) { append.clear; } // ... do something append ~= item; MyType[] ret; if (append.data.length 10_000) { ret = append.data).dup; append.clear; //clears buffer, keeps memory. } else { ret = append.data; append = appender!(MyType[])(); //jettison old appender data. } return ret; } Yes, you're right, this is a possible solution. However, I don't feel good about keeping memory I don't need. This might be a problem when the code will finally be ported to mobile devices. I benchmarked the two implementations (class variable vs local variable) and the performance (i.e. speed) remains the same.
Cost of .dup vs. instantiation
I use Appender to fill an array. The Appender is a class variable and is not instantiated with each function call to save instantiation. However, the return value or the function must be dup'ed, like so: Appender!(MyType[]) append; public auto doSomething() { scope (exit) { // clear append } // ... do something append ~= item; return (append.data).dup } My question is whether I save anything with Appender as a class variable here. I have to .dup the return value (+ clear the Appender). If I had a new Appender with each function call, it might be just as good. public auto doSomething() { Appender!(MyType[]) append; // return append.data. } Right or wrong?
Re: Cost of .dup vs. instantiation
On Wednesday, 28 May 2014 at 14:36:25 UTC, Chris wrote: I use Appender to fill an array. The Appender is a class variable and is not instantiated with each function call to save instantiation. However, the return value or the function must be dup'ed, like so: Appender!(MyType[]) append; public auto doSomething() { scope (exit) { // clear append } // ... do something append ~= item; return (append.data).dup } My question is whether I save anything with Appender as a class variable here. I have to .dup the return value (+ clear the Appender). If I had a new Appender with each function call, it might be just as good. public auto doSomething() { Appender!(MyType[]) append; // return append.data. } Right or wrong? You might save a little because you avoid the cost of growing your appender repeatedly: Once the appender has come to maturity, it will very likely stop growing. At that point, you only pay for *1* allocation per call to doSomething. Further advantages include: - dup has APPENDABLE info (whereas appender.data does not). - less wasted memory: dup uses no more memory than it has to, whereas Appender may over-allocate, depending on how you fill it. The downside to your approach is that you keep a handle on a buffer that can grow, but never shrink. If a at a certain point, you have to process some particularly large input, then you'll consume excessive amounts of memory.
Re: Cost of .dup vs. instantiation
On Wednesday, 28 May 2014 at 14:36:25 UTC, Chris wrote: I use Appender to fill an array. The Appender is a class variable and is not instantiated with each function call to save instantiation. However, the return value or the function must be dup'ed, like so: Appender!(MyType[]) append; public auto doSomething() { scope (exit) { // clear append } // ... do something append ~= item; return (append.data).dup } My question is whether I save anything with Appender as a class variable here. I have to .dup the return value (+ clear the Appender). If I had a new Appender with each function call, it might be just as good. public auto doSomething() { Appender!(MyType[]) append; // return append.data. } Right or wrong? When it comes to optimizations it's hard to say. Benchmarking is better than relying advice/opinions on the internet in any case. That being said i doubt that the instantiation cost of the Appender is relevant. (Btw the appender is not a class variable! It is a struct with reference semantics). Reusing an appender is more for those cases where you want to reuse the underlying memory of the appender itself.