Choosing a CPU for 5 Years: Buy by Workload, Not by Logo

Was this helpful?

The CPU you buy today will silently dictate your next five years of incident tickets: latency spikes you can’t reproduce,
“mysterious” GC pauses, and that one batch job that always runs long right before the CFO meeting.
Most teams still choose CPUs like they choose coffee: brand loyalty, vibes, and a benchmark screenshot from a chat thread.

Production doesn’t care about vibes. Production cares about tail latency, cache behavior, NUMA placement, and whether your
storage stack is asking for cycles you didn’t budget. If you want five years of predictable operations, you buy by workload,
and you prove it with measurements.

The core principle: workload first, logo last

A CPU is not a status symbol. It’s a contract: you’re committing to a specific balance of cores, frequency,
cache, memory channels, PCIe lanes, power limits, and platform quirks. Over five years, that contract will either
keep your systems boring (the good kind of boring) or turn every scaling conversation into a budget negotiation.

Buy by answering these questions with evidence:

  • What saturates first? CPU cycles, memory bandwidth, cache, I/O, or network?
  • What is the critical SLO? Throughput, p99 latency, job completion time, or cost per unit?
  • What is the concurrency model? Single-thread hot loop, many independent threads, or fork/join?
  • How “bursty” is it? Can you ride turbo/boost, or do you live at sustained all-core load?
  • What else will run there? Sidecars, agents, encryption, compression, scrubbing, backups, observability.

Then you select a platform (CPU + motherboard + memory + BIOS defaults + power/cooling) that serves those answers.
Not the other way around.

Joke #1: If your CPU selection process starts with “my friend says,” your next outage will end with “my friend was wrong.”

Quick facts and history that actually matter

A few concrete points—historical and technical—that help you reason about why modern CPU buying feels weird:

  1. Clock speeds stopped scaling linearly in the mid-2000s due to power density and heat; the industry pivoted hard to multicore.
  2. “Turbo”/boost clocks changed procurement math: short bursts can look amazing in benchmarks but collapse under sustained all-core load.
  3. Hyper-threading/SMT is not “2x cores”; it’s a utilization trick that helps some workloads and harms others, especially under contention.
  4. NUMA has been the quiet tax on server performance for decades: local memory is fast; remote memory is “fast-ish until it isn’t.”
  5. Cache sizes ballooned because memory didn’t keep up; latency to DRAM is still expensive, and many workloads are accidentally memory-latency bound.
  6. AES-NI and similar instruction extensions made encryption cheap enough to be “default on,” shifting bottlenecks elsewhere.
  7. Speculation mitigations (post-2018) made microarchitecture details matter operationally; patch levels can change performance profiles.
  8. PCIe lane counts became a first-class capacity metric as NVMe, GPUs, and smart NICs became normal in “general purpose” servers.

None of this tells you which brand to buy. It tells you why a one-number benchmark never described your future.

Workload shapes: what your CPU is really doing

1) Latency-critical services (p95/p99 lives here)

Web APIs, auth, ad bidding, market data, payments: the business metric is tail latency. These workloads often have
small hot loops, lots of branching, and frequent cache misses caused by large working sets or allocator churn.

What you want:

  • Strong single-thread performance (not just peak turbo on one core, but sustained under realistic load).
  • Large, effective cache hierarchy; fewer cache misses at scale beats “more cores” for tail latency.
  • Predictable frequency behavior under thermal and power limits.
  • Clear NUMA story: pin critical processes, keep memory local, avoid cross-socket chatter.

2) Throughput workloads (batch, ETL, render, offline compute)

If completion time matters more than request latency, you can often throw cores at it—until memory bandwidth or I/O becomes the wall.
Compilers, build farms, ETL jobs, and some analytics love parallelism, but only if they aren’t fighting over memory channels.

What you want:

  • More physical cores and enough memory bandwidth to feed them.
  • Sustained all-core performance under power limits, not bursty marketing clocks.
  • Enough PCIe for the storage and networking you’ll inevitably add mid-cycle.

3) Virtualization and container hosts (the “mixed bag”)

