...

Server för NUMA-balansering: Optimering av minnesåtkomst för hosting-hårdvara

Jag visar hur Server för NUMA-balansering på värdhårdvara effektiviserar minnesåtkomst och minskar latenstider genom att binda processer och data till lämplig NUMA-nod. Den avgörande faktorn är Optimering av minnesåtkomst genom lokal åtkomst, placering av uppgifter och riktad sidmigrering till Linux-värdar med många kärnor.

Centrala punkter

  • NUMA CPU:er och minne delas upp i noder; lokal åtkomst ger låg Fördröjning.
  • Automatisk NUMA-balansering flyttar sidor och placerar uppgifter nära noden.
  • VM-storlek per nod, annars finns det en risk att NUMA-skrapning.
  • Verktyg som numactl, lscpu, numad visa Topologi och använda.
  • TuningC-States, Node Interleaving från, Stora sidor, Affiniteter.

Vad NUMA är - och varför det är viktigt för hosting

NUMA delar upp ett multiprocessorsystem i Nod, som var och en innehåller sina egna processorer och lokalt minne, vilket gör att åtkomst i närheten går snabbare än åtkomst på avstånd. Medan UMA skickar alla kärnor på en gemensam väg, förhindrar NUMA flaskhalsar på grund av lokal minneskanaler per nod. I hostingmiljöer med många parallella virtuella datorer räknas varje millisekund av latens ihop, så varje begäran ger mätbara fördelar. Om du vill ha mer bakgrundsinformation kan du läsa mer om NUMA-arkitektur. För mig är en sak säker: om du förstår och använder noder får du mer bandbredd från samma hårdvara.

Automatisk NUMA-balansering i Linux-kärnan - hur fungerar det?

Kärnan skannar regelbundet delar av adressrymden och „avmapsar“ sidor så att ett hinting-fel kan uppstå. optimal nod synlig. Om felet inträffar utvärderar algoritmen om det är värt att migrera sidan eller flytta uppgiften och undviker onödiga förflyttningar. Migrering vid fel ger Uppgifter närmare den exekverande CPU:n, flyttar NUMA-placeringen processer närmare deras minne. Skannern distribuerar sitt arbete bit för bit så att overhead ligger inom ramen för den normala belastningen. Detta resulterar i kontinuerlig finjustering som minskar latensen utan att det krävs hårda pinning-regler.

Optimering av minnesåtkomst: lokalt och på distans

Lokala åtkomster använder Minneskontrollant av din egen nod och minimera väntetiderna för interconnect. Fjärråtkomst kostnadscyklar via QPI/UPI eller Infinity Fabric och minimerar därmed den effektiva åtkomsttiden. Bandbredd. Höga kärnantal förvärrar denna effekt eftersom fler och fler kärnor konkurrerar om samma anslutningar. Jag planerar därför så att het kod och aktiv data samlas på en nod. Om du bortser från detta ger du bort procentenheter som avgör svarstid eller timeout under belastningstoppar.

VM-storlekar, NUMA-trashing och host cropping

Jag dimensionerar virtuella datorer så att vCPU:er och RAM får plats i en NUMA-nod för att undvika åtkomst mellan noderna. Ofta ger 4-8 vCPU:er per nod bra prestanda. Träfffrekvens, beroende på plattform och cachehierarki. Stora sidor hjälper också till eftersom TLB fungerar mer effektivt och sidmigreringar sker mindre ofta. Om det behövs ställer jag in CPU-affinitet för latenskritiska processer för att binda trådar till lämpliga kärnor - för mer information se CPU-affinitet. Om du sprider VM:er över noder riskerar du NUMA trashing, dvs. en ping-pong av data och trådar.

Verktyg i praktiken: numactl, lscpu, numad

Med „lscpu“ läser jag Topologi och NUMA-noder, inklusive tilldelning av kärnor. „numactl -hardware“ visar mig minne per nod och tillgängliga avstånd, vilket gör det lättare att utvärdera sökvägarna. Daemon „numad“ övervakar användningen och justerar dynamiskt affiniteterna när lastcentra flyttas. För fasta scenarier använder jag „numactl -cpunodebind/-membind“ för att explicit pinna processer och minne. På så sätt kombinerar jag automatisk balansering med riktade specifikationer och kontrollerar resultatet via „perf“, „numastat“ och „/proc“.

Hur jag mäter påverkan: Nyckeltal och kommandon

Jag betygsätter alltid NUMA-Tuning via Mätserier, inte på magkänsla. Tre indikatorer har visat sitt värde: Förhållandet mellan lokala och avlägsna sidvisningar, migreringshastighet och latensfördelning (P95/P99).

  • Systemomfattandenumastat„ visar lokala/fjärranvändningar och migrerade sidor per nod.
  • Processrelaterade: „/proc//numa_maps“ avslöjar var minnet finns och hur det har fördelats.
  • Vy för schemaläggareCpus_allowed_list„ och real “Cpus_allowed„ kontrollerar om bindningar gäller.
