Thread overview
size of executables
Aug 11, 2008
Sivo Schilling
Aug 11, 2008
Christian Kamm
Aug 11, 2008
Sivo Schilling
August 11, 2008
Hi all,

below are two versions of a small test code nailed down from a more complex
project.
In case 1 there are some static arrays inside a struct which is declared at
function scope. Then an instance of this struct is used in the same scope.
Case 2 differs from case 1 only in that the static arrays are placed direct
into the function, but with equal size and layout as before.

--- test_mdsasf.d ---
/***
 * test of multi dimensional static arrays
 *
 * Case 1:  - static arrays inside a struct
 *          - struct declaration at function scope
 */
module test_mdsasf;
import std.stdio;

void fnMDSA()
{
    enum
    {
        SD = 33    // single dimension
    }

    struct MDSA
    {
        float[SD][SD][SD] m2;
        int[SD][SD][SD]   wt;
        int[SD][SD][SD]   mr;
        int[SD][SD][SD]   mg;
        int[SD][SD][SD]   mb;
    }

    MDSA mdsa;

    void initMDSA()
    {
        // Clear all
        (cast(ubyte*)&mdsa)[0..mdsa.sizeof] = 0;
    }

    void testMDSA()
    {
        writefln("before init: mdsa.m2[%d][%d][%d] = %f", 13, 4, 11, mdsa.m2[13][4][11]);

        // initialize
        initMDSA();

        // show result
        writefln("after init: mdsa.m2[%d][%d][%d] = %f", 13, 4, 11, mdsa.m2[13][4][11]);

        // assign a value
        mdsa.m2[13][4][11] = 13*4*11;

        // show result
        writefln("after assign: mdsa.m2[%d][%d][%d] = %f", 13, 4, 11, mdsa.m2[13][4][11]);
    }

    testMDSA();
}

void main()
{
    fnMDSA();
}
--- test_mdsaf.d ---
/***
 * test of multi dimensional static arrays
 *
 * Case 2:  - static arrays inside a function
 */
module test_mdsaf;
import std.stdio;

void fnMDSA()
{
    enum
    {
        SD = 33    // single dimension
    }

    float[SD][SD][SD] m2;
    int[SD][SD][SD]   wt;
    int[SD][SD][SD]   mr;
    int[SD][SD][SD]   mg;
    int[SD][SD][SD]   mb;

    void initMDSA()
    {
        // Clear all
        (cast(ubyte*)&m2)[0..m2.sizeof] = 0;
        (cast(ubyte*)&wt)[0..wt.sizeof] = 0;
        (cast(ubyte*)&wt)[0..mr.sizeof] = 0;
        (cast(ubyte*)&wt)[0..mg.sizeof] = 0;
        (cast(ubyte*)&wt)[0..mb.sizeof] = 0;
    }

    void testMDSA()
    {
        writefln("before init: m2[%d][%d][%d] = %f", 13, 4, 11, m2[13][4][11]);

        // initialize
        initMDSA();

        // show result
        writefln("after init: m2[%d][%d][%d] = %f", 13, 4, 11, m2[13][4][11]);

        // assign a value
        m2[13][4][11] = 13*4*11;

        // show result
        writefln("after assign: m2[%d][%d][%d] = %f", 13, 4, 11, m2[13][4][11]);
    }

    testMDSA();
}

void main()
{
    fnMDSA();
}
--- end of files ---

But comparing the size of the two executables is very weird:

case 1: 929.820 bytes (test_mdsasf_v2.exe)
case 2: 216.604 bytes (test_mdsaf_v2.exe)

both compiled with DMD 2.018 (switches: -release -O -inline) on WinXP SP3.