Hypervisors and Kubernetes nodes run a zoo: some things are latency-sensitive, others are CPU-bound, and plenty are just noisy.
Your CPU choice should minimize the blast radius of that noise.

What you want:

  • Enough cores for consolidation, but not so many that you can’t keep per-socket locality under control.
  • Good memory capacity and channels; memory overcommit turns into swap, and swap turns into existential dread.
  • Platform stability: predictable BIOS defaults, stable microcode, and clean IOMMU behavior for passthrough if needed.

4) Storage servers (yes, CPU matters a lot)

Storage stacks eat CPU in unglamorous ways: checksums, compression, RAID parity, encryption, dedupe (if you’re brave),
and metadata operations. ZFS, Ceph, mdraid, LVM, dm-crypt—these are not free.

What you want:

  • Enough cores for background work (scrub, rebalance, compaction) while serving foreground IO.
  • Strong memory subsystem; metadata-heavy IO becomes memory-latency bound.
  • PCIe lanes and topology that match your HBA/NVMe layout; “it fits in the slot” is not the same as “it performs.”

5) Specialized compute (transcoding, ML, crypto, compression)

These are the easiest to get right and the easiest to get wrong. Right: measure instructions used and pick the best accelerator path
(GPU, Quick Sync, AVX-512, etc.). Wrong: assume your CPU’s shiny vector extension is a guaranteed win.

What you want:

  • Instruction set support your software actually uses (and is compiled to use).
  • Thermals and power delivery that sustain vector workloads (they can downclock hard).
  • Enough IO for feeding the beast (NVMe for datasets, fast network, etc.).

CPU traits that move the needle (and the ones that don’t)

Cores vs frequency: stop treating it like a binary choice

Core count helps when you have parallel work that can be kept busy without fighting for shared resources.
Frequency helps when a small number of threads dominate latency or when lock contention makes “more threads” mostly just more contention.
Over five years, your workload will drift. But it won’t usually flip from “single-thread hot loop” to “perfectly parallel.”

The practical approach is to classify your workload by effective parallelism:

  • 1–4 hot threads matter most: prioritize strong per-core performance and cache, and keep the platform cool.
  • 8–32 useful threads: balance frequency and cores, watch memory bandwidth.
  • 64+ useful threads: cores and memory channels dominate; topology and NUMA become the hidden cliff.

Cache is often more valuable than you’re budgeting for

Many production services are “CPU bound” only because they’re stalled on memory. If you see high CPI, low IPC, and lots of cache misses,
a CPU with more cache (or better cache behavior) can outperform a higher-clocked part. This is the least sexy way to win performance and
the most repeatable.

Memory channels, frequency, and capacity: the quiet limiter

If your working set doesn’t fit in cache, you’re in the memory business now. More cores without enough memory bandwidth turns into
“expensive idling.” Also, memory capacity is a performance feature: staying out of swap and page cache thrash beats almost any CPU upgrade.

NUMA and topology: the performance you lose without noticing

On dual-socket systems (and even on some complex single-socket designs), memory locality matters. Remote memory access can add latency,
reduce bandwidth, and increase variance—especially visible at p99.

If you’re going multi-socket, budget time for:

  • NUMA-aware scheduling (systemd CPUAffinity, Kubernetes CPU Manager, pinning DB processes).
  • Validating that your NICs and NVMe devices are attached to the socket running the workload.
  • Measuring with real traffic, not synthetic tests that accidentally stay within one NUMA node.

PCIe lanes and IO topology: the trap in “general purpose” servers

You can buy a CPU with plenty of compute and then choke it with IO: too few PCIe lanes, oversubscribed root complexes,
or NVMe drives hanging off a switch that shares bandwidth in ways you didn’t model. Over five years, you’ll add NICs, more NVMe,
maybe a GPU, maybe a DPU. Choose a platform with headroom.

Power limits and cooling: sustained performance is the only performance

CPUs don’t “have” a frequency; they negotiate one with physics. If your chassis, fans, or datacenter inlet temperatures are marginal,
your expensive SKU turns into a cheaper SKU under load. This shows up as “weirdly inconsistent benchmarks” and later as “why did latency regress?”

