Vladislav Shpilevoy PRO
Database C developer at Tarantool. Backend C++ developer at VirtualMinds.
I categorize the primary sources of code performance degradation into three groups: - Thread contention. For instance, too hot mutexes, overly strict order in lock-free operations, and false sharing. - Heap utilization. Loss is often caused by frequent allocation and deallocation of large objects, and by the absence of intrusive containers at hand. - Network IO. Socket reads and writes are expensive due to being system calls. Also they can block the thread for a long time, resulting in hacks like adding tens or hundreds more threads. Such measures intensify contention, as well as CPU and memory usage, while neglecting the underlying issue. I present a series of concise and straightforward low-level recipes on how to gain performance via code optimizations. While often requiring just a handful of changes, the proposals might amplify the performance N-fold. The suggestions target the mentioned bottlenecks caused by certain typical mistakes. Proposed optimizations might render architectural changes not necessary, or even allow to simplify the setup if existing servers start coping with the load effortlessly. As a side effect, the changes can make the code cleaner and reveal more bottlenecks to investigate.
I categorize the primary sources of code performance degradation into three groups: - Thread contention. For instance, too hot mutexes, overly strict order in lock-free operations, and false sharing. - Heap utilization. Loss is often caused by frequent allocation and deallocation of large objects, and by the absence of intrusive containers at hand. - Network IO. Socket reads and writes are expensive due to being system calls. Also they can block the thread for a long time, resulting in hacks like adding tens or hundreds more threads. Such measures intensify contention, as well as CPU and memory usage, while neglecting the underlying issue. I present a series of concise and straightforward low-level recipes on how to gain performance via code optimizations. While often requiring just a handful of changes, the proposals might amplify the performance N-fold. The suggestions target the mentioned bottlenecks caused by certain typical mistakes. Proposed optimizations might render architectural changes not necessary, or even allow to simplify the setup if existing servers start coping with the load effortlessly. As a side effect, the changes can make the code cleaner and reveal more bottlenecks to investigate.
Algorithm for a multithreaded task scheduler for languages like C, C++, C#, Rust, Java. C++ version is open-sourced. Features: (1) formally verified in TLA+, (2) even CPU usage across worker threads, (3) coroutine-like functionality, (4) almost entirely lock-free, (5) up to 10 million RPS per thread. Key points for the potential audience: fair task scheduling with multiple worker threads; open source; algorithms; TLA+ verified; up to 10 million RPS per thread; for backend programmers; algorithm for languages like C++, C, Java, Rust, C# and others.
Algorithm for a multithreaded task scheduler for languages like C, C++, C#, Rust, Java. C++ version is open-sourced. Features: (1) formally verified in TLA+, (2) even CPU usage across worker threads, (3) coroutine-like functionality, (4) almost entirely lock-free, (5) up to 10 million RPS per thread. Key points for the potential audience: fair task scheduling with multiple worker threads; open source; algorithms; TLA+ verified; up to 10 million RPS per thread; for backend programmers; algorithm for languages like C++, C, Java, Rust, C# and others.
Использование асинхронной репликации может приводить к потере транзакции, если мастер-узел выходит из строя сразу после ее коммита. Синхронная репликация позволяет добиться репликации транзакции на заданное число реплик до ее коммита, когда изменения становятся видны пользователю. В данном докладе рассматривается один из таких алгоритмов - Raft, и его применение в СУБД Tarantool.
Tarantool 2.6 was released in October of 2020. This is the biggest release in several years, which brings beta version of synchronous replication and transaction manager for memtx storage engine. The talk sheds more light on the key features of the release.
Usage of asynchronous replication can lead to transaction loss if the master node fails immediately after its commit. Synchronous replication helps to achieve replication of a transaction on a specified number of replicas before its commit, before the changes become visible to the user. This talk describes one of such algorithms - Raft, and its application in Tarantool DBMS.
Использование асинхронной репликации может приводить к потере транзакции, если мастер-узел выходит из строя сразу после ее коммита. Синхронная репликация позволяет добиться репликации транзакции на заданное число реплик до ее коммита, когда изменения становятся видны пользователю. В данном докладе рассматривается один из таких алгоритмов - Raft, и его применение в СУБД Tarantool.
Users and groups, rights. Attributes and access rights of files and processes. Process groups, sessions. /etc/passwd, /etc/group. Sticky bit. Process daemonization. Object attributes.
Advanced IO. Non-blocking IO operations. File blocks: flock, lockf, fcntl. Multiplexed IO: select, poll, kqueue. Async IO: aio_read/write.
Network. Short history from ARPANET. Canonical OSI model, real TCP/IP model, protocol stack. Network implementation in the kernel. User space interface socket(), connect(), close(). TCP and UDP.
SWIM is a protocol for detection and monitoring of cluster nodes, distribution of events and data between them. The protocol is lightweight, decentralized and its speed does not depend on cluster size. The talk describes how SWIM protocol is organized, how and with which extensions it is implemented in Tarantool.
IPC. Pipe, FIFO. XSI: message queue, semaphore, shared memory. POSIX semaphore. Sockets: API, byte ordering. Domain sockets.
Threads in Linux, kernel representation. Difference from processes. POSIX. Synchronisation: mutex, rw-lock, condition variable, spin lock, barrier. Atomic operations. Attributes of thread and synchronisation object.
SWIM - это протокол обнаружения и мониторинга узлов кластера, распространения событий и данных между ними. Протокол особенен своей легковесностью, децентрализованностью и независимостью скорости работы от размера кластера. В докладе рассказывается о том, как устроен протокол SWIM, как и с какими расширениями он реализован в Тарантуле.
Storage devices. File system and the kernel. Virtual file system. Files and their types: block, char, network. Representation in the kernel: inode. Sectors. IO schedulers - elevators: Linus, Deadline, Anticipatory, CFQ, Noop. Page cache. Page nowrite/writethrough/writeback. File work modes - buffered, unbuffered, line.
SWIM - это протокол обнаружения и мониторинга узлов кластера, распространения событий и данных между ними. Протокол особенен своей легковесностью, децентрализованностью и независимостью скорости работы от размера кластера. В докладе рассказывается о том, как устроен протокол SWIM, как и с какими расширениями он реализован в Тарантуле.
Interrupts. Hardware and software, their nature, purpose. Interrupt handling. Purpose of signals, how they work. Signals handling, execution context, longjmp, top and bottom halves. /proc/interrupts. signal, sigaction.
SWIM - это протокол обнаружения и мониторинга узлов кластера, распространения событий и данных между ними. Протокол особенен своей легковесностью, децентрализованностью и независимостью скорости работы от размера кластера. В докладе рассказывается о том, как устроен протокол SWIM, как и с какими расширениями он реализован в Тарантуле.
Virtual and physical memory. Cache, cache line, cache levels, cache coherence, false sharing. High and low memory. Page tables. User space and kernel space memory, layout. Functions brk, madvice, mmap. Malloc and alternative libraries.
Work modes: privileged, normal. Memory, its sections. Process resources - descriptors, locks. Process interrupts: exceptions, hardware, scheduling. Work context: user, kernel, signal. Interaction with the kernel - system calls: what are they, how parameters are passed and a result returned.
The kernel. Process and its representation in the kernel. Process states, lifecycle. Types of process scheduling: preemptive and cooperative. Process schedulers, and IO Bound vs Processor Bound processes, details of scheduling. 'Nice' value and priorities. Timeslice - scheduling atom. CFS scheduler.
Linux vs Unix. Microkernel. FreeBSD, Ubuntu, Mac, System III, V, Unix time-sharing system, 4.4BSD. Standard: ISO C, POSIX, Single Unix Specifications. Organisations: Open Group, IEEE.
Прерывания. Аппаратные и программные, их природа, назначение. Обработка прерываний. Сигналы - зачем нужни они, как устроены. Обработка сигналов, особенности, контекст выполнения, longjump, top and bottom halves. /proc/interrupts. signal, sigaction.
Пользователи, группы, права. Атрибуты и права доступа файлов и процессов. Группы процессов, сессии. /etc/passwd, /etc/group. Sticky bit. Демонизация процесса. Атрибуты глобальных объектов: локов, памяти.
Advanced IO. Неблокирующие IO операции. Блокировка файла: flock, lockf, fcntl. Multiplexed IO: select, poll, kqueue. Async IO: aio_read/write.
Сеть, краткая история от ARPANET. Каноническая модель OSI, реальная TCP/IP, стек протоколов. Реализация сетевого взаимодействия в ядре. Пользовательский интерфейс socket, connect, close, send, recv. TCP и UDP.
IPC. Pipe, FIFO. XSI: message queue, semaphore, shared memory. POSIX semaphore. Sockets: API, byte ordering. Доменные сокеты.
Потоки в linux, представление в ядре. Отличие от процессов. POSIX. Синхронизация: mutex, rw-lock, condition variable, spin lock, barrier. Атомарные операции. Атрибуты потоков и объектов синхронизации.
Файловая система и ядро. Виртуальная ФС. Файлы и типы: block, char, network. Представление в ядре: inode. Секторы. Планировщики IO операций - elevator-ы: Linus, Deadline, Anticipatory, CFQ, Noop. Page cache. Page nowrite/writethrough/writeback. Работа с файлом - buffered, unbuffered, line.
Виртуальная и физическая память. Cache, cache line, cache levels, cache coherence, false sharing. High and low memory, области памяти. Page tables. Память ядра и процесса пользователя, разметка, вызовы: kmalloc, vmalloc, brk, madvice, mmap, pmap. Malloc, его альтернативы.
Режимы работы: привелигированный, обычный. Память, разбивка на секции. Ресурсы процесса - дескрипторы, локи. Прерывания процесса: исключения, аппаратные, шедулинг. Контексты работы: пользователь, ядро, сигнал. Обращения к ядру - системные вызовы: как определяются, передача параметров, возврат результата.
Ядро. Процесс и его представление в ядре. Состояния процесса, цикл жизни. Типы совместной работы процессов: preemptive и cooperative. Планировщики и IO Bound vs Processor Bound процессы, особенности планирования. Вызов nice, приоритеты. Единица планирования - timeslice. Планировщики в ядре, CFS. Вызовы sched_yield и sched_setaffinity.
Linux vs Unix. Microkernel. FreeBSD, Ubuntu, Mac, System III, V, Unix time-sharing system, 4.4BSD. Стандарты: ISO C, POSIX, Single Unix Specifications. Организации: Open Group, IEEE.