Comparing the corresponding map files it becomes clear that this considerable size difference comes from the _DATA section (see <---):

 case 1                                             | case 2:
 ---------------------------------------------------+--------------------------------------------------
 Start         Length     Name      Class           | Start         Length     Name      Class
 0002:00000000 0002B40BH  _TEXT     CODE 32-bit     | 0002:00000000 0002CA8BH  _TEXT     CODE 32-bit
 0002:0002B40C 00000150H  ICODE     ICODE 32-bit    | 0002:0002CA8C 00000150H  ICODE     ICODE 32-bit
 0003:00000000 00000004H  .tls      tls 32-bit      | 0003:00000000 00000004H  .tls      tls 32-bit
 0003:00000004 00000004H  .tls$     tls 32-bit      | 0003:00000004 00000004H  .tls$     tls 32-bit
 0003:00000008 00000004H  .tls$ZZZ  tls 32-bit      | 0003:00000008 00000004H  .tls$ZZZ  tls 32-bit
 0004:00000000 00000004H  .CRT$XIA  DATA 32-bit     | 0004:00000000 00000004H  .CRT$XIA  DATA 32-bit
 0004:00000010 00000004H  .CRT$XIZ  DATA 32-bit     | 0004:00000010 00000004H  .CRT$XIZ  DATA 32-bit
 0004:00000020 00000004H  .CRT$XCA  DATA 32-bit     | 0004:00000020 00000004H  .CRT$XCA  DATA 32-bit
 0004:00000030 00000004H  .CRT$XCZ  DATA 32-bit     | 0004:00000030 00000004H  .CRT$XCZ  DATA 32-bit
 0004:00000040 00000004H  .CRT$XPA  DATA 32-bit     | 0004:00000040 00000004H  .CRT$XPA  DATA 32-bit
 0004:00000050 00000004H  .CRT$XPZ  DATA 32-bit     | 0004:00000050 00000004H  .CRT$XPZ  DATA 32-bit
 0004:00000060 00000004H  .CRT$XTA  DATA 32-bit     | 0004:00000060 00000004H  .CRT$XTA  DATA 32-bit
 0004:00000070 00000004H  .CRT$XTZ  DATA 32-bit     | 0004:00000070 00000004H  .CRT$XTZ  DATA 32-bit
 0004:00000074 00000000H  IMP__DATA IMP__DATA 32-bit| 0004:00000074 00000000H  IMP__DATA IMP__DATA 32-bit
 0004:00000080 000B5168H  _DATA     DATA 32-bit     | 0004:00000080 000059A8H  _DATA     DATA 32-bit       <---
 0004:000B51E8 00000000H  FMB       DATA 32-bit     | 0004:00005A28 00000000H  FMB       DATA 32-bit
 0004:000B51E8 0000003CH  FM        DATA 32-bit     | 0004:00005A28 0000003CH  FM        DATA 32-bit
 0004:000B5224 00000000H  FME       DATA 32-bit     | 0004:00005A64 00000000H  FME       DATA 32-bit
 0004:000B5224 00000000H  XIB       DATA 32-bit     | 0004:00005A64 00000000H  XIB       DATA 32-bit
 0004:000B5224 00000018H  XI        DATA 32-bit     | 0004:00005A64 00000018H  XI        DATA 32-bit
 0004:000B523C 00000000H  XIE       DATA 32-bit     | 0004:00005A7C 00000000H  XIE       DATA 32-bit
 0004:000B523C 00000000H  XIFCB     DATA 32-bit     | 0004:00005A7C 00000000H  XIFCB     DATA 32-bit
 0004:000B523C 00000004H  XIFU      DATA 32-bit     | 0004:00005A7C 00000004H  XIFU      DATA 32-bit
 0004:000B5240 00000000H  XIFL      DATA 32-bit     | 0004:00005A80 00000000H  XIFL      DATA 32-bit
 0004:000B5240 00000004H  XIFM      DATA 32-bit     | 0004:00005A80 00000004H  XIFM      DATA 32-bit
 0004:000B5244 00000000H  XIFCE     DATA 32-bit     | 0004:00005A84 00000000H  XIFCE     DATA 32-bit
 0004:000B5244 00000000H  XCB       DATA 32-bit     | 0004:00005A84 00000000H  XCB       DATA 32-bit
 0004:000B5244 0000000CH  XC        DATA 32-bit     | 0004:00005A84 0000000CH  XC        DATA 32-bit
 0004:000B5250 00000000H  XCE       DATA 32-bit     | 0004:00005A90 00000000H  XCE       DATA 32-bit
 0004:000B5250 00000000H  CONST     CONST 32-bit    | 0004:00005A90 00000000H  CONST     CONST 32-bit
 0004:000B5250 00000000H  EEND      ENDBSS 32-bit   | 0004:00005A90 00000000H  EEND      ENDBSS 32-bit
 0004:000B5250 000025BCH  _BSS      BSS 32-bit      | 0004:00005A90 000025BCH  _BSS      BSS 32-bit
 0004:000B780C 00000000H  XOB       BSS 32-bit      | 0004:0000804C 00000000H  XOB       BSS 32-bit
 0004:000B780C 00000004H  XO        BSS 32-bit      | 0004:0000804C 00000004H  XO        BSS 32-bit
 0004:000B7810 00000000H  XOE       BSS 32-bit      | 0004:00008050 00000000H  XOE       BSS 32-bit
 0004:000B7810 00000000H  XOFB      BSS 32-bit      | 0004:00008050 00000000H  XOFB      BSS 32-bit
 0004:000B7810 00000108H  XOF       BSS 32-bit      | 0004:00008050 00000108H  XOF       BSS 32-bit
 0004:000B7918 00000000H  XOFE      BSS 32-bit      | 0004:00008158 00000000H  XOFE      BSS 32-bit
 0004:000B7920 00000419H  c_common  BSS 32-bit      | 0004:00008160 00000419H  c_common  BSS 32-bit
 0004:000B7D40 00000000H  STACK     STACK 32-bit    | 0004:00008580 00000000H  STACK     STACK 32-bit
                                                    |
 Program entry point at 00023BDC                    | Program entry point at 0002525C