# Systemövergripande vy
numastat
numastat -m

# Processrelaterad distribution och bindningar
pid=$(pidav )
numastat -p "$pid"
cat /proc/"$pid"/numa_maps | head
cat /proc/"$pid"/status | grep -E 'Cpus_allowed_list|Mems_allowed_list'
uppgiftsuppsättning -cp "$pid"

# Kärnräknare för NUMA-aktivitet
grep -E 'numa|migrate' /proc/vmstat

# Spårningshändelser för djupa analyser (aktiveras under en kort tid)
echo 1 > /sys/kernel/debug/tracing/events/mm/enable
sleep 5; cat /sys/kernel/debug/tracing/trace | grep -i numa; echo 0 > /sys/kernel/debug/tracing/events/mm/enable

Jag jämför i varje enskilt fall A/B: obundet vs. bundet, automatisk balansering på/av och olika VM-slices. Målet är en tydlig minskning av fjärråtkomst och migreringsbrus samt stramare P95/P99-latenstider. Först när de uppmätta värdena är stabilt bättre kommer jag att ta över inställningen.

BIOS- och firmware-inställningar som verkligen fungerar

Jag stänger av „Node Interleaving“ i BIOS så att NUMA-strukturen förblir synlig och kärnan lokal kan planera. Reducerade C-lägen stabiliserar latenspikar eftersom kärnorna är mindre benägna att hamna i djupa sömnlägen, vilket sparar uppvakningstid. Jag allokerar minneskanaler symmetriskt så att varje nod kan utnyttja sin maximala minneskapacitet. Bandbredd uppnått. Jag testar prefetchers och RAS-funktioner med arbetsbelastningsprofiler, eftersom de hjälper eller stjälper beroende på åtkomstmönstret. Jag mäter varje förändring mot en baslinje och först därefter antar jag inställningen permanent.

Kernel- och sysctl-parametrar som gör skillnad

Finjustering av kärnan hjälper mig, Overhead och Svarstid av balanseraren för att matcha arbetsbelastningen. Jag börjar med konservativa standardvärden och arbetar mig framåt steg för steg.

  • kernel.numa_balanseringPå/av för automatisk balansering. Jag låter den vara påslagen vid rörliga laster och stänger av den som ett test vid strikt fastspända specialtjänster.
  • kernel.numa_balansering_scan_fördröjning_msVäntetid före den första skanningen efter att processen skapats. Välj större om många kortlivade uppgifter körs; mindre för långvariga tjänster som kräver snabb närhet.
  • kernel.numa_balansering_scan_period_min_ms / _max_msBandbredd för skanningsintervallen. Snäva intervall ökar responsen, men också CPU-belastningen.
  • kernel.numa_balansering_skanning_storlek_mbAndel av adressrymden per skanning. För stor genererar hint-felstormar, för liten reagerar långsamt.
  • vm.zon_återvinning_läge: Om det är ont om minne föredrar kärnan lokal återvinning i stället för fjärrtilldelning. För allmänna arbetsbelastningar för hosting lämnar jag vanligtvis 0; För lokala minnestjänster som är mycket känsliga för fördröjning testar jag noggrant högre värden.
  • Transparenta stora sidor (THP): Under „/sys/kernel/mm/transparent_hugepage/{enabled,defrag}“ ställer jag vanligtvis in madvise och konservativ defragmentering. Hårda „alltid“-profiler ger TLB-fördelar, men riskerar att stanna upp på grund av komprimering.
  • sched_migration_cost_ns: Kostnadsberäkning för migrering av uppgifter. Högre värden dämpar omfördelningen av aggressiva schemaläggare.
  • cgroups cpusetMed cpuset.cpus och cpuset.mems Jag separerar tjänsterna rent per nod och ser till att Första beröringen förblir inom tillåtna noder.
# Exempel: konservativ men responsiv balansering
sysctl -w kärna.numa_balansering=1
sysctl -w kärnan.numa_balansering_scan_fördröjning_ms=30000
sysctl -w kärnan.numa_balansering_scan_period_min_ms=60000
sysctl -w kärnan.numa_balansering_scan_period_max_ms=300000
sysctl -w kärnan.numa_balansering_scan_storlek_mb=256

# Använd THP med försiktighet
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
echo defer > /sys/kernel/mm/transparent_hugepage/defrag

Det är fortfarande viktigt: Ändra endast en justerskruv per testomgång och testa effekten mot samma belastningskurva. Det är så jag skiljer på orsak och verkan.

Placera arbetsbelastningen rätt: Databaser, cacher, containrar

