BigInt memory usage

Marco Leise Marco.Leise at gmx.de
Thu Oct 13 08:00:54 PDT 2011


Am 13.10.2011, 02:26 Uhr, schrieb bearophile <bearophileHUGS at lycos.com>:

> On a 32 bit system this program has allocates about 100 MB of RAM:
>
>
> import std.bigint;
> int main() {
>     static assert(BigInt.sizeof == 12);
>     auto data = new BigInt[2_000_000];
>     foreach (i; 0 .. data.length)
>         data[i] = BigInt("9223372036854775808123");
>
>     int count;
>     foreach (i; 0 .. 2_000_000_000) { count++; }
>     return count;
> }
>
>
>
> It means about 50 bytes/biginteger.
>
> Every zero BigInt struct needs 12 bytes inside the 'data' array.
>
> The represented numeral requires about 73 bits, this means 3 words (with  
> lot of wasted space):
>
>>>> l = 9223372036854775808123
>>>> from math import log
>>>> log(l, 2)
> 72.965784284662092
>
>
> Using so much memory allows to store less numbers, and makes them slower  
> too (I have hit both problems). Do you know why D BigInts use so much  
> memory?
>
> Bye,
> bearophile

So the BigInt struct has a size of 3 machine words:
"data": a dynamic array (2 words) pointing to a block of uints
"signed": a flag (1 word including alignment) that can be avoided
           if you only need positive BigUInts.

During parsing the "data" array is set to a predicted size of 4 uints (16  
bytes) for your number, which makes a total of 28 bytes. That is what you  
must expect as a minimum from the implementation. Now when I run your code  
I get between 45 to 46 bytes per BigInt. So that is a difference of 17 to  
18 bytes.
That is the overhead of D's memory management. You get the same 17 to 18  
additional bytes if you replace your BigInt with a dynamic array of uints  
and initialize each of them like this:

      auto data = new uint[][2_000_000];
      foreach (i; 0 .. data.length)
          data[i] = new uint[4];


More information about the Digitalmars-d mailing list