Современная операционная система: что надо знать разработчику Александр Крижановский NatSys Lab., Tempesta Technologies [email protected]
Jan 06, 2017
Современная операционная система: что надо знать разработчику
Александр Крижановский
NatSys Lab., Tempesta [email protected]
Disclamer
Компоненты ОС Linux – да, но через призму...
…моего личнго мнения → welcome to holy war :)
Современная ОС – зло!
Netmap (network IO), user-space TCP
O_DIRECT (databases), Linux Torvalds, LKML 10 Jan 2007: “The whole notion of "direct IO" is totally braindamaged. Just say no.”
Threads, Events OR Coroutines?- “Why Events are A Bad Idea”, Rob von Behren- “SEDA: An Architecture for Well-Conditioned, Scalable Internet Services”, Matt Welsh- Coroutines...
Memory allocation: ptmalloc, hoard, jemalloc, SLAB, pool, page, buddy...
...но не для десктопа
Gentoo с легким оконным менеджером:$ ps -A|wc -l112
Kernel stuff, X, fluxbox, Xterm, bash, skype, thunderbird, firefox, ooffice, gcc, ./a.out ….=> и у каждого это свое
$ grep -c processor /proc/cpuinfo4$ grep MemTotal /proc/meminfo MemTotal: 8123396 kB$ numactl -sphyscpubind: 0 1 2 3 No NUMA support available on this system.
Что делает прогрессивная часть человечества?
“...standard servers running an in-house OS. The key to achieve that performance was to disable IRQs, no syscalls, no context switching, no kernel, no memcopy, new stack etc.Basically in few hundreds ticks a packet hits the nginx or whatever application runs on it.”
Processing
Процессы как-то спроведливо и оптимально планируются по ядрам, получают свои time slice'ы...
Процессы и потоки – это удобство, для производительности есть ядра CPU и “железные потоки”
Context switch! Инвалидация TLB и L1{d,c} кэшей! Вымывание L2{d,c} и L3{d,c} кэшей+ kernel/user switch - дешев
NUMA миграция контекста - перепланирование на другую ноду
Shared memory – прямой доступ к удаленной ноде
Ulrich Drepper, “What Every Programmer Should Know about Memory”
Processing: NUMA (i7)# numactl --hardware
available: 4 nodes (0-3)
node 0 cpus: 0 4 8 12 16 20 24 28 32 36
node 0 size: 163763 MB
node 0 free: 160770 MB
node 1 cpus: 2 6 10 14 18 22 26 30 34 38
node 1 size: 163840 MB
node 1 free: 160866 MB
node 2 cpus: 1 5 9 13 17 21 25 29 33 37
node 2 size: 163840 MB
node 2 free: 160962 MB
node 3 cpus: 3 7 11 15 19 23 27 31 35 39
node 3 size: 163840 MB
node 3 free: 160927 MB
node distances:
node 0 1 2 3
0: 10 21 21 21
1: 21 10 21 21
2: 21 21 10 21
3: 21 21 21 10
Processing: best practices(1 машина – 1 задача!)
Spin locks, lock-free & Ko. - только в пределах одного процессора=> мини-кластеры внутри одной NUMA машины со своими очередями, локами и пр.
=> Минимизация разделяемых данныхex. std::shared_ptr использует reference counter – целую переменную, разделяемую и модифицируемую всеми потоками
False sharing => выравнивайте данные
=> Привязывайте процессы# dd if=/dev/zero count=2000000 bs=8192 | nc 1.1.1.1 80
16384000000 bytes (16 GB) copied, 59.4648 seconds, 276 MB/s
# taskset 0x400 dd if=/dev/zero count=2000000 bs=8192 | taskset 0x200 nc 1.1.1.1 80
16384000000 bytes (16 GB) copied, 39.8281 seconds, 411 MB/s
Memory: вытеснение страниц
Привет, Базы данных!(ex. InnoDB buffer pool)
Linux [kswapd/N], [writeback]
linux/Documentation/sysctl/vm.txt:
● vm.dirty_background_{ratio,bytes} – точка начала отложенных сбросов● vm.dirty_{ratio,bytes} – точка начала сброса страниц самим процессом● vm.dirty_expire_centisecs – время устаревания страниц● vm.dirty_writeback_centisecs – время между отложенными сбросами● vm.vfs_cache_presure – вымещение dentries/inodes vs. pagecache
active list
inactive list
add
freeP
P
P
P
P P
P
P
hit
Memory: (Transparrent) Huge Pages
Подходит не всем (ex. некоторые БД)+ меньший TLB miss, лучшая работа с page table- TLB маленький, тяжело выделить страницу
$ grep -o 'pdpe1gb\|pse' /proc/cpuinfo| sort -updpe1gb # 1GBpse # 2MB
Linux 2.6.38, для анонимных страниц (не связанных с файлами)
CONFIG_TRANSPARENT_HUGEPAGE
/sys/kernel/mm/transparent_hugepage/
madvise(..., …, MADV_HUGEPAGE)
https://lwn.net/Articles/423584/
Storage: disk IO
Page cache: open(2), read(2), write(2)
open(.., O_DIRECT): используется современными ACID СУБД для кэширования буферов данных
● Прямая работа с DMA контроллером
mmap(): использование механизмов кэширования ОС (встречается в “легких” СУБД)
● Можно адресовать 128TB в user space, при этом page table ~256GB
Storage: IO scheduler
Современные SAS/SATA контроллеры имеютсобственные аналогичные механизмы планирования
Уровень блочного ввода-вывода(между ФС и драйвером устройства)
Накапливает, переупорядочивает и отдает наввод-вывод драйверу запросы ввода-вывода
Noop (No Operation): простой FIFO без переупорядочивания, слитие запросов для снижения нагрузки на CPU при IO (полагается на TCQ/NCQ)
Deadline: циклический, почти RT (рекомендуется для СУБД)
CFQ (Complete Fair Queuing): IO QoS для процессов, имеет возможность настройки баланса между latency и пропускной способностью
Storage: IO оптимизация
Планировщик
● /sys/block/{dev}/queue/scheduler – алгоритм планировщика
● /sys/block/{dev}/queue/nr_requests – длина очереди планировщика IO (latency vs. throughput)
● /sys/block/{dev}/queue/read_ahead_kb - префетчинг
Системные вызовы
● msync() – синхронизация mmap()'ленных страниц
● fsync() – сброс кэшированных блоков
● madvise()/posix_fadvise() – access hints
● mlock() – запретить свопинг
● fallocate() – предвыделение блоков
Networking: zero-copy network (I)O
vmsplice(2), splice(2)
Только на Output
Сетевой стек пишет данные напрямуюсо страницы => перед использованиемстраницы снова нужно записать 2 размерабуфера отправки (double-buffer write)
нужен страничный аллокатор # ./nettest/xmit -s65536 -p1000000 127.0.0.1 5500
xmit: msg=64kb, packets=1000000 vmsplice() -> splice()
usr=9259, sys=6864, real=27973
# ./nettest/xmit -s65536 -p1000000 -n 127.0.0.1 5500
xmit: msg=64kb, packets=1000000 send()
usr=8762, sys=25497, real=34261
Networking: Параллельность обработки
Параллельность: MSI-X, irq round-robin$ grep eth0 /proc/interrupts$ echo 1 > /proc/irq/$q0/smp_affinity$ echo 2 > /proc/irq/$q1/smp_affinity$ echo 4 > /proc/irq/$q2/smp_affinity…
RPS (Receive Packet Steering) позволяет «разбрасывать» пакеты по softirq на разных ядрах если MSI-X недостаточно (или железо вообще не может параллелить прерывания)$ for i in `seq 0 7`; do echo fffffff > /sys/class/net/eth0/queues/rx-$i/rps_cpus;done
RFS (Receive Flow Steering) позволяет отправлять пакеты на CPU прикладного процесса
Networking: CPU offloading
Jumbo frames (MTU <= 9KB)
IP fragments на уровне сетевого адаптера (IPv4/IPv6, TCP, UDP)● GRO (Generic Receive Offloading)● GSO (Generic Segmentation Offloading)
Networking: Qdisc
(В основном про роутеры и приоритизацию потоков)
Queueing Discipline (Qdisc), tc(8)
Очереди
Дерево классов обслуживания
Фильтры определяют класс
http://www.linuxjournal.com/content/queueing-linux-network-stack
Networking: sysctl
net.core.somaxconn – listen(2) backlog
net.core.tcp_max_syn_backlog – TCP SYN backlog
net.ipv4.tcp_fin_timeout – таймаут для FIN_WAIT_2 соединений
net.ipv4.tcp_tw_recycle – переиспользование TIME-WAIT сокетов
net.ipv4.{tcp_mem, tcp_rmem, tcp_wmem} – размер TCP буферов
net.ipv4.{tcp_keepalive_time, tcp_keepalive_probes, tcp_keepalive_intvl} – управление TCP Keep-Alive
….
Linux/Documentation/networking/ip-sysctl.txt