The difference in size of the _DATA section of the two cases above is

case 1      case 2      delta
000B5168H - 000059A8H = 000AF7C0H --> 718.784 byte!

To this end i've no idea what in case 1 goes into the _DATA section, but i suppose it's an (hidden ?)
instance of struct MDSA (MDSA.sizeof = 718.740 bytes) at global scope.

What do you think ?

Regards.

August 11, 2008
Sivo Schilling Wrote:
>     struct MDSA
>     {
>         float[SD][SD][SD] m2;
>         int[SD][SD][SD]   wt;
>         int[SD][SD][SD]   mr;
>         int[SD][SD][SD]   mg;
>         int[SD][SD][SD]   mb;
>     }
> 
>     MDSA mdsa;

vs

>     float[SD][SD][SD] m2;
>     int[SD][SD][SD]   wt;
>     int[SD][SD][SD]   mr;
>     int[SD][SD][SD]   mg;
>     int[SD][SD][SD]   mb;

In the first case DMD will generate a default initializer for the struct which is probably what you're looking at in the DATA section. I do not think you can stop DMD from doing that - it's part of the TypeInfo instance it generates for the struct.

Christian Kamm

August 11, 2008
Replay to Christian,

ok I get it. Structs are treated as POD by the compiler and therefore have a default initializer which have to be present in the executable.

Thanks.

Christian Kamm Wrote:

> Sivo Schilling Wrote:
> >     struct MDSA
> >     {
> >         float[SD][SD][SD] m2;
> >         int[SD][SD][SD]   wt;
> >         int[SD][SD][SD]   mr;
> >         int[SD][SD][SD]   mg;
> >         int[SD][SD][SD]   mb;
> >     }
> > 
> >     MDSA mdsa;
> 
> vs
> 
> >     float[SD][SD][SD] m2;
> >     int[SD][SD][SD]   wt;
> >     int[SD][SD][SD]   mr;
> >     int[SD][SD][SD]   mg;
> >     int[SD][SD][SD]   mb;
> 
> In the first case DMD will generate a default initializer for the struct which is probably what you're looking at in the DATA section. I do not think you can stop DMD from doing that - it's part of the TypeInfo instance it generates for the struct.
> 
> Christian Kamm
>