Repository navigation
Commit ee79e66
committed
mem: add HG_MALLOC, a hugepage-backed slab allocator, with CPU pinning
A fifth core allocator, selectable at runtime with -a/-s/-k HG_MALLOC
alongside F_MALLOC, Q_MALLOC, HP_MALLOC and F_PARALLEL_MALLOC, plus the
CPU pinning it needs to be worth having.
Under load OpenSIPS spends a surprising share of its CPU inside the
allocator - profiling a topology-hiding proxy put allocator self-time
between 9.5% and 22.8% of total CPU depending on which of the existing
four was in use. That is a large enough budget to be worth attacking
directly rather than by shaving call paths elsewhere.
The design takes two things the existing allocators do not. First, huge
pages: the arena is acquired through a four-tier ladder - MAP_HUGETLB,
then MADV_HUGEPAGE, then MADV_COLLAPSE, then plain 4K - and each tier is
verified through /proc rather than assumed from a kernel version or a
sysfs setting, degrading quietly and logging what it actually got.
Second, and this turns out to matter more: allocation is served from
fixed size classes off a per-process free stack, so the hot path takes no
lock and touches no shared cache line. Measuring the tiers separately
showed huge pages are only about a fifth of the win - tier 4, with huge
pages entirely disabled, still beat F_MALLOC by 2.8x - so the allocator
is worth using on machines with no hugetlb pool at all.
Keeping free lists per process only pays while a process stays on one
CPU, which OpenSIPS had no way to arrange: there was no affinity support
in the core. So this adds it. pin_workers pins every worker round-robin;
pin_udp_cpus / pin_tcp_cpus / pin_timer_cpus / pin_module_cpus confine one
kind of process to a CPU list; and a UDP listener may name pin_cpus of
its own, which is finer still and lets a public interface and a private
one keep off each other's cores. Precedence runs listener, then process
type, then unpinned. Every choice is intersected with the set the process
is already allowed to run on, read back with sched_getaffinity(), so a
cpuset or container can only ever narrow it, never widen it. The CPU is
picked by occupancy over the processes running at that moment rather than
from a process-table slot, which is what makes it behave under
auto-scaling, where slots are freed and reused.
One process is deliberately not pinned to a single CPU: TCP main is
multithreaded - its IO pool defaults to one thread per online CPU - so a
single-CPU pin would serialise every one of those threads onto one core.
It is confined to the whole pin_tcp_cpus list instead, before its threads
are created so they all inherit it, and it does not count as occupying a
slot when the single-threaded TCP workers pick theirs.
Measured on the topology-hiding path, HG_MALLOC costs 10-24% less CPU
than F_MALLOC at matched load in containers, and 20-45% less on a
dispatcher load balancer holding 20,000 calls in flight, with the gap
widening as the load rises. It is not free: the arena is pre-faulted and
mlock()ed at startup, so it is resident from the first second, and the
size classes need roughly twice the shm F_MALLOC does for the same
traffic. Both are documented, along with what running short looks like -
loud in the log, but not fatal, which is the trap.
CPU pinning is Linux-only and compiled out elsewhere with a warning
rather than guessed at. The allocator itself is portable: ARM alignment
and page-size assumptions are handled and asserted, and it has been
cross-compiled for aarch64 and armv7, though not yet run on ARM hardware.1 parent c05b576 commit ee79e66
32 files changed
Lines changed: 3615 additions & 14 deletions
File tree
- mem
- modules/hgstress
- net
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
100 | 105 | | |
101 | 106 | | |
102 | 107 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
524 | 524 | | |
525 | 525 | | |
526 | 526 | | |
| 527 | + | |
527 | 528 | | |
528 | 529 | | |
529 | 530 | | |
530 | 531 | | |
| 532 | + | |
531 | 533 | | |
532 | 534 | | |
533 | 535 | | |
| |||
558 | 560 | | |
559 | 561 | | |
560 | 562 | | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
561 | 567 | | |
562 | 568 | | |
563 | 569 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
246 | 246 | | |
247 | 247 | | |
248 | 248 | | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
249 | 254 | | |
250 | 255 | | |
251 | 256 | | |
| |||
318 | 323 | | |
319 | 324 | | |
320 | 325 | | |
| 326 | + | |
321 | 327 | | |
322 | 328 | | |
323 | 329 | | |
| |||
480 | 486 | | |
481 | 487 | | |
482 | 488 | | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
483 | 494 | | |
484 | 495 | | |
485 | 496 | | |
| |||
601 | 612 | | |
602 | 613 | | |
603 | 614 | | |
| 615 | + | |
604 | 616 | | |
605 | 617 | | |
606 | 618 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
182 | 182 | | |
183 | 183 | | |
184 | 184 | | |
| 185 | + | |
185 | 186 | | |
186 | 187 | | |
187 | 188 | | |
| |||
352 | 353 | | |
353 | 354 | | |
354 | 355 | | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
355 | 361 | | |
356 | 362 | | |
357 | 363 | | |
| |||
459 | 465 | | |
460 | 466 | | |
461 | 467 | | |
| 468 | + | |
462 | 469 | | |
463 | 470 | | |
464 | 471 | | |
| |||
761 | 768 | | |
762 | 769 | | |
763 | 770 | | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
764 | 774 | | |
765 | 775 | | |
766 | 776 | | |
| |||
1257 | 1267 | | |
1258 | 1268 | | |
1259 | 1269 | | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
1260 | 1280 | | |
1261 | 1281 | | |
1262 | 1282 | | |
| |||
2793 | 2813 | | |
2794 | 2814 | | |
2795 | 2815 | | |
| 2816 | + | |
2796 | 2817 | | |
2797 | 2818 | | |
2798 | 2819 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
98 | 105 | | |
99 | 106 | | |
100 | 107 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
121 | 121 | | |
122 | 122 | | |
123 | 123 | | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
124 | 129 | | |
125 | 130 | | |
126 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
99 | 100 | | |
100 | 101 | | |
101 | 102 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
| 157 | + | |
157 | 158 | | |
158 | 159 | | |
159 | 160 | | |
| |||
0 commit comments