Как отладочные символы влияют на производительность исполняемого файла Linux, скомпилированного GCC?
при прочих равных факторах (например, уровень оптимизации), Как влияет наличие отладочных символов в ELF или так:
- время загрузки.
- объем памяти во время выполнения.
- быстродействие?
и что можно сделать, чтобы смягчить любые негативные последствия?
изменить Я видел этот вопрос, но я нахожу обсуждение бесполезным, так как фактор оптимизации кода запутал проблему. почему работает мой код медленнее с несколькими потоками, чем с одним потоком, когда он составляется для профилирования (-ГУ)?
2 ответов
символы отладки расположены в совершенно разных разделах из разделов кода / данных. Вы можете проверить это с помощью objdump
:
$ objdump -h a.out
a.out: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000400200 0000000000400200 00000200 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 000000000040021c 000000000040021c 0000021c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 000000000040023c 000000000040023c 0000023c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .hash 00000018 0000000000400260 0000000000400260 00000260 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000400278 0000000000400278 00000278 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000048 0000000000400298 0000000000400298 00000298 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 00000038 00000000004002e0 00000000004002e0 000002e0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000006 0000000000400318 0000000000400318 00000318 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000020 0000000000400320 0000000000400320 00000320 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000018 0000000000400340 0000000000400340 00000340 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 00000018 0000000000400358 0000000000400358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000400370 0000000000400370 00000370 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 00000020 0000000000400388 0000000000400388 00000388 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 000001c8 00000000004003b0 00000000004003b0 000003b0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 0000000e 0000000000400578 0000000000400578 00000578 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000004 0000000000400588 0000000000400588 00000588 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 00000024 000000000040058c 000000000040058c 0000058c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 0000007c 00000000004005b0 00000000004005b0 000005b0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .ctors 00000010 0000000000600630 0000000000600630 00000630 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .dtors 00000010 0000000000600640 0000000000600640 00000640 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .jcr 00000008 0000000000600650 0000000000600650 00000650 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .dynamic 000001a0 0000000000600658 0000000000600658 00000658 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .got 00000008 00000000006007f8 00000000006007f8 000007f8 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .got.plt 00000020 0000000000600800 0000000000600800 00000800 2**3
CONTENTS, ALLOC, LOAD, DATA
24 .data 00000010 0000000000600820 0000000000600820 00000820 2**3
CONTENTS, ALLOC, LOAD, DATA
25 .bss 00000010 0000000000600830 0000000000600830 00000830 2**3
ALLOC
26 .comment 00000039 0000000000000000 0000000000000000 00000830 2**0
CONTENTS, READONLY
27 .debug_aranges 00000030 0000000000000000 0000000000000000 00000869 2**0
CONTENTS, READONLY, DEBUGGING
28 .debug_pubnames 0000001b 0000000000000000 0000000000000000 00000899 2**0
CONTENTS, READONLY, DEBUGGING
29 .debug_info 00000055 0000000000000000 0000000000000000 000008b4 2**0
CONTENTS, READONLY, DEBUGGING
30 .debug_abbrev 00000034 0000000000000000 0000000000000000 00000909 2**0
CONTENTS, READONLY, DEBUGGING
31 .debug_line 0000003b 0000000000000000 0000000000000000 0000093d 2**0
CONTENTS, READONLY, DEBUGGING
32 .debug_str 00000026 0000000000000000 0000000000000000 00000978 2**0
CONTENTS, READONLY, DEBUGGING
33 .debug_loc 0000004c 0000000000000000 0000000000000000 0000099e 2**0
CONTENTS, READONLY, DEBUGGING
вы можете увидеть дополнительные разделы (с 27 до 33). Эти разделы не будут загружены во время выполнения, поэтому не будет никакого штрафа за производительность. Используя gdb
, вы также можете рассмотреть их во время выполнения
$ gdb ./a.out
(gdb) break main
(gdb) run
(gdb) info files
// blah blah ....
Local exec file:
`/home/kghost/a.out', file type elf64-x86-64.
Entry point: 0x4003b0
0x0000000000400200 - 0x000000000040021c is .interp
0x000000000040021c - 0x000000000040023c is .note.ABI-tag
0x000000000040023c - 0x0000000000400260 is .note.gnu.build-id
0x0000000000400260 - 0x0000000000400278 is .hash
0x0000000000400278 - 0x0000000000400294 is .gnu.hash
0x0000000000400298 - 0x00000000004002e0 is .dynsym
0x00000000004002e0 - 0x0000000000400318 is .dynstr
0x0000000000400318 - 0x000000000040031e is .gnu.version
0x0000000000400320 - 0x0000000000400340 is .gnu.version_r
0x0000000000400340 - 0x0000000000400358 is .rela.dyn
0x0000000000400358 - 0x0000000000400370 is .rela.plt
0x0000000000400370 - 0x0000000000400388 is .init
0x0000000000400388 - 0x00000000004003a8 is .plt
0x00000000004003b0 - 0x0000000000400578 is .text
0x0000000000400578 - 0x0000000000400586 is .fini
0x0000000000400588 - 0x000000000040058c is .rodata
0x000000000040058c - 0x00000000004005b0 is .eh_frame_hdr
0x00000000004005b0 - 0x000000000040062c is .eh_frame
0x0000000000600630 - 0x0000000000600640 is .ctors
0x0000000000600640 - 0x0000000000600650 is .dtors
0x0000000000600650 - 0x0000000000600658 is .jcr
0x0000000000600658 - 0x00000000006007f8 is .dynamic
0x00000000006007f8 - 0x0000000000600800 is .got
0x0000000000600800 - 0x0000000000600820 is .got.plt
0x0000000000600820 - 0x0000000000600830 is .data
0x0000000000600830 - 0x0000000000600840 is .bss
// blah blah ....
таким образом, единственным наказанием является то, что вам нужно дополнительное место на диске для хранения этой информации. Вы также можете использовать strip
для удаления отладочная информация:
$ strip a.out
использовать objdump
чтобы проверить это снова, вы увидите разницу.
EDIT:
вместо того, чтобы смотреть разделы, на самом деле загрузчик загружает файл elf в соответствии с его Program Header
, который можно увидеть objdump -p
. (следующий пример использует другой двоичный файл elf)
$ objdump -p /bin/cat
/bin/cat: file format elf64-x86-64
Program Header:
PHDR off 0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3
filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r-x
INTERP off 0x0000000000000238 vaddr 0x0000000000000238 paddr 0x0000000000000238 align 2**0
filesz 0x000000000000001c memsz 0x000000000000001c flags r--
LOAD off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
filesz 0x00000000000078bc memsz 0x00000000000078bc flags r-x
LOAD off 0x0000000000007c28 vaddr 0x0000000000207c28 paddr 0x0000000000207c28 align 2**21
filesz 0x0000000000000678 memsz 0x0000000000000818 flags rw-
DYNAMIC off 0x0000000000007dd8 vaddr 0x0000000000207dd8 paddr 0x0000000000207dd8 align 2**3
filesz 0x00000000000001e0 memsz 0x00000000000001e0 flags rw-
NOTE off 0x0000000000000254 vaddr 0x0000000000000254 paddr 0x0000000000000254 align 2**2
filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
EH_FRAME off 0x0000000000006980 vaddr 0x0000000000006980 paddr 0x0000000000006980 align 2**2
filesz 0x0000000000000274 memsz 0x0000000000000274 flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
RELRO off 0x0000000000007c28 vaddr 0x0000000000207c28 paddr 0x0000000000207c28 align 2**0
filesz 0x00000000000003d8 memsz 0x00000000000003d8 flags r--
заголовки программы сообщают, какой сегмент будет загружен с флагами rwx, несколько разделов с одинаковыми флагами будут объединены в один сегмент.
BTW:
загрузчику все равно разделы при загрузке файла elf, но он будет выглядеть несколько разделов, связанных с символами, чтобы разрешить символы, когда это необходимо.
вы можете посмотреть на почему мой код работает медленнее с несколькими потоками, чем с одним потоком, когда он компилируется для профилирования (- pg)? для быстрого объяснения того, как символы отладки могут повлиять на оптимизацию.
чтобы ответить на ваши 3 вопроса:
- время загрузки будет увеличено, когда символы отладки присутствуют, когда их нет
- след на диске будет больше
- если вы собрали с нуля оптимизация тогда вы действительно ничего не теряете. Если вы установите оптимизацию, то оптимизированный код будет менее оптимизирован из-за символов отладки.