Thread overview
memory allocation is slow, why and how to improve
Oct 19, 2006
%u
Oct 19, 2006
Andy Knowles
Oct 19, 2006
Breezes
Oct 19, 2006
Hasan Aljudy
Oct 19, 2006
Lionello Lunesu
Oct 22, 2006
kawa
October 19, 2006
I supposed that memory allocation in D should be very fast for it employees GC technique. However, I dit a simple test and found D is slower that C++ and Java. The source file a used in test is listed as follows.

== File test.d

int main(char[][] args) {
        for (int i = 0; i < 10000000; i++) {
                new byte[(i % 128) + 1];
        }
        return 0;
}

== File test.cpp
int main(void) {
        int i;
        for (i = 0; i < 10000000; i++) {
                char *p = new char[(i % 128) + 1];
                delete p;
        }
}

== File test.java
public class test {
        public static void main(String[] args) {
                for (int i = 0; i < 10000000; i++) {
                        byte[] a = new byte[(i % 128) + 1];
                }
        }
}

For test.cpp, I build it with:
  g++ -O2 test.cpp
For test.d, I build it with:
  dmd -O -release test.d

The results are:
time java test ; time ./a.out ; time ./test
real    0m7.754s
user    0m5.688s
sys     0m2.048s

real    0m11.919s
user    0m11.909s
sys     0m0.004s

real    0m19.256s
user    0m19.033s
sys     0m0.004s

You can see that Java is the fastest, D is the slowest, much slower that C++.

My test environment:
Hardware: IBM laptop T43
OS: Ubuntu Dapper 6.06
Kernel: 2.6.15-27-386
DMD version:  v0.169
g++ version: g++ (GCC) 4.0.3
java version: Sun JVM 1.5.0_06

So what's the reason, and how to improve it?
October 19, 2006
%u wrote:
> I supposed that memory allocation in D should be very fast for it employees GC
> technique. However, I dit a simple test and found D is slower that C++ and
> Java. The source file a used in test is listed as follows.
> 
> == File test.d
> 
> int main(char[][] args) {
>         for (int i = 0; i < 10000000; i++) {
>                 new byte[(i % 128) + 1];
>         }
>         return 0;
> }
> 
> == File test.cpp
> int main(void) {
>         int i;
>         for (i = 0; i < 10000000; i++) {
>                 char *p = new char[(i % 128) + 1];
>                 delete p;
>         }
> }
> 
> == File test.java
> public class test {
>         public static void main(String[] args) {
>                 for (int i = 0; i < 10000000; i++) {
>                         byte[] a = new byte[(i % 128) + 1];
>                 }
>         }
> }
> 
> For test.cpp, I build it with:
>   g++ -O2 test.cpp
> For test.d, I build it with:
>   dmd -O -release test.d
> 
> The results are:
> time java test ; time ./a.out ; time ./test
> real    0m7.754s
> user    0m5.688s
> sys     0m2.048s
> 
> real    0m11.919s
> user    0m11.909s
> sys     0m0.004s
> 
> real    0m19.256s
> user    0m19.033s
> sys     0m0.004s
> 
> You can see that Java is the fastest, D is the slowest, much slower that C++.
> 
> My test environment:
> Hardware: IBM laptop T43
> OS: Ubuntu Dapper 6.06
> Kernel: 2.6.15-27-386
> DMD version:  v0.169
> g++ version: g++ (GCC) 4.0.3
> java version: Sun JVM 1.5.0_06
> 
> So what's the reason, and how to improve it?

When you say memory allocation should be fast, are you referring to just memory allocation or memory allocation and deallocation (memory management)?

If you are talking about only memory allocation, you should not be deleting the memory you allocated in C++ and you should be disabling the garbage collector in D and Java.  I'm not sure this is possible in Java.

If you want to compare memory management, then you should expect D to be slower than C++ because a GC will always be slower than manual memory management in straight forward situations such as the example above.

You should also not delete any of the allocated arrays until the end  of the loop - the GC in D is very likely not being run until the program exits, so no memory will be freed until this point.  So you are allocating from different heaps - one which is reset after each allocation (C++) and one which is not.  This will effect your results.

And technically, you should be using delete [] p; in C++.

Java may be faster than D because the garbage collector is not even called - the program simply exits and leaves cleanup to the OS.  This would make it faster than C++ because there is no need to delete.

Java probably also has a smarter GC than D.  D's GC is not type-aware, so it has to scan the arrays you allocate for pointers to other objects.  This is one area where D's GC could be improved.

D also initializes allocated arrays where C++ does not.  I believe Java does as well but I'm not sure.

And last of all, you should be careful constructing examples that do nothing as a clever optomiser will get rid of the parts that cannot possibly have any side effects.

I'd be interested to see timing results for more carefully constructed examples.

Regards,
Andy
October 19, 2006
Hi Andy
  Thanks a lot for your quick reply. Definitly I want to test memory allocation
and deallocation as a whole. As you have stated, the main problem of my simple
test is that it is too simple. I think I should construct a more complex and
resonalbe test case.
October 19, 2006

Breezes wrote:
> Hi Andy
>   Thanks a lot for your quick reply. Definitly I want to test memory allocation
> and deallocation as a whole. As you have stated, the main problem of my simple
> test is that it is too simple. I think I should construct a more complex and
> resonalbe test case.

You can still try the "= void;" initializer for D and get rid of the "delete p;" in C++
October 19, 2006
"Hasan Aljudy" <hasan.aljudy@gmail.com> wrote in message news:eh8jrd$3k8$1@digitaldaemon.com...
>
>
> Breezes wrote:
>> Hi Andy
>>   Thanks a lot for your quick reply. Definitly I want to test memory
>> allocation
>> and deallocation as a whole. As you have stated, the main problem of my
>> simple
>> test is that it is too simple. I think I should construct a more complex
>> and
>> resonalbe test case.
>
> You can still try the "= void;" initializer for D and get rid of the "delete p;" in C++

Yes, the "=void" and perhaps use "delete" also in D! That would make it somewhat fairer.

L.


October 22, 2006
Andy Knowles wrote:
> When you say memory allocation should be fast, are you referring to just memory allocation or memory allocation and deallocation (memory management)?
> 
> If you are talking about only memory allocation, you should not be deleting the memory you allocated in C++ and you should be disabling the garbage collector in D and Java.  I'm not sure this is possible in Java.
Right, don't use GC if you (moslty) manage memory manually.
You can't turn off GC in Java.

> Java may be faster than D because the garbage collector is not even called - the program simply exits and leaves cleanup to the OS.  This would make it faster than C++ because there is no need to delete.

The java VM don't run GC collect on exit (.NET clr do).
Add -verbose:gc flag

> Java probably also has a smarter GC than D.  D's GC is not type-aware, so it has to scan the arrays you allocate for pointers to other objects.  This is one area where D's GC could be improved.
As far as I know D use a conservative GC, being able to have a generational one like Java improve performance in such typical situations.

> 
> D also initializes allocated arrays where C++ does not.  I believe Java does as well but I'm not sure.
Java initializes every data so you have to do the same in C++.

> 
> And last of all, you should be careful constructing examples that do nothing as a clever optomiser will get rid of the parts that cannot possibly have any side effects.
> 
> I'd be interested to see timing results for more carefully constructed examples.
Me too :)

> 
> Regards,
> Andy