Databaser gynnas när buffertpooler förblir lokala per NUMA-nod och trådar är bundna nära sina heaps. I cacheminnen i minnet ställer jag in sharding till Nod för att undvika fjärrhämtningar. Containerplattformar tar emot gränser och förfrågningar så att pods inte hoppar mellan noder. För minnesreservationer använder jag Huge Pages, vilket gör det enklare att lagra hotsets i Cacher passar. I följande tabell sammanfattas strategier och typiska effekter i kompakt form.

Strategi Användning Förväntad effekt Ledtråd
Första beröringen Databaser, JVM-högar Tilldelning på lokal sida Utför initialisering på målnoden
Interleave Bredt fördelad belastning Jämn fördelning Inte optimalt för hotspots
Fastsättning av uppgifter Latenskritiska tjänster Konstant latens Mindre flexibel vid lastförändringar
Automatisk balansering Blandade arbetsbelastningar Dynamisk närhet Vägning av omkostnader mot vinst
Stora sidor Stora högar, cacher Färre TLB-missar Planera rena bokningar

Virtualisering: Virtuell NUMA, anpassning av schemaläggare och gäster

Virtual NUMA skickar värdtopologin till gästoperativsystemet i en förenklad form så att den första kontakten och Allokator arbeta på ett förnuftigt sätt. Hypervisor-schemaläggare uppmärksammar nodnärhet när de distribuerar vCPU:er och migrerar virtuella datorer. Jag anpassar sällan stora virtuella datorer över flera noder om inte arbetsbelastningen strömmar mycket och drar nytta av interleave. I gästen anpassar jag JVM:ernas eller databasernas heaps så att de förblir lokala på synliga NUMA-noder. För minneshantering i gästen kan du titta på Virtuellt minne, för att tämja sidstorlekar och byten.

Närhet till PCIe: NVMe och NIC i rätt noder

Om möjligt tilldelar jag NVMe SSD-enheter och snabba nätverkskort till den nod där Arbetsbelastning är igång. Detta förhindrar I/O-förfrågningar från att korsa interconnect och lägga till latens. Jag binder multikö-NIC:er till kärnuppsättningar i en nod med RSS/RPS så att IRQ:erna förblir lokala. För lagringsstackar är det värt att dela upp trådpoolerna nod för nod. Om du är uppmärksam på detta kommer du att märkbart minska P99-latenserna och skapa utrymme för belastningstoppar.

IRQ och köaffinitet i praktiken

Jag kontrollerar först vilken NUMA-nod enheter och pinna IRQ:er och köer på lämpligt sätt. Detta säkerställer att datavägens lokalisering bibehålls.

# Mappning av enhet till nod
cat /sys/class/net/eth0/enhet/numa_node
cat /sys/block/nvme0n1/enhet/numa_node

# Ställ in IRQ-affinitet specifikt (exempel: kärnor 0-7 i en nod)
irq=
echo 0-7 > /proc/irq/$irq/smp_affinity_list

# Binda NIC-köer till kärnor (RPS/RFS)
for q in /sys/class/net/eth0/queues/rx-*; do echo 0-7 > "$q"/rps_cpus; done
sysctl -w net.core.rps_sock_flow_entries=32768
for q in /sys/class/net/eth0/queues/rx-*; do echo 4096 > "$q"/rps_flow_cnt; done

# Förbättra NVMe-köaffinitet
echo 2 > /sys/block/nvme0n1/queue/rq_affinity
cat /sys/block/nvme0n1/queue/scheduler # "none" föredras

„Jag kör “irqbalance" med nodmedvetenhet eller ställer in den på Undantag för hot path-avbrott. Resultatet är stabilare latenser, färre IRQ-hopp mellan noderna och en mätbar ökning av antalet lokala I/O-träffar.

Statisk bindning vs. dynamisk balansering - en medelväg

Jag använder „taskset“ och cgroups för att sätta hårda regler när deterministiska Fördröjning räknar. Jag låter automatisk NUMA-balansering vara aktiv när belastningen förändras och jag behöver adaptiv närhet. En blandning fungerar ofta bäst: hårda stift för hotpaths, mer öppna gränser för extraarbete. Jag kontrollerar regelbundet om migreringarna ökar märkbart, eftersom det är ett tecken på dålig planering. Målet är fortfarande att välja data- och trådplatser på ett sådant sätt att migrering förblir sällsynt men möjlig.

NUMA i containrar och Kubernetes

Jag tar med en behållare cpusets och Stora sidor på linjen. Jag tilldelar pods/containers till en NUMA-nod genom att lagra konsekventa CPU- och minnesmängder. I orkestreringar ställer jag in policyer som gynnar tilldelningar av enstaka noder och därmed respekterar första kontakten.

  • Container runtime: „-cpuset-cpus“ och „-cpuset-mems“ håller ihop uppgifter och minne; tilldelar stora sidor som resurser.
  • Topologi/CPU-hanterareStrikta eller föredragna tilldelningar säkerställer att relaterade kärnor och minnesområden tilldelas.
  • Garanterad QoSFasta önskemål/begränsningar minimerar omfördelning av schemaläggaren.

