...

Att tolka Linux NUMA-statistiken på rätt sätt

Linux NUMA Statistiken visar mig hur väl processerna hanterar sitt lokala minne och var fjärråtkomst ökar latensen. Jag förklarar hur jag tolkar dessa siffror på ett målinriktat sätt, utvärderar trender över tid och utifrån detta tar fram tydliga åtgärder för optimering av Prestanda avleda.

Centrala punkter

  • Att förstå räknare: numa_hit, numa_miss, numa_foreign, local_node, other_node, interleave_hit
  • Utvärdera sammanhanget: Lastprofil, topologi, typ av arbetsbelastning
  • Mäta trender: Före/efter och över tidsintervall
  • Granska processer: Systemomfattande jämfört med per process
  • Tillämpa inställningar: Affinitet, riktlinjer, placering

Vad NUMA-statistiken egentligen visar

Jag betraktar NUMA-siffror som en karta över Förvaringsplats och datavägar. En hög numa_hit betyder att allokeringarna har hamnat på den önskade noden. Däremot indikerar numa_miss att kärnan har tvingats utnyttja en annan nod. Räknaren numa_foreign visar motsvarigheten på målnoden och kompletterar bilden. Med local_node och other_node kan jag se om åtkomsten skedde lokalt eller om fjärrminne användes.

Dessa värden ska aldrig tolkas isolerat, eftersom Arbetsbelastning reagerar mycket olika. Korta processer ger enstaka missar utan att den totala prestandan påverkas märkbart. Interleave-policyer å sin sida skapar avsiktligt spridda tilldelningar, vilket gör att interleave_hit ökar. Därför kontrollerar jag alltid den avsedda policyn och den aktuella belastningen. Först därefter avgör jag om ett värde kräver åtgärder eller om det passar in i designen.

För mig är kärnidén följande: räknare ger signaler, inte bedömningar. Jag letar efter mönster över tid, inte enskilda siffror. På så sätt kan jag se om en förändring i systemet förskjuter lokaliteten. Först när jag har denna trendbild bedömer jag om jag ska flytta processer, anpassa policyer eller ställa in CPU-bindningar. Varje NUMA-analys börjar därför med en tydlig frågeställning och repeterbara mätpunkter.

Tolka kärnräknare i sitt sammanhang

Jag jämför alltid numa_hit och jämför numa_miss med varandra, istället för att utvärdera absoluta värden. Om missarna ökar kontrollerar jag samtidigt utvecklingen av numa_foreign på den potentiella målnoden. Om båda stämmer överens tyder det på en verklig förskjutning och inte enbart en artefakt från avläsningen. local_node och other_node kompletterar denna bild genom att visa de faktiska åtkomsterna. På så sätt kan jag se om en allokering visserligen började lokalt, men om verksamheten senare läste från mer avlägset minne.

En enda hög other_node Det stör mig inte om arbetsbelastningen fördelas medvetet. Webbservrar med många arbetare drar däremot nytta av en konsekvent lokalisering. Därför tittar jag på enskilda processer, inte bara på helhetsbilden. Så fort enskilda tjänster avviker från mönstret granskar jag deras placering. Först när fel ökar systemövergripande letar jag efter orsaker som har med topologi eller belastning att göra.

Jämförelser över tid: en mätrutin som ger resultat

Jag avläser mätarställningarna i början och slutet av en Slutfas och beräknar skillnaden. Enstaka värden döljer effekter, medan skillnader visar på förändringar. Upprepade intervall på till exempel 30 till 60 sekunder räcker ofta för att upptäcka trender. Efter driftsättningar, kärnuppdateringar eller hårdvaruförändringar jämför jag samma intervall på nytt. Om det då uppstår fler missar eller om local_node förskjuts, föreligger en verklig förändring.

Sådana tidsserier omfattar Placeringsfel snabbare än ögonblicksbilder. Jag korrelerar linjerna med CPU-utnyttjande, kontextbyten och minnesanvändning per nod. På så sätt kan jag se om flaskhalsar i en nods RAM-minne leder till avvikande beteenden. Eller om nya processer rubbar balansen i noderna. Den rena andelen träffar och missar redovisar jag alltid som en kurva, inte som ett enskilt tal.

Granska hela systemet, och zooma sedan in på processerna

