www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - dynamic array initialized within a short function.

reply coxalan <coxalan web.de> writes:
...I dare to repost my last message, now including a non-empty subject line.


Hello!

I realized that this code:

int func() {
    int res;
    int[] g;
    g.length = 10;
    foreach(v; g) {
        res += v;
    }
    return res;
}

void main() {
    for(int i=0; i<10000000; i++) {
        func;
    }
}

runs about 7 times slower than this one:

class Funcclass {
    int[] g;

    this() {
        g.length = 10;
    }

    int func() {
        int res;
        foreach(v; g) {
            res += v;
        }
        return res;
    }
}

void main() {
    auto fc = new Funcclass;
    for(int i=0; i<10000000; i++) {
        fc.func;
    }
}

The compilation was done with -O -release.
The difference comes from all the memory-allocating and garbage collecting in
the first case.

My question is:
Is it the default solution to put the function 'func' and the array 'g' as
members into a common class?
Or are there other / more elegant solutions for this?

Thanks!
Oct 14 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
coxalan wrote:
 ....I dare to repost my last message, now including a non-empty subject line.
 
 
 Hello!
 
 I realized that this code:
 
 int func() {
     int res;
     int[] g;
     g.length = 10;
     foreach(v; g) {
         res += v;
     }
     return res;
 }
 
 void main() {
     for(int i=0; i<10000000; i++) {
         func;
     }
 }
 
 runs about 7 times slower than this one:
 
 class Funcclass {
     int[] g;
 
     this() {
         g.length = 10;
     }
 
     int func() {
         int res;
         foreach(v; g) {
             res += v;
         }
         return res;
     }
 }
 
 void main() {
     auto fc = new Funcclass;
     for(int i=0; i<10000000; i++) {
         fc.func;
     }
 }
 
 The compilation was done with -O -release.
 The difference comes from all the memory-allocating and garbage collecting in
the first case.
 
 My question is:
 Is it the default solution to put the function 'func' and the array 'g' as
members into a common class?
 Or are there other / more elegant solutions for this?
 
 Thanks!
 
int func(int[] g) { int res; foreach(v; g) { res += v; } return res; } void main() { auto g = new int[10]; for(int i=0; i<10000000; i++) { func(g); } } In general, you should try and do as few allocations as possible. If you're using an array as "scratch space" -- that is, you don't care about what's in it before or after the function, only that it's there, it often help to allocate it earlier, and pass it into the function. Actually, you could add an overload of func like so: int func() { auto g = new int[10]; scope(exit) delete g; return func(g); } Now both approaches work, and you can use whichever is most appropriate. -- Daniel
Oct 14 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Daniel Keep wrote:
 Actually, you could add an overload of func like so:
 
 int func() {
     auto g = new int[10];
     scope(exit) delete g;
     return func(g);
 }
 
 Now both approaches work, and you can use whichever is most appropriate.
If you're going to delete it anyway, and the length is a compile-time constant, you might as well pass a static array from the second function to the first instead. Another option: --- int func(int[] g = null) { g.length = 10; // original function code goes here } --- If a sufficiently-sized buffer is passed in, it's used. If not, a buffer is allocated. The main benefit over the 2-function approach is that only a single function is needed (so less clutter), but it does still heap-allocate when a new buffer is needed (and it doesn't delete such newly-allocated buffers).
Oct 14 2007
parent coxalan <coxalan web.de> writes:
Thanks for your answers!

Frits van Bommel Wrote:

 Daniel Keep wrote:
 Actually, you could add an overload of func like so:
 
 int func() {
     auto g = new int[10];
     scope(exit) delete g;
     return func(g);
 }
 
 Now both approaches work, and you can use whichever is most appropriate.
If you're going to delete it anyway, and the length is a compile-time constant, you might as well pass a static array from the second function to the first instead. Another option: --- int func(int[] g = null) { g.length = 10; // original function code goes here } --- If a sufficiently-sized buffer is passed in, it's used. If not, a buffer is allocated. The main benefit over the 2-function approach is that only a single function is needed (so less clutter), but it does still heap-allocate when a new buffer is needed (and it doesn't delete such newly-allocated buffers).
Thanks for your answers!
Oct 17 2007