Linux Kernel Tinification Josh Triplett josh@joshtriplett.org - - PowerPoint PPT Presentation

linux kernel tinification
SMART_READER_LITE
LIVE PREVIEW

Linux Kernel Tinification Josh Triplett josh@joshtriplett.org - - PowerPoint PPT Presentation

Linux Kernel Tinification Josh Triplett josh@joshtriplett.org Linux Plumbers Conference 2014 boot-floppies two floppies and an Internet connection 2.2.19 - 977k compressed debian-installer one floppy and an Internet connection 2.4.27 -


slide-1
SLIDE 1

Linux Kernel Tinification

Josh Triplett josh@joshtriplett.org Linux Plumbers Conference 2014

slide-2
SLIDE 2
slide-3
SLIDE 3
slide-4
SLIDE 4
slide-5
SLIDE 5

boot-floppies

slide-6
SLIDE 6

two floppies and an Internet connection

slide-7
SLIDE 7

2.2.19 - 977k compressed

slide-8
SLIDE 8

debian-installer

slide-9
SLIDE 9
  • ne floppy and

an Internet connection

slide-10
SLIDE 10

2.4.27 - 797k compressed

slide-11
SLIDE 11

2.4.27 - 797k compressed 2.6.8 - 1073k compressed

slide-12
SLIDE 12

“Linux runs on everything from cell phones to supercomputers”

slide-13
SLIDE 13

This is not an embedded system anymore

2GB RAM 16GB storage

slide-14
SLIDE 14

Original motivation

◮ Size-constrained bootloaders (why use GRUB?) ◮ x86 boot track: 32256 bytes

slide-15
SLIDE 15

Embedded systems

◮ Tiny flash part (1-8MB or smaller) for kernel and userspace ◮ CPU with onboard SRAM (< 1024kB)

slide-16
SLIDE 16

Compression

◮ vmlinuz is compressed ◮ Decompression stub for self-extraction

slide-17
SLIDE 17

Execute in place

◮ Don’t load kernel into memory ◮ Run directly from flash ◮ Code and read-only data read from flash ◮ Read-write data in memory

slide-18
SLIDE 18

Execute in place

◮ Don’t load kernel into memory ◮ Run directly from flash ◮ Code and read-only data read from flash ◮ Read-write data in memory ◮ Minimizes memory usage

slide-19
SLIDE 19

Execute in place

◮ Don’t load kernel into memory ◮ Run directly from flash ◮ Code and read-only data read from flash ◮ Read-write data in memory ◮ Minimizes memory usage ◮ Precludes compression

slide-20
SLIDE 20

Configuring a minimal kernel

Configuration Compressed Uncompressed make defconfig 5706k 16532k

slide-21
SLIDE 21

Configuring a minimal kernel

Configuration Compressed Uncompressed make defconfig 5706k 16532k make allnoconfig 503k 1269k

slide-22
SLIDE 22

Configuring a minimal kernel

Configuration Compressed Uncompressed make defconfig 5706k 16532k make allnoconfig 503k 1269k

◮ 3.15-rc1: allnoconfig automatically disables options behind

EXPERT and EMBEDDED

slide-23
SLIDE 23

Configuring a minimal kernel

Configuration Compressed Uncompressed make defconfig 5706k 16532k make allnoconfig 503k 1269k

◮ 3.15-rc1: allnoconfig automatically disables options behind

EXPERT and EMBEDDED

◮ 3.17-rc1: tinyconfig: enable CC_OPTIMIZE_FOR_SIZE,

OPTIMIZE_INLINING, KERNEL_XZ, SLOB, NOHIGHMEM,

slide-24
SLIDE 24

Configuring a minimal kernel

Configuration Compressed Uncompressed make defconfig 5706k 16532k make allnoconfig 503k 1269k make tinyconfig 346k 1048k

◮ 3.15-rc1: allnoconfig automatically disables options behind

EXPERT and EMBEDDED