Jag börjar med helhetsbilden från numastat och granskar först därefter enskilda processer. Denna ordning sparar tid, eftersom många effekter blir synliga på övergripande nivå. För processvyn använder jag den processspecifika utskriften för att isolera tjänster som sticker ut. Så snart kandidaterna är fastställda justerar jag Placering om CPU- och minnesanvändning. Praktiska tips om detta sammanfattas i artikeln om CPU- och minnesaffinitet.

Särskilt när det gäller Java-tjänster, PHP-FPM eller databaser räcker det ofta med en ren Affinitet, för att avsevärt minska missarna. Containerorkestrering döljer ofta dessa problem, eftersom schemaläggare fördelar resurser utan hänsyn till NUMA. Därför kontrollerar jag nodtilldelningen per pod eller VM. Om CPU-uppsättningar och RAM-tilldelning stämmer överens ökar local_node märkbart. Vissa problem löser sig så snart processen körs nära den nödvändiga datamängden.

Översikt över NUMA-räknare (tabell)

När jag utvärderar ett nytt system fyller jag i följande tabell så att jag kan se varje Nyckeltal snabbt kunna placera in. Den visar betydelse, typisk tolkning och möjliga åtgärder. Jag ser den inte som ett fast schema, utan som en checklista. Det avgörande är fortfarande jämförelsen med belastningsprofilen och servertopologin. Först med detta sammanhang kan jag fatta ett välgrundat beslut.

räknare Betydelse tolkning Tillvägagångssätt
numa_hit Allokering vid önskad nod Ett högt värde är positivt Behålla placeringen
numa_miss Allokeringen flyttades till andra noder Ökad risk för fördröjningar Kontrollera Affinity/Policy
numa_utländsk Främmande allokering på denna nod Motsvarighet till numa_miss Analysera målnoder
local_node Åtkomst till lokalt lagringsutrymme Ju högre, desto billigare Processen närmare RAM-minnet
other_node Åtkomst till fjärrlagring Bara lite oroande, utan avsikt Kontrollera topologi/belastning
interleave_hit Träffar vid interleave-fördelning Förväntat vid interleave-policy Bedöma jämnheten

Med detta Översikt då kan jag snabbare avgöra när jag ska ingripa. En ökning av numa_miss utan någon förklarlig förändring utlöser en orsaksanalys. Om interleave_hit förblir högt kontrollerar jag om policyn är avsiktligt aktiv. Om other_node ökar utan att belastningen stiger undersöker jag om det finns arbetsbelastningar som tränger undan andra. På så sätt blir tabellen en utgångspunkt för målinriktade åtgärder.

Att förstå och använda NUMA-topologi

Innan jag börjar träna kontrollerar jag Topologi på servern: socklar, kärnor, minneskanaler, latensvägar. Om en process körs på sockel 0 men lagrar arbetssatserna på sockel 1 ökar åtkomsttiden. Detta minskar genomströmningen och gör att svarstiderna varierar. Särskilt minneskrävande tjänster märker varje onödig avstånd. Jag placerar därför dataintensiva processer på noder med tillräckligt med ledigt RAM-minne.

Asymmetriska Anslutningar förstärker effekterna, till exempel när en nod använder färre kanaler. I sådana fall flyttar jag den cachade datamängden på ett målinriktat sätt istället för att fördela processen. Jag konfigurerar VM- och container-värdar så att varje instans får en konsekvent nodkoppling. På så sätt minskar jag den fjärrdataöverföringen utan att begränsa kvoterna. Maskinens fysiska begränsningar sätter ramarna, och jag håller mig till dem.

Att förstå interleave och balansering på rätt sätt

Interleave-policyer fördelar minnet medvetet över noderna så att Genomströmning per process ökar eller att hotspots minskar. I den här konfigurationen räknas höga interleave_hit som önskvärda. Jag kontrollerar då framför allt jämnheten, inte den absoluta lokaliteten. AutoNUMA respektive NUMA-balansering kan hjälpa, men inte i alla situationer.

Jag avgör utifrån situationen om automatisk Balansering förblir aktiv. För stabila, långvariga tjänster föredrar jag fasta bindningar. Vid varierande belastning kan AutoNUMA reagera på ett lämpligt sätt. En bra översikt över fördelar och risker finns i artikeln NUMA-balansering. Först när målet och ramarna är klara väljer jag det lämpliga läget.

