Compiling explicit double array definitions as binary resource in a DLL - is there a better way?

Viewed 49

I am currently using some explicit array definition like the following in my code:

double * p = new double[5]{
      0.029426,   0.029366,   0.029281,   0.029157,   0.028979
};

but with much bigger array-sizes. The reason I do this is, because I get the data in this ASCII text-form and want to be able to add it directly as binary data to the created DLL. Swapping the text before compiling is automated, but I want to avoid additional pre-compilation steps.

Now I've noticed two things:

a) compiling this code becomes really slow for larger arrays

b) the resulting DLL is much bigger than the array's binary data size should be

c) If I change double to float this does not really change the DLL size

All of this makes me wonder if there is not a (much) better way to do it, but so far I haven't found an answer here on SO which helped me, although I've seen a couple of related questions.

Can somebody explain why I see b) and c)?

Can somebody suggest a better method that takes (float/double) data as ASCII and embeds it as binary in a DLL but doesn't require pre-compilation steps?

Other hints or suggestions are also welcome.

1 Answers

Checking the assembler output, it seems like using new have a significant overhead.

Using your example we get assembly like.

double * p = new double[5]{
      0.029426,   0.029366,   0.029281,   0.029157,   0.028979
};

yields

p:
        .zero   8
__static_initialization_and_destruction_0(int, int):
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], edi
        mov     DWORD PTR [rbp-8], esi
        cmp     DWORD PTR [rbp-4], 1
        jne     .L3
        cmp     DWORD PTR [rbp-8], 65535
        jne     .L3
        mov     edi, 40
        call    operator new[](unsigned long)
        mov     rdx, rax
        mov     rax, rdx
        movsd   xmm0, QWORD PTR .LC0[rip]
        movsd   QWORD PTR [rax], xmm0
        add     rax, 8
        movsd   xmm0, QWORD PTR .LC1[rip]
        movsd   QWORD PTR [rax], xmm0
        add     rax, 8
        movsd   xmm0, QWORD PTR .LC2[rip]
        movsd   QWORD PTR [rax], xmm0
        add     rax, 8
        movsd   xmm0, QWORD PTR .LC3[rip]
        movsd   QWORD PTR [rax], xmm0
        add     rax, 8
        movsd   xmm0, QWORD PTR .LC4[rip]
        movsd   QWORD PTR [rax], xmm0
        mov     QWORD PTR p[rip], rdx
.L3:
        nop
        leave
        ret
_GLOBAL__sub_I_p:
        push    rbp
        mov     rbp, rsp
        mov     esi, 65535
        mov     edi, 1
        call    __static_initialization_and_destruction_0(int, int)
        pop     rbp
        ret
.LC0:
        .long   1855700750
        .long   1067327961
.LC1:
        .long   -428534657
        .long   1067323934
.LC2:
        .long   -1517051168
        .long   1067318230
.LC3:
        .long   634143331
        .long   1067309909
.LC4:
        .long   -988460953
        .long   1067297963

However, when not using new the compiler can just save everything as raw data:

const double p[] = {
      0.029426,   0.029366,   0.029281,   0.029157,   0.028979
};

yields something like

        .file   "example.cpp"
        .intel_syntax noprefix
        .text
.Ltext0:
        .section        .rodata
        .align 32
        .type   p, @object
        .size   p, 40
p:
        .long   1855700750
        .long   1067327961
        .long   -428534657
        .long   1067323934
        .long   -1517051168
        .long   1067318230
        .long   634143331
        .long   1067309909
        .long   -988460953
        .long   1067297963
        .text

Edit: (Lift in commend that seem to be a solution) If you put it in a header file, it is possible that the data ends upp multiple times in the library, and in that case, putting it in the cpp-files could help, and then you would need to use a function or extern variable to access it.

Related