◮ 3.17-rc1: tinyconfig: enable CC_OPTIMIZE_FOR_SIZE,

OPTIMIZE_INLINING, KERNEL_XZ, SLOB, NOHIGHMEM,

slide-25
SLIDE 25

Configuring a minimal kernel

Configuration Compressed Uncompressed make defconfig 5706k 16532k make allnoconfig 503k 1269k make tinyconfig 346k 1048k

◮ 3.15-rc1: allnoconfig automatically disables options behind

EXPERT and EMBEDDED

◮ 3.17-rc1: tinyconfig: enable CC_OPTIMIZE_FOR_SIZE,

OPTIMIZE_INLINING, KERNEL_XZ, SLOB, NOHIGHMEM,

◮ Manually simulated ”tinyconfig” on older kernels for size

comparisons

slide-26
SLIDE 26

Configuring a minimal useful kernel

Configuration Compressed Uncompressed make tinyconfig 346k 1048k

slide-27
SLIDE 27

Configuring a minimal useful kernel

Configuration Compressed Uncompressed make tinyconfig 346k 1048k + ELF support +2k +4k

slide-28
SLIDE 28

Configuring a minimal useful kernel

Configuration Compressed Uncompressed make tinyconfig 346k 1048k + ELF support +2k +4k + modules +18k +53k

slide-29
SLIDE 29

Configuring a minimal useful kernel

Configuration Compressed Uncompressed make tinyconfig 346k 1048k + ELF support +2k +4k + modules +18k +53k + initramfs +32k +37k

slide-30
SLIDE 30

Configuring a minimal useful kernel

Configuration Compressed Uncompressed make tinyconfig 346k 1048k + ELF support +2k +4k + modules +18k +53k + initramfs +32k +37k + flash storage + filesystem + networking . . .

slide-31
SLIDE 31

minimum kernel size (kB) by kernel version

3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.103.113.123.133.143.153.163.17 860 880 900 920 940 960 980 1,000 1,020 1,040 1,060

slide-32
SLIDE 32

minimum kernel size (kB) by kernel version

3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.103.113.123.133.143.153.163.17 860 880 900 920 940 960 980 1,000 1,020 1,040 1,060

CONFIG_TTY

slide-33
SLIDE 33

Shrinking further

◮ Let’s not give up and let ”tiny” mean ”proprietary RTOS” ◮ Linux could still go an order of magnitude smaller, at least

slide-34
SLIDE 34

Shrinking further

◮ Let’s not give up and let ”tiny” mean ”proprietary RTOS” ◮ Linux could still go an order of magnitude smaller, at least ◮ Let’s make the core as small as possible ◮ Leave maximum room for useful functionality

slide-35
SLIDE 35

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data 00001000 d raw_data 00001210 r intel_tlb_table 00002000 D init_thread_union 00002000 r nhm_lbr_sel_map 00002000 r snb_lbr_sel_map 00002180 D init_tss 00003094 T real_mode_blob 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-36
SLIDE 36

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data 00001210 r intel_tlb_table 00002000 D init_thread_union 00002000 r nhm_lbr_sel_map 00002000 r snb_lbr_sel_map 00002180 D init_tss 00003094 T real_mode_blob 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-37
SLIDE 37

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table 00002000 D init_thread_union 00002000 r nhm_lbr_sel_map 00002000 r snb_lbr_sel_map 00002180 D init_tss 00003094 T real_mode_blob 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-38
SLIDE 38

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table 00002000 D init_thread_union initial thread and stack 00002000 r nhm_lbr_sel_map 00002000 r snb_lbr_sel_map 00002180 D init_tss 00003094 T real_mode_blob 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-39
SLIDE 39

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table 00002000 D init_thread_union initial thread and stack 00002000 r nhm_lbr_sel_map tiny/disable-perf (-147k) 00002000 r snb_lbr_sel_map tiny/disable-perf 00002180 D init_tss 00003094 T real_mode_blob 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-40
SLIDE 40

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table 00002000 D init_thread_union initial thread and stack 00002000 r nhm_lbr_sel_map tiny/disable-perf (-147k) 00002000 r snb_lbr_sel_map tiny/disable-perf 00002180 D init_tss tiny/no-io (-9k) 00003094 T real_mode_blob 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-41
SLIDE 41

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table 00002000 D init_thread_union initial thread and stack 00002000 r nhm_lbr_sel_map tiny/disable-perf (-147k) 00002000 r snb_lbr_sel_map tiny/disable-perf 00002180 D init_tss tiny/no-io (-9k) 00003094 T real_mode_blob copied to low mem 00006000 b .brk.early_pgt_alloc 00100000 b .brk.pagetables

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-42
SLIDE 42

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table 00002000 D init_thread_union initial thread and stack 00002000 r nhm_lbr_sel_map tiny/disable-perf (-147k) 00002000 r snb_lbr_sel_map tiny/disable-perf 00002180 D init_tss tiny/no-io (-9k) 00003094 T real_mode_blob copied to low mem 00006000 b .brk.early_pgt_alloc .bss 00100000 b .brk.pagetables .bss

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-43
SLIDE 43