Arbetsbelastningsmönster: databaser, virtuella maskiner, webbtjänster

Databaser är känsliga för Fördröjning mellan CPU och RAM. Därför håller jag instansen, buffertcachen och aktiva shards på samma nod. Virtuella maskiner drar nytta av tydliga CPU-uppsättningar plus nodens RAM, så att gästoperativsystemen ser konsekventa vägar. Webbtjänster med många arbetare fungerar bäst när arbetsgrupper förblir bundna till en nod. För lagringsstrategin använder jag, beroende på fallet, riktade NUMA-minnesprinciper.

Analytiska uppgifter och omfattande genomsökningar sköter jag däremot delvis fördelat . Här ger interleave ofta bättre bandbredd än hård lokalitet. Det är viktigt att noggrant analysera arbetsbelastningens I/O-mönster. Skrivning dominerar på ett annat sätt än läsning, och slumpmässiga åtkomstförfrågningar på ett annat sätt än sekventiella. Jag väljer den policy som passar åtkomstmönstret, inte den som låter bra i läroboken.

Praktiska mätrutiner och verktyg

För att komma igång räcker det för mig med numastat och processvyn. Jag dokumenterar mätarställningar med datum, PID och belastningsindikatorer. Det är viktigt att mäta under identiska tidsfönster. På så sätt kan man tydligt visa skillnaderna före och efter. Under produktiva tidsfönster antecknar jag delta-värdena och korrelerar dem med release-tidpunkter.

Vid påfallande Tjänster Jag kontrollerar dessutom CPU-bindningen och nodvyn med verktyg som lscpu, numactl och perf-vyn för att se på fjärrbelastningen. Jag dokumenterar den valda policyn för varje mätomgång. Efter en ändring mäter jag igen. Först när trendlinjerna stabiliseras betraktar jag effekten som lyckad. Att byta policy i blindo leder lätt till skenbara förbättringar.

Undvika vanliga missuppfattningar

En hög interleave_hit är inget fel om interleave är avsiktligt aktiverat. På samma sätt är en enstaka avvikelse försumbar vid lång körtid. Jag granskar alltid tätheten och fördelningen över hela intervallet, inte bara toppvärdena. Vissa tolkar other_node som generellt negativt och förbiser belastningens karaktär. Därför tittar jag först på designmålet och utvärderar sedan siffrorna.

Ytterligare en missuppfattning: Övergripande syn Okej, då är allt bra. Ofta gömmer sig avvikelser bara i vissa PID:er. Eller så fördelar containerschedulern pods över olika noder, trots att en lokal grupp skulle vara mer lämpligt. Sådana effekter upptäcker jag först när jag mäter per process. Utan den här djupgående analysen blir resultatet ofullständigt.

Effektiva inställningssteg

Jag börjar med Placering: Processer på de noder där data finns eller ska finnas. Sedan ställer jag in CPU-affinitet så att trådar inte hoppar mellan socklar. Därefter följer minnesbindning, så att kärnan allokerar på önskad plats. För varierande belastningar kontrollerar jag policyer och, om det är lämpligt, AutoNUMA.

Därefter ser jag till att Samstämmighet I livscykeln: Omstarter, driftsättningar och skalningar får inte ändra nodreferenser på måfå. Jag dokumenterar kopplingarna i kod så att de förblir reproducerbara. Därefter mäter jag på nytt, utvärderar avvikelserna och beslutar om finjusteringar. Varje ändring förtjänar ett tydligt mätbevis.

Praktiskt exempel: Från flopp till succé

Anta att en Databas visar fler ”numa_miss” och stigande ”other_node” under belastning. Latensen för frågorna varierar mer. Jag kontrollerar först processbindningen och konstaterar att tjänsten efter en utrullning körs på nod A, men att cachen har tilldelats nod B. Efter en fast CPU- och minnesbindning till nod B vänds förhållandet: numa_hit stiger, missarna minskar. Svarstiderna blir mer konstanta och CPU-belastningen sjunker något eftersom fjärråtkomsten försvinner.