Jag delar medvetet upp sidovagnar och hjälpprocesser till andra kärnor inom i samma nod så att den heta sökvägen förblir ostörd men inte deltar i tävlingen mellan noderna.

Förståelse för CPU-topologier: CCD/CCX, SNC och Cluster-on-Die

Nuvarande server-CPU:er delar upp socklarna i Underdomäner med sina egna cacher och vägar. Jag tar hänsyn till detta när jag skär kärnor / högar:

  • AMD EPYCCCD/CCX och „NUMA per socket“ (NPS=1/2/4) påverkar hur finfördelad NUMA är. Fler noder (NPS=4) ökar lokaliteten, men kräver ren pinning.
  • IntelSub-NUMA Clustering (SNC2/4) delar upp LLC i kluster. Bra för minnesbundna belastningar, förutsatt att operativsystemet och arbetsbelastningen är nodmedvetna.
  • L3 närhetJag binder trådar som använder samma heaps till samma L3-kluster för att spara koherenstrafik och hopp mellan klustren.

Dessa alternativ fungerar som en multiplikator: om de används på rätt sätt ökar de Lokalitet Dessutom - felaktigt konfigurerade ökar de fragmenteringen och fjärrtrafiken.

Steg-för-steg-introduktion och rollback-plan

Jag har aldrig introducerat „big bang“ NUMA-tuning. En motståndskraftig Planera undviker överraskningar:

  1. BaslinjeHårdvarutopologi, P50/P95/P99-latenstider, genomströmning, numastat-frekvensmätning.
  2. HypotesFormulera ett specifikt mål (t.ex. fjärråtkomst -30%, P99 -20%).
  3. Ett stegÄndra endast en inställningsskruv (t.ex. VM cut, cpuset, THP policy, scanningsintervall).
  4. KanariefågelTesta på 5-10% av flottan under verklig belastning, håll rollback redo.
  5. VärderingJämför mätvärden, definiera regressionsfönster, logga biverkningar.
  6. UtrullningRulla ut axel för axel, mät igen efter varje axel.
  7. UnderhållMät på nytt varje kvartal (uppdateringar av kärnan, den fasta programvaran och arbetsbelastningen ändrar optimum).

Detta säkerställer att förbättringarna är reproducerbara och kan återställas inom några minuter om ett fel skulle uppstå.

Vanliga misstag - och hur du undviker dem

Ett typiskt felsteg är att aktivera node interleaving i BIOS, vilket döljer NUMA-topologin och Balansering svårare. Lika ofördelaktigt: virtuella datorer med fler vCPU:er än vad en nod erbjuder, plus orenligt reserverade stora sidor. Vissa administratörer lägger allt hårt och förlorar därmed all flexibilitet när arbetsbelastningen förändras. Andra förlitar sig helt på kärnan, även om hårda hotspots kräver tydliga regler. Jag registrerar mätserier, identifierar avvikande värden tidigt och justerar inställningar och policyer steg för steg.

  • THP „alltid“ utan kontroll: Oplanerad komprimering stör latensen. Jag föredrar att använda „madvise“ och reservera stora sidor specifikt.
  • vm.zon_återvinning_läge för aggressiv: Lokal återvinning kan göra mer skada än nytta vid fel tillfälle. Mät först, skärp sedan.
  • irqbalance blindOkritiska IRQ:er flyttas mellan noder. Jag ställer in undantag eller fasta masker för hotpaths.
  • Blandning av interleave + hård pinningMotsägelsefull politik skapar ping-pong. Jag förordar en tydlig linje för varje tjänst.
  • Oren cpusetsContainrar ser en nod, men mappar minne till andra noder. Ställ alltid in „cpuset.mems“ konsekvent med CPU-uppsättningen.
  • Sub-NUMA-funktioner aktiverade men inte använda: Fler noder utan planering ökar fragmenteringen. Slå bara på efter tester.

Kortfattat sammanfattat

NUMA Balancing Server sammanför processer och data på ett målinriktat sätt, vilket gör att lokala åtkomster blir mer frekventa och mer effektiva. Fördröjningar blir kortare. Med en lämplig VM-storlek, ren BIOS-konfiguration och verktyg som numactl skapas en tydlig topologi som kärnan utnyttjar. Virtuell NUMA, stora sidor och affiniteter kompletterar den automatiska balanseringen i stället för att ersätta den. Genom att ansluta I/O-enheter nära noderna och använda hotpaths elimineras dyr fjärråtkomst. På så sätt kan hårdvaran skalas på ett tillförlitligt sätt och varje CPU-sekund ger mer nyttolast.

Aktuella artiklar