nm --size-sort vmlinux

◮ Find large symbols for potential removal

00001000 d raw_data VDSO 00001000 d raw_data Another VDSO 00001210 r intel_tlb_table

  • Hmmmm. . .

00002000 D init_thread_union initial thread and stack 00002000 r nhm_lbr_sel_map tiny/disable-perf (-147k) 00002000 r snb_lbr_sel_map tiny/disable-perf 00002180 D init_tss tiny/no-io (-9k) 00003094 T real_mode_blob copied to low mem 00006000 b .brk.early_pgt_alloc .bss 00100000 b .brk.pagetables .bss

◮ ’r’ is read-only, ’b’ is bss, ’d’ is data, ’t’ is text ◮ For memory usage, look at writable data and bss ◮ For compiled size, ignore bss

slide-44
SLIDE 44

intel_tlb_table

◮ git grep intel_tlb_table

slide-45
SLIDE 45

intel_tlb_table

◮ git grep intel_tlb_table

static const struct _tlb_table intel_tlb_table[] = { { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages ..." }, { 0x02, TLB_INST_4M, 2, " TLB_INST 4 MByte pages ..." }, /* ... 34 entries total ... */

slide-46
SLIDE 46

intel_tlb_table

◮ git grep intel_tlb_table

static const struct _tlb_table intel_tlb_table[] = { { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages ..." }, { 0x02, TLB_INST_4M, 2, " TLB_INST 4 MByte pages ..." }, /* ... 34 entries total ... */ struct _tlb_table { unsigned char descriptor; char tlb_type; unsigned int entries; /* unsigned int ways; */ char info[128]; };

slide-47
SLIDE 47

intel_tlb_table

◮ git grep intel_tlb_table

static const struct _tlb_table intel_tlb_table[] = { { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages ..." }, { 0x02, TLB_INST_4M, 2, " TLB_INST 4 MByte pages ..." }, /* ... 34 entries total ... */ struct _tlb_table { unsigned char descriptor; char tlb_type; unsigned int entries; /* unsigned int ways; */ char info[128]; };

◮ 34 ∗ 128 = 4352 bytes (0x1100)

slide-48
SLIDE 48

Shrinking intel_tlb_table

◮ Kconfig to remove human-readable descriptions?

slide-49
SLIDE 49

Shrinking intel_tlb_table

◮ Kconfig to remove human-readable descriptions? ◮ Absolutely nothing references those descriptions!

slide-50
SLIDE 50

Shrinking intel_tlb_table

◮ Kconfig to remove human-readable descriptions? ◮ Absolutely nothing references those descriptions! ◮ Just delete the info field ◮ Make the descriptions comments

slide-51
SLIDE 51

Shrinking intel_tlb_table

◮ Kconfig to remove human-readable descriptions? ◮ Absolutely nothing references those descriptions! ◮ Just delete the info field ◮ Make the descriptions comments ◮ How much did we save?

slide-52
SLIDE 52

scripts/bloat-o-meter

◮ Compare symbol sizes between two kernels ◮ Similar to diffstat ◮ scripts/bloat-o-meter vmlinux-old vmlinux-new

slide-53
SLIDE 53

scripts/bloat-o-meter

◮ Compare symbol sizes between two kernels ◮ Similar to diffstat ◮ scripts/bloat-o-meter vmlinux-old vmlinux-new

add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-4361 (-4361) function

  • ld

new delta intel_detect_tlb 876 867

  • 9

intel_tlb_table 4624 272

  • 4352
slide-54
SLIDE 54

TLB round 2

struct _tlb_table { unsigned char descriptor; char tlb_type; unsigned int entries; };

◮ All values for entries fit in a u16 ◮ Result is copied into a u16 after lookup ◮ Wastes 4 bytes per entry (including padding)

slide-55
SLIDE 55

TLB round 2

struct _tlb_table { unsigned char descriptor; char tlb_type; unsigned int entries; };

◮ All values for entries fit in a u16 ◮ Result is copied into a u16 after lookup ◮ Wastes 4 bytes per entry (including padding)

add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-146 (-146) function

  • ld

new delta intel_detect_tlb 867 857

  • 10

intel_tlb_table 272 136

  • 136
slide-56
SLIDE 56

TLB round 3

◮ We’ve just saved 4.5k in every kernel ◮ Can we do even better for embedded kernels?

slide-57
SLIDE 57

TLB round 3

◮ We’ve just saved 4.5k in every kernel ◮ Can we do even better for embedded kernels? ◮ Why do we decode the TLB, anyway?

slide-58
SLIDE 58

TLB round 3

◮ We’ve just saved 4.5k in every kernel ◮ Can we do even better for embedded kernels? ◮ Why do we decode the TLB, anyway? ◮ A single printk at boot time

slide-59
SLIDE 59

TLB round 3

◮ We’ve just saved 4.5k in every kernel ◮ Can we do even better for embedded kernels? ◮ Why do we decode the TLB, anyway? ◮ A single printk at boot time ◮ #ifndef CONFIG_PRINTK

slide-60
SLIDE 60

TLB round 3

◮ We’ve just saved 4.5k in every kernel ◮ Can we do even better for embedded kernels? ◮ Why do we decode the TLB, anyway? ◮ A single printk at boot time ◮ #ifndef CONFIG_PRINTK

add/remove: 0/3 grow/shrink: 0/0 up/down: 0/-1215 (-1215) function

  • ld

new delta intel_tlb_table 136

  • 136

cpu_detect_tlb_amd 222

  • 222

intel_detect_tlb 857

  • 857
slide-61
SLIDE 61

TLB summary

add/remove: 0/3 grow/shrink: 0/0 up/down: 0/-5722 (-5722) function

  • ld

new delta cpu_detect_tlb_amd 222

  • 222

intel_detect_tlb 876

  • 876

intel_tlb_table 4624

  • 4624

◮ 4.5k saved on every kernel ◮ 1.2k more saved on embedded kernels ◮ Patches in tinification tree, tiny/tlb branch

slide-62
SLIDE 62

syscalls

◮ Current Linux (on 32-bit x86) has ∼353 syscalls ◮ /bin/true uses ∼11 (less if static) ◮ Embedded systems fall somewhere in the middle

slide-63
SLIDE 63

syscalls

◮ Current Linux (on 32-bit x86) has ∼353 syscalls ◮ /bin/true uses ∼11 (less if static) ◮ Embedded systems fall somewhere in the middle ◮ make tinyconfig kernel has ∼247 ◮ Far too many unconditionally available syscalls

slide-64
SLIDE 64

A few unconditionally available syscalls

◮ adjtime/adjtimex and NTP support ◮ Older compatibility syscalls ◮ fallocate ◮ tee/splice ◮ kill and signal handling ◮ Scheduler configuration and priorities ◮ xattrs ◮ ptrace

slide-65
SLIDE 65

Removing syscalls

◮ Add Kconfig symbol for the syscall

◮ default y ◮ bool "..." if EXPERT

slide-66
SLIDE 66

Removing syscalls

◮ Add Kconfig symbol for the syscall

◮ default y ◮ bool "..." if EXPERT

◮ Add cond_syscall(sys_foo); to kernel/sys_ni.c

slide-67
SLIDE 67

Removing syscalls

◮ Add Kconfig symbol for the syscall

◮ default y ◮ bool "..." if EXPERT

◮ Add cond_syscall(sys_foo); to kernel/sys_ni.c ◮ Compile out the syscall entry point (SYSCALL DEFINE)

slide-68
SLIDE 68

Removing syscalls

◮ Add Kconfig symbol for the syscall

◮ default y ◮ bool "..." if EXPERT

◮ Add cond_syscall(sys_foo); to kernel/sys_ni.c ◮ Compile out the syscall entry point (SYSCALL DEFINE) ◮ Compile out the infrastructure

slide-69
SLIDE 69

Example: omitting madvise and fadvise

init/Kconfig: +config ADVISE_SYSCALLS + bool "Enable madvise/fadvise syscalls" if EXPERT + default y + help + This option enables ...

slide-70
SLIDE 70

Example: omitting madvise and fadvise

init/Kconfig: +config ADVISE_SYSCALLS + bool "Enable madvise/fadvise syscalls" if EXPERT + default y + help + This option enables ... kernel/sys ni.c: +cond_syscall(sys_fadvise64); +cond_syscall(sys_fadvise64_64); +cond_syscall(sys_madvise);

slide-71
SLIDE 71

Example: Omitting madvise and fadvise (2)

mm/Makefile:

  • obj-y := filemap.o mempool.o oom_kill.o fadvise.o \

+obj-y := filemap.o mempool.o oom_kill.o \

slide-72
SLIDE 72

Example: Omitting madvise and fadvise (2)

mm/Makefile:

  • obj-y := filemap.o mempool.o oom_kill.o fadvise.o \

+obj-y := filemap.o mempool.o oom_kill.o \ +obj-$(CONFIG_ADVISE_SYSCALLS) += fadvise.o

slide-73
SLIDE 73

Example: Omitting madvise and fadvise (2)

mm/Makefile:

  • obj-y := filemap.o mempool.o oom_kill.o fadvise.o \

+obj-y := filemap.o mempool.o oom_kill.o \ +obj-$(CONFIG_ADVISE_SYSCALLS) += fadvise.o

  • mmu-$(CONFIG_MMU) := ... highmem.o madvise.o memory.o ...

+mmu-$(CONFIG_MMU) := ... highmem.o memory.o ...

slide-74
SLIDE 74

Example: Omitting madvise and fadvise (2)

mm/Makefile:

  • obj-y := filemap.o mempool.o oom_kill.o fadvise.o \

+obj-y := filemap.o mempool.o oom_kill.o \ +obj-$(CONFIG_ADVISE_SYSCALLS) += fadvise.o

  • mmu-$(CONFIG_MMU) := ... highmem.o madvise.o memory.o ...

+mmu-$(CONFIG_MMU) := ... highmem.o memory.o ... +ifdef CONFIG_MMU +

  • bj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o

+endif

slide-75
SLIDE 75

Example: Omitting madvise and fadvise (2)

mm/Makefile:

  • obj-y := filemap.o mempool.o oom_kill.o fadvise.o \

+obj-y := filemap.o mempool.o oom_kill.o \ +obj-$(CONFIG_ADVISE_SYSCALLS) += fadvise.o

  • mmu-$(CONFIG_MMU) := ... highmem.o madvise.o memory.o ...

+mmu-$(CONFIG_MMU) := ... highmem.o memory.o ... +ifdef CONFIG_MMU +

  • bj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o

+endif

◮ Saves 2.2k ◮ Merged during 3.18 merge window

slide-76
SLIDE 76

syscall infrastructure

◮ uselib (785 bytes)

◮ In-kernel ELF library loader

slide-77
SLIDE 77

syscall infrastructure

◮ uselib (785 bytes)

◮ In-kernel ELF library loader

◮ iopl and ioperm (9k)

◮ Piles of task-switching code ◮ Most of init_tss (seen in nm --size-sort)

slide-78
SLIDE 78

syscall infrastructure

◮ uselib (785 bytes)

◮ In-kernel ELF library loader

◮ iopl and ioperm (9k)

◮ Piles of task-switching code ◮ Most of init_tss (seen in nm --size-sort)

◮ perf (147k)

◮ Performance counter infrastructure ◮ Complete x86 instruction decoder ◮ Large per-CPU data tables ◮ Hardware breakpoints

slide-79
SLIDE 79

Link-Time Optimization (LTO)

◮ Compile the entire kernel at once ◮ Cross-module optimization ◮ Automatically compile out unused code

slide-80
SLIDE 80

Link-Time Optimization (LTO)

◮ Compile the entire kernel at once ◮ Cross-module optimization ◮ Automatically compile out unused code ◮ Could reduce #ifdef logic to just top-level interfaces

slide-81
SLIDE 81

Compiler wishlist

◮ Transparently omitting struct fields

◮ Compiler __attribute__ on field declaration ◮ Turn initialization and writes into no-ops ◮ Error or dummy value on reads

slide-82
SLIDE 82

Compiler wishlist

◮ Transparently omitting struct fields

◮ Compiler __attribute__ on field declaration ◮ Turn initialization and writes into no-ops ◮ Error or dummy value on reads ◮ Workaround: write all accesses as inline functions ◮ Major code churn to switch from field to accessor functions

slide-83
SLIDE 83

Compiler wishlist

◮ Transparently omitting struct fields

◮ Compiler __attribute__ on field declaration ◮ Turn initialization and writes into no-ops ◮ Error or dummy value on reads ◮ Workaround: write all accesses as inline functions ◮ Major code churn to switch from field to accessor functions

◮ Constant folding through function pointer fields

◮ Automatically notice no calls to a function pointer ◮ Automatically omit it as above ◮ Omit functions stored in that function pointer ◮ Recurse

slide-84
SLIDE 84

Best practices

◮ Almost never add new unconditional code

slide-85
SLIDE 85

Best practices

◮ Almost never add new unconditional code ◮ Strings can be large!

slide-86
SLIDE 86

Best practices

◮ Almost never add new unconditional code ◮ Strings can be large! ◮ Decode-and-print infrastructure should be optional

slide-87
SLIDE 87

Best practices

◮ Almost never add new unconditional code ◮ Strings can be large! ◮ Decode-and-print infrastructure should be optional ◮ syscalls should be optional

slide-88
SLIDE 88

Best practices

◮ Almost never add new unconditional code ◮ Strings can be large! ◮ Decode-and-print infrastructure should be optional ◮ syscalls should be optional ◮ Infrastructure supporting those syscalls should be optional

slide-89
SLIDE 89

Best practices

◮ Almost never add new unconditional code ◮ Strings can be large! ◮ Decode-and-print infrastructure should be optional ◮ syscalls should be optional ◮ Infrastructure supporting those syscalls should be optional ◮ Improve toolchain to make tinification more automatic

slide-90
SLIDE 90

Best practices

◮ Almost never add new unconditional code ◮ Strings can be large! ◮ Decode-and-print infrastructure should be optional ◮ syscalls should be optional ◮ Infrastructure supporting those syscalls should be optional ◮ Improve toolchain to make tinification more automatic

Project list and tinification tree:

tiny.wiki.kernel.org