Samtidigt kontrollerar jag Policy. Interleave var oavsiktligt aktiverat och har fördelat allokeringar. Efter övergången till den prioriterade noden förblir cachen stängd lokalt. Efter en timmes mätning bekräftar delta-värdena förbättringen. Först då betraktar jag optimeringen som lyckad. Utan denna kontrollmätning skulle en ögonblicksbild ha varit missvisande.

Mätvärden och riktlinjer för praktiken

När jag fattar beslut använder jag tillförlitliga Odds istället för enskilda råvärden. För varje process beräknar jag allokeringsgraden local_alloc = numa_hit / (numa_hit + numa_miss). Dessutom utvärderar jag Tillgångsgrad local_access = local_node / (local_node + other_node). Tillsammans visar dessa värden om minnet förblir lokalt även efter allokeringen. Mina grova riktlinjer är följande: För latenskritiska tjänster strävar jag efter att fjärråtkomsten ska ligga under 5–10 %. Vid analytiska bandbreddsbelastningar tolererar jag 20–30 %, förutsatt att genomströmningen ökar. Avgörande är Stabilitet över tid. Jag föredrar ett värde som förblir stabilt under belastning framför en kort topp med perfekta värden. Jag dokumenterar dessa målintervall för varje service, så att senare mätningar tydligt kan placeras i sitt sammanhang.

Cgroups, containrar och schemaläggningsfällor

I container-miljöer kontrollerar jag först cpuset‑Tilldelning: CPU-uppsättningar och cpuset.mems måste avbilda samma nodutrymme, annars uppstår oundvikligen problem. Jag ser till att poddar med fasta CPU-begäranden inte sträcker sig över flera NUMA-noder, och att schemaläggaren inte fördelar arbetare från samma applikation över flera noder. För burst-typer begränsar jag det maximala antalet trådar per pod så att de hålls inom en enda nod. Jag dokumenterar NUMA-domän per distribution och kräver konsekventa repliker (en arbetsgrupp per nod, inte halva grupper fördelade på två noder). Om jag beräknar lagringsutrymmet per pod för snävt skapar jag oönskad press: ett litet utrymme per nod förhindrar att kärnan tvingas byta till andra noder i förtid. Om containrar startas om ofta ser jag till att använda deterministisk bindning, så att Kallstart inte av en slump hamna på en sämre plats.

Synkronisera virtuella maskiner och vNUMA

När det gäller virtuella maskiner riktar jag min uppmärksamhet mot vNUMA: Den virtuella topologin måste stämma överens med den fysiska. Jag fördelar vCPU:er så att varje vNUMA-nod hamnar på exakt en fysisk NUMA-nod. På värdsidan kopplar jag QEMU/hypervisor-trådarna till denna domän och ser till att det tilldelade RAM-minnet tillhandahålls helt och hållet från denna nod. Ballongflygning och jag accepterar överutnyttjande med försiktighet för latenskritiska virtuella maskiner; aggressivt ”ballooning” kan tränga bort hotsets från noden och öka antalet fjärråtkomster. Vid livemigrering verifierar jag bindningarna på nytt efter flytten – vissa miljöer förlorar nämligen de noggrant inställda CPU- och minnesbindningarna vid detta tillfälle. Först när vNUMA-inriktningen är korrekt utvärderar jag numastat systemomfattande: annars åtgärdar jag symptomen, inte orsaken.

THP, Hugepages och sidmigrering

Transparenta stora sidor (THP) kan både vara till hjälp och orsaka problem. Större sidor minskar antalet TLB-missar och förbättrar bandbredden, men om kärnan först sent börjar använda Hugepages kollapsar eller migreras, kan olämpliga Avstånd mellan orter uppstår. Jag följer två regler: För det första, den Policy definiera tydligt (t.ex. prioriterad nod) och i möjligaste mån tilldela stora lokala resurser redan från början. För det andra, vid arbetsbelastningar med fasta, stora cacher använder jag om möjligt statiska hugepages (hugetlb), som jag uttryckligen reserverar på en nod. Detta minskar fragmentering och kompensationsrelaterade omfördelningar. Om jag i tidsserier ser att efter en längre körtid har other_node– andelen ökar, så undersöker jag om Sidmigrering eller om komprimering sker och om THP-inställningarna passar mönstret. Det är viktigt för mig att inte stänga av eller slå på funktionen globalt – jag fattar beslut för varje tjänst och mäter effekten på lokalitet och latens.