Brand is not a strategy

Buy the part that wins on your metrics, on your compiler/runtime stack, on your power envelope, with your supply chain. Then validate.
That’s it. The logo is for the invoice.

Joke #2: The best CPU is the one that doesn’t make you learn a new vendor portal at 3 a.m.

Planning for five years: what changes, what doesn’t

Five years is long enough for your workload to evolve and short enough that you’ll still be running some embarrassing legacy.
The CPU selection needs to survive:

  • Software upgrades that change performance characteristics (new JIT behavior, new storage engine defaults, new kernel scheduler).
  • Security patch regimes that may affect microarchitectural performance.
  • New observability agents that “just need a little CPU.” They all do.
  • Growth in dataset sizes that turns cache-friendly workloads into memory-latency ones.
  • Platform drift: BIOS updates, microcode changes, and firmware features like power management defaults.

Buy headroom in the right dimension

Headroom is not “50% more cores.” Headroom is:

  • Memory capacity so you can grow without swapping.
  • Memory bandwidth so added cores don’t stall.
  • PCIe lanes for expansion without IO oversubscription.
  • Thermal margin so sustained load doesn’t downclock.
  • A SKU family that you can still source in year 3 without begging.

Prefer boring platforms when uptime is the product

Cutting-edge platforms are fine when you have a lab, spare capacity, and a rollback plan. If you run a lean team,
prefer the CPU/platform combo with predictable firmware, mature kernel support, and known NIC/HBA compatibility.
You are not paid in novelty.

One quote, because it’s still the best ops advice

Hope is not a strategy. — James Cameron

It applies embarrassingly well to capacity planning and CPU buying.

Three corporate mini-stories from the trenches

Mini-story #1: The incident caused by a wrong assumption

A mid-size SaaS company migrated their API tier onto new servers that looked perfect on paper: more cores, newer generation,
better synthetic scores. The workload was a Java service with a hot authentication path and a pile of tiny allocations.
It had been stable for years.

Within days, p99 latency started spiking. Not average latency. Not CPU utilization. Just p99, in bursts that lined up with traffic peaks.
The team assumed GC tuning. They tweaked heap sizes, changed collectors, rolled forward and back. The spikes persisted.

The wrong assumption was that “more cores” automatically improves tail latency. In reality, the new platform had a different NUMA topology,
and their container scheduler was happily placing the process on one socket while memory allocations came from another. Add a little lock
contention and you get a latency lottery.

The fix was not heroic. They pinned CPU sets and memory policy for the latency-critical pods, adjusted IRQ affinity so the NIC queues were
local to the compute, and validated with perf counters. The p99 spikes vanished. The CPU wasn’t bad. The assumption was.

Mini-story #2: The optimization that backfired

A storage team running a ZFS-backed object store decided they were “CPU heavy,” based on top showing high system time during peak ingest.
Someone proposed enabling aggressive compression everywhere and leaning on “modern CPUs” to make it free. They rolled it out gradually.

Ingest throughput improved initially. The dashboard looked better. Then the weekly scrub window started overlapping business hours because
scrubs took longer. Latency for reads became noisier, and a few customers complained about timeouts during background maintenance.

Compression was not the villain; unbounded compression was. The system was now juggling foreground compression, background scrub checksums,
and network interrupts on the same cores. They had accidentally moved the bottleneck from disk to CPU scheduling and cache pressure.

The rollback was partial: they kept compression for cold data and tuned recordsize and compression level for hot buckets.
More importantly, they reserved cores for storage maintenance and isolated interrupt handling. Performance returned, and scrub windows became
predictable again. The lesson: “CPU is cheap” is a dangerous sentence when you also need deterministic maintenance.

Mini-story #3: The boring but correct practice that saved the day

A financial services shop had a habit that looked painfully conservative: before approving any new CPU platform, they ran a week-long
canary in production with mirrored traffic and strict SLO gates. Procurement hated it. Engineers sometimes grumbled.
It slowed down “innovation.” It also prevented outages.