Att tolka Reclaim, Swap och Memory‑Pressure på rätt sätt

Om missar uppstår utan någon uppenbar förändring i placeringen, letar jag efter minnesutskrift per nod. Fulla noder tvingar kärnan att återvinna utrymme och komprimera, delvis utlöst av kswapd på en annan nod – det ger upphov till sidoeffekter i räknarna. Jag kontrollerar det lediga minnet och utnyttjandet av sidcachen för varje nod. Aktiverad Byta kan tränga undan Hotsets och få latenserna att skjuta i höjden; för särskilt känsliga tjänster inaktiverar jag swap eller begränsar den strikt. I loggar och perf-vyer letar jag efter Reclaim-toppar under belastningstoppar. Målet är att ha tillräckligt med ledigt, lokala Att behålla RAM-minnet på målnoden så att allokeringarna inte glider iväg. Om cacheminnena måste minskas för detta ändamål prioriterar jag tjänstens arbetsuppsättning framför den generiska sidcachen.

Praktiska kommandon och utvärdering

För processvyn använder jag numastat -p och lägg till cat /proc//numa_maps, för att se tilldelningar per område (anonymt, filbaserat) och per nod. numactl --hårdvara ger mig latensmatriser och nodstorlekar, lscpu --extended visar CPU-tilldelningen till noder. För minnesåtkomst med fokus på långa vägar använder jag perf mem för att verifiera belastningsmönster. Jag samlar in delta-värden på ett reproducerbart sätt, t.ex.:

Mätningsrutin

  • t0: spara numastat (totalt) och numastat -p för de främsta PID:erna
  • 30–60 sekunders belastningskörning, identisk arbetsbelastningsfas
  • t1: Läs in numastat på nytt, beräkna delta per räknare
  • Logga parallella CPU-, kontextväxlings- och nodminnesvärden

Därefter beräknar jag Odds och markerar vilka processer som avviker väsentligt från de systemomfattande trenderna. Om osäkerhet kvarstår upprepar jag mätningen minst tre gånger. Först när avvikelserna är konsekventa betraktar jag dem som tillförlitliga. För kontinuerlig övervakning kartlägger jag räknarna mot tidsserier och kopplar dem till release-metadata – på så sätt kan jag upptäcka Regressionspunkter omedelbart.

Checklista för strukturerad NUMA-optimering

  • Definiera målet: latens kontra genomströmning, fast belastning kontra variabel belastning
  • Registrera topologi: noder, latenser, ledigt RAM-minne per nod
  • Mäta utgångsvärden: numastat totalt och per process, beräkna andelar
  • Korrigera placering: CPU-affinitet, minnesbindning, policyer
  • Konfigurera containrar/VM: cpuset.cpus = noder, cpuset.mems anpassade; korrekt mappning av vNUMA
  • Välj THP/Hugepages medvetet – håll koll på fragmenteringen
  • Minska minnesbelastningen: Headroom per nod, kontrollera swap-strategin
  • Uppföljning: Jämföra delta-värden, säkerställa stabilitet över tid
  • Dokumentera: Kopplingar som kod, releaseanteckningar med NUMA-sammanhang

Kortfattat sammanfattat

Jag analyserar NUMA-siffror genom att Signaler Läs även: räknarpar, tidsförlopp och processvy. Nyckelvärdena numa_hit, numa_miss, numa_foreign, local_node, other_node och interleave_hit visar mig lokalitet, avvikelser och fördelningsstrategier. Jag fattar beslut utifrån topologin och arbetsbelastningen, inte utifrån fasta gränsvärden. Optimering börjar med placering, affinitet, lämplig policy och en ren mätrutin. På så sätt levererar jag konstanta Prestanda, eftersom processorn och RAM-minnet är anpassade till applikationen och långa överföringsvägar är sällsynta.

Aktuella artiklar

Teknisk serverinfrastruktur med fokus på Linux NUMA-analys
Servrar och virtuella maskiner

Att tolka Linux NUMA-statistiken på rätt sätt

Att korrekt tolka Linux NUMA-statistik: förstå NUMA-statistik, kontrollera minneslokalitet och målmedvetet förbättra serverns prestanda.