During one refresh cycle, a new server model passed basic benchmarks and unit tests but showed intermittent packet drops under sustained load.
The drops were rare enough that short tests missed them. The canary caught them because it ran long enough to hit the actual thermals and
the real NIC queue patterns.

They worked with the vendor and found a firmware + BIOS power management interaction that caused brief latency spikes in interrupt handling.
A firmware update and a BIOS setting change resolved it. No customer saw it. No incident review was needed.

The practice wasn’t glamorous: long canaries, boring acceptance criteria, and a refusal to trust a single benchmark.
That’s what “reliability engineering” looks like when it’s working.

Practical tasks: commands, outputs, and decisions (12+)

These are field tasks you can run on a candidate server (or an existing one) to understand what kind of CPU you need.
Each task includes: the command, what the output means, and the decision you make from it.

Task 1: Identify CPU model, cores, threads, and sockets

cr0x@server:~$ lscpu
Architecture:                         x86_64
CPU(s):                               64
Thread(s) per core:                   2
Core(s) per socket:                   32
Socket(s):                            1
Model name:                           AMD EPYC 7543 32-Core Processor
NUMA node(s):                         1
L3 cache:                             256 MiB

What it means: You now know your baseline: 32 physical cores, SMT enabled, single socket, and large L3 cache.

Decision: If you need predictable latency, single-socket often simplifies NUMA. If your workload is throughput-heavy, 32 cores may be perfect—or starved by memory bandwidth. Don’t guess; measure.

Task 2: Check CPU frequency behavior under load (governor and scaling)

cr0x@server:~$ cpupower frequency-info
analyzing CPU 0:
  driver: acpi-cpufreq
  CPUs which run at the same hardware frequency: 0
  available cpufreq governors: performance powersave
  current policy: frequency should be within 1500 MHz and 3700 MHz.
                  The governor "performance" may decide which speed to use
  current CPU frequency: 3692 MHz (asserted by call to hardware)

What it means: You’re likely not stuck in a low-power governor. Frequency headroom exists up to ~3.7 GHz.

Decision: For latency-critical nodes, use performance and validate sustained clocks under real load. If frequency collapses under load, you need better cooling/power limits or a different SKU.

Task 3: See if you’re CPU-saturated or just “busy”

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server) 	01/12/2026 	_x86_64_	(64 CPU)

12:00:01 PM  CPU   %usr  %nice   %sys %iowait  %irq  %soft  %steal  %idle
12:00:02 PM  all   62.10   0.00  10.40    0.20  0.10   1.30    0.00  25.90
12:00:02 PM   0   95.00   0.00   4.00    0.00  0.00   0.00    0.00   1.00
12:00:02 PM   1   10.00   0.00   1.00    0.00  0.00   0.00    0.00  89.00

What it means: Overall headroom exists, but CPU0 is hot. That’s a scheduling or interrupt hotspot, not “need more cores.”

Decision: Before buying a bigger CPU, fix pinning/IRQ affinity. If %idle is near zero across CPUs and load scales with demand, you may actually need more compute.

Task 4: Check run queue pressure (are you waiting on CPU?)

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 8  0      0 802312  11232 9212440    0    0     0    12 5821 9902 64 11 25  0  0
12  0      0 801900  11232 9212600    0    0     0     0 6001 11022 72 12 16  0  0

What it means: r is 8–12 runnable tasks. If that’s consistently above core count, you’re CPU-saturated. Here, it’s below 64 threads but could be above physical cores on smaller systems.

Decision: If r is consistently high and latency increases, you need more cores or better parallelism. If wa rises, you’re blocked on IO, not CPU.

Task 5: Determine if memory bandwidth/latency is the limit

cr0x@server:~$ perf stat -a -e cycles,instructions,cache-misses,LLC-load-misses -I 1000 sleep 3
#           time             counts unit events
     1.000349290    3,210,442,991      cycles
     1.000349290    2,120,112,884      instructions
     1.000349290       45,332,100      cache-misses
     1.000349290       12,501,883      LLC-load-misses

     2.000719401    3,188,102,112      cycles
     2.000719401    2,098,554,001      instructions
     2.000719401       46,110,220      cache-misses
     2.000719401       12,980,004      LLC-load-misses

What it means: Instructions per cycle is around 0.65 (2.1B / 3.2B), and LLC misses are significant. That hints at memory stalls.

Decision: If your service is memory-stall heavy, choose CPUs with better cache behavior and invest in memory channels/speed. “More GHz” won’t fix cache misses.

Task 6: Check NUMA layout and distances

cr0x@server:~$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0-31
node 0 size: 257837 MB
node 0 free: 210112 MB
node 1 cpus: 32-63
node 1 size: 257838 MB
node 1 free: 211004 MB
node distances:
node   0   1
  0:  10  21
  1:  21  10

What it means: Two NUMA nodes with remote access cost ~2x local (distance 21 vs 10). That’s normal-ish, but it will show up at p99 if you ignore it.

Decision: If you run latency-sensitive services, prefer single-socket or enforce NUMA locality. If you must go dual-socket, plan for pinning and memory policy from day one.

Task 7: Map PCIe devices to NUMA nodes (NICs, NVMe, HBAs)

cr0x@server:~$ lspci -vv | grep -E "Ethernet|Non-Volatile|NUMA"
3b:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983
	NUMA node: 1
41:00.0 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5]
	NUMA node: 0

What it means: Your NIC is local to node 0, NVMe to node 1. If your IO path crosses sockets, you just bought latency variance.

Decision: Align workloads with their IO devices (pin compute near NIC/NVMe) or re-slot hardware. For new purchases, choose platforms with enough lanes to avoid awkward placement.

Task 8: Identify interrupt hotspots (often mistaken for “CPU needs upgrade”)

cr0x@server:~$ cat /proc/interrupts | head -n 8
           CPU0       CPU1       CPU2       CPU3
  24:  99211231          0          0          0   PCI-MSI 524288-edge      mlx5_comp0@pci:0000:41:00.0
  25:         0   98122010          0          0   PCI-MSI 524289-edge      mlx5_comp1@pci:0000:41:00.0
  26:         0          0   99100110          0   PCI-MSI 524290-edge      mlx5_comp2@pci:0000:41:00.0
  27:         0          0          0   98911220   PCI-MSI 524291-edge      mlx5_comp3@pci:0000:41:00.0

What it means: Interrupts are well-distributed here; in many systems they’re not, and one CPU gets hammered.

Decision: If interrupts pile onto one CPU, fix IRQ affinity and queue settings before changing CPUs. Tail latency improves dramatically with correct interrupt distribution.

Task 9: Check for throttling and thermal limits

cr0x@server:~$ dmesg | grep -iE "thrott|thermal|powercap" | tail -n 5
[ 8921.112233] intel_rapl_common: Found RAPL domain package
[ 9122.445566] CPU0: Core temperature above threshold, cpu clock throttled (total events = 3)
[ 9122.445700] CPU0: Package temperature/speed normal

What it means: You’re occasionally throttling. That’s performance variability you will feel at p99.

Decision: If throttling appears under normal load, fix cooling, fan curves, heatsink contact, or power limits. If you can’t, don’t buy the top-bin SKU that only performs in an ideal lab.

Task 10: Validate virtualization overhead and steal time

cr0x@server:~$ mpstat 1 3 | tail -n 3
12:10:02 PM  all  40.00   0.00   8.00   0.00   0.00   0.50   7.50  44.00
12:10:03 PM  all  42.00   0.00   9.00   0.00   0.00   0.40   8.20  40.40
12:10:04 PM  all  41.50   0.00   8.80   0.00   0.00   0.60   8.10  41.00

What it means: %steal around 8% indicates your VM is waiting because the hypervisor is oversubscribed or noisy neighbors exist.

Decision: Don’t “fix” steal time by upgrading the guest CPU. Fix host oversubscription, reserve CPU, or move workloads. For purchasing, ensure hosts have enough real cores for consolidation targets.

Task 11: Determine if storage is stealing your cycles (ZFS example)

cr0x@server:~$ zpool iostat -v 1 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
tank        7.21T  3.12T    980  4.20K  112M  610M
  raidz2    7.21T  3.12T    980  4.20K  112M  610M
    nvme0n1     -      -    120    520  14.0M 72.0M
    nvme1n1     -      -    118    525  13.8M 72.5M
    nvme2n1     -      -    121    515  14.2M 71.2M
    nvme3n1     -      -    119    518  13.9M 71.8M

What it means: You’re pushing 610 MB/s writes with 4.2K ops/s. If CPU is also high, checksumming/compression/parity may be the limiter, not the drives.

Decision: For storage servers, favor CPUs with enough cores for maintenance and data services, and ensure memory is abundant. If write throughput plateaus with CPU pegged, you need more CPU or different RAID/compression choices.

Task 12: Measure network processing load (softirq pressure)

cr0x@server:~$ sar -n DEV 1 3
Linux 6.5.0 (server) 	01/12/2026 	_x86_64_	(64 CPU)

12:15:01 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s
12:15:02 PM      eth0   120000    118500   980000    910000
12:15:03 PM      eth0   121200    119100   990500    915200

What it means: Very high packet rates. That’s CPU work (softirq, interrupts), not just “network bandwidth.”

Decision: If packet rate is high, pick CPUs with strong per-core performance and ensure NIC queue/IRQ affinity is correct. Sometimes fewer faster cores beat more slower cores for packet-heavy workloads.

Task 13: Check context switching and scheduler churn

cr0x@server:~$ pidstat -w 1 3
Linux 6.5.0 (server) 	01/12/2026 	_x86_64_	(64 CPU)

12:18:01 PM   UID       PID   cswch/s nvcswch/s  Command
12:18:02 PM     0      1221    1200.00    300.00  kubelet
12:18:02 PM   999      3456   22000.00   9000.00  java

What it means: High voluntary and non-voluntary context switches. That’s often lock contention, too many threads, or noisy scheduling.

Decision: Before adding cores, reduce thread counts, tune runtimes, or isolate workloads. If you can’t, prefer higher per-core performance and fewer cross-NUMA migrations.

Task 14: Confirm kernel sees correct mitigations (performance can shift)

cr0x@server:~$ grep -E "Mitigation|Vulnerable" /sys/devices/system/cpu/vulnerabilities/* | head
/sys/devices/system/cpu/vulnerabilities/meltdown:Mitigation: PTI
/sys/devices/system/cpu/vulnerabilities/spectre_v1:Mitigation: usercopy/swapgs barriers and __user pointer sanitization
/sys/devices/system/cpu/vulnerabilities/spectre_v2:Mitigation: Retpolines; IBPB: conditional; STIBP: disabled; RSB filling

What it means: You can’t ignore security mitigations; they influence syscall-heavy and context-switch-heavy workloads.

Decision: For syscall-heavy services, measure performance with the actual mitigations you will run in production. Don’t benchmark a lab kernel configuration you won’t ship.

Fast diagnosis playbook: find the bottleneck quickly

When something is slow and everyone starts arguing about CPUs, you need a short playbook that cuts through noise.
This sequence is designed for production triage: minimal tooling, maximum signal.

First: decide if you’re CPU-bound, IO-bound, or waiting on something else

  • Run mpstat to see idle, iowait, and steal time.
  • Run vmstat to see runnable queue r and wait wa.
  • Check load average with uptime, but don’t treat it as truth—treat it as smoke.

If %idle is low and r is high, you’re plausibly CPU-bound.
If %iowait is high or blocked processes appear, you’re IO-bound.
If %steal is high in VMs, you’re being robbed by the hypervisor.

Second: classify the CPU pain (compute vs memory vs scheduler)

  • Use perf stat for IPC and cache misses. Low IPC + high misses suggests memory stalls.
  • Use pidstat -w for context switching. High switches suggest contention or too many threads.
  • Check NUMA with numactl --hardware and device placement with lspci.

Third: look for the platform-specific foot-guns

  • Throttling in dmesg (thermals/powercap).
  • Interrupt imbalance in /proc/interrupts.
  • Frequency governor mismatch in cpupower frequency-info.
  • Virtualization steal time: fix host sizing, not guest CPUs.

Fourth: decide what to change

  • If it’s CPU-saturated and scales with demand: add cores or split the service.
  • If it’s memory-stalled: prioritize cache/memory channels; consider fewer faster cores over many slower ones.
  • If it’s NUMA/topology: pin, align devices, or prefer single-socket for latency tiers.
  • If it’s thermals/power: fix cooling or stop buying SKUs you can’t sustain.

Common mistakes: symptoms → root cause → fix

1) Symptom: p99 latency regresses after “upgrade”

Root cause: NUMA remote memory access, IRQs on the wrong socket, or frequency instability under load.

Fix: Pin processes and memory, align NIC/NVMe to the same NUMA node, set appropriate governor, and verify no throttling events.

2) Symptom: CPU usage is high, but throughput doesn’t improve with more cores

Root cause: Memory bandwidth limit, lock contention, or cache thrash. More cores increase contention and stalls.

Fix: Measure IPC and cache misses, reduce thread counts, shard or partition work, or choose a CPU with stronger cache/memory subsystem instead of more cores.

3) Symptom: “Random” spikes during peak traffic

Root cause: Interrupt storms, noisy neighbors (VM steal), background tasks (scrub, compaction), or thermal throttling.

Fix: Isolate cores for IRQs and background work, reserve CPU, run long canaries, and audit thermals under sustained load.

4) Symptom: Load average is high, but CPU is not busy

Root cause: Tasks blocked in IO, storage latency, or kernel waits; load average counts runnable and uninterruptible tasks.

Fix: Check %iowait, storage stats, and blocked processes. Upgrade storage or fix IO path; don’t buy CPUs to compensate for slow disks.

5) Symptom: Storage server can’t hit expected NVMe speeds

Root cause: PCIe topology oversubscription, wrong slot wiring, shared root complex, or CPU overhead in checksums/parity/encryption.

Fix: Validate PCIe placement, ensure enough lanes, measure CPU cost of storage features, and reserve CPU for background maintenance.

6) Symptom: Benchmark looks great, production looks mediocre

Root cause: Benchmark uses a single thread, fits in cache, or runs for 30 seconds. Production runs for days and misses cache all day.

Fix: Benchmark with production-like dataset sizes, concurrency, and run duration. Use canary traffic and SLO gates.

7) Symptom: Performance changes after firmware/microcode update

Root cause: Power management defaults changed, mitigations behavior changed, or scheduler interactions shifted.

Fix: Treat firmware like a release: test, measure, pin BIOS settings, and document the “known-good” configuration for your fleet.

Checklists / step-by-step plan

Step-by-step: picking the right CPU for a 5-year horizon

  1. Write down the real workload mix. Include background tasks (backups, scrubs, compaction, observability agents).
  2. Define success metrics. Throughput, p99 latency, cost per request, completion time. Pick two, not ten.
  3. Capture current bottleneck evidence. Use mpstat, vmstat, perf stat, NUMA and IO mapping.
  4. Classify the workload shape. Latency-critical vs throughput vs mixed virtualization vs storage-heavy.
  5. Choose platform constraints first. Single vs dual socket, memory channels/capacity, PCIe lanes, NIC/HBA plan, rack power and cooling.
  6. Select 2–3 candidate SKUs. One “safe,” one “performance,” one “cost-optimized.”
  7. Run realistic benchmarks. Same kernel settings, same mitigations, same dataset size, same run duration.
  8. Do a production canary. Mirror traffic, run long enough to hit thermals and maintenance cycles.
  9. Lock down BIOS and firmware settings. Document them. Make them reproducible across the fleet.
  10. Decide with a written rationale. Include what you’re optimizing for, what you’re sacrificing, and the evidence.

Checklist: don’t get ambushed in year 3

  • Memory slots free for expansion, not fully populated on day one unless required.
  • PCIe lane headroom for adding NVMe or faster NICs later.
  • Cooling margin tested at sustained load in your actual chassis.
  • Spare capacity for background maintenance (storage scrubs, compaction, indexing, backups).
  • Supply chain reality check: can you buy the same platform later?
  • Operational tooling readiness: can you observe per-core utilization, throttling, and NUMA issues?

Checklist: platform settings to standardize (so performance doesn’t drift)

  • CPU governor / power profile
  • SMT policy (on/off) per workload class
  • NUMA balancing policy and pinning strategy
  • IRQ affinity and NIC queue configuration
  • Microcode and firmware version pinning strategy
  • Kernel mitigations policy consistent with security posture

FAQ

1) Should I buy the highest core count I can afford to “future-proof”?

No. Buy the right mix. High core count without memory bandwidth and cache effectiveness often makes p99 worse and cost higher.
Future-proofing is usually memory capacity + PCIe headroom + predictable sustained performance.

2) Is single-socket always better than dual-socket?

For latency-critical tiers, single-socket is often easier to run well because you reduce NUMA complexity.
For throughput-heavy compute or massive memory capacity needs, dual-socket can be correct—if you commit to NUMA-aware operations.

3) Do I want SMT/Hyper-Threading enabled?

It depends. SMT can improve throughput for some mixed workloads. It can also increase contention and jitter for tail-latency-sensitive services.
Test both modes on realistic load; pick per cluster role, not as a universal rule.

4) How do I know if my workload is memory-latency bound?

Low IPC, high cache/LLC misses, and weak scaling with more cores are classic signs. Use perf stat to check instructions vs cycles and cache misses,
and validate with dataset sizes that match production.

5) Are synthetic benchmarks useless?

Not useless—dangerous when used alone. They’re good for catching obvious regressions and hardware defects.
They’re bad at predicting tail latency, NUMA effects, IO topology issues, and sustained thermal behavior.

6) What matters more for virtualization hosts: cores or frequency?

Both, but don’t skip memory. Consolidation needs cores; noisy tenants and network/storage overhead often punish weak per-core performance.
If you run mixed workloads, you usually want a balanced CPU plus strong memory capacity and bandwidth.

7) If we run ZFS or Ceph, should we prioritize CPU more than usual?

Yes. Modern storage features are CPU features: checksums, compression, encryption, parity, and background maintenance.
Also prioritize memory (ARC, metadata, caching) and PCIe topology so your fast drives aren’t bottlenecked upstream.

8) When is it rational to pay for “top bin” parts?

When you are latency-constrained by a few hot threads, and you can keep the CPU cool enough to sustain high clocks.
If your chassis or datacenter can’t sustain it, the premium is mostly donated to physics.

9) How should I think about power consumption over five years?

Power is not just cost; it’s also performance stability. A platform that’s always at the edge of power/thermals will be noisy.
Choose a CPU that delivers needed performance within your rack power and cooling reality, not a brochure.

10) What’s the single biggest “tell” that we’re choosing CPUs by logo?

When the evaluation ends at “this benchmark is higher,” without pinning down what metric you’re optimizing (p99 vs throughput) and without a canary plan.
If you can’t describe your bottleneck with measurements, you’re shopping emotionally.

Next steps you can do this week

If you want a CPU decision you won’t regret for five years, do the unglamorous work now:

  1. Profile one representative host using the commands above and write down what’s actually limiting you.
  2. Decide your top metric: p99 latency, throughput, or cost per unit. Pick one primary and one secondary.
  3. Build a candidate list of 2–3 CPUs and include platform constraints: memory channels, PCIe lanes, and cooling.
  4. Run a long test (hours, not minutes). Include background maintenance (scrub, backups, compaction) in the test window.
  5. Canary in production with mirrored traffic and a rollback switch. Boring, yes. Effective, absolutely.
  6. Document the decision with evidence: what you measured, what you chose, and what you intentionally didn’t optimize.

The goal isn’t to pick the “best” CPU. The goal is to pick the CPU that makes your specific workloads boring to operate, for a long time.

← Previous
G-Sync vs FreeSync: the monitor war that affected everyone
Next →
ZeroTier: Build a Private Network and Fix the “Can’t Ping” Problem

Leave a comment