Бұлттық сервердегі жад кідірісі: болжам емес, өлшем

Бұлттық сервердегі жад кідірісі: болжам емес, өлшем

Бұлттық сервердегі жад кідірісі: болжам емес, өлшем

Қысқаша (2026-11-01 тексерілді): Осы демалыста Hacker News басты бетіне шыққан жазба 100% жүктемені көрсететін процессор жиі тек RAM-ды күтіп тұрады дейді. Автор көбірек жұмыс істеп, бірақ жадқа сирек жүгініп жылдамдаған GROUP BY сұрауын көрсетеді. Біз сол идеяны осы блогты жазатын бұлттық серверде тексердік: деректер L1-ге сыйса, бір оқу шамамен 2 нс тұрады, ал 256 МБ жұмыс жиынында шамамен 200 нс, яғни жүз есеге жуық көп. Сервер жалдайтындар үшін бұл айырма тапсырыстағы ядро санынан маңыздырақ. Төменде скрипт, біздің сандар және олардың бұлт пен арнайы сервер арасындағы таңдауға әсері.

Дереккөз. "It's the memory latency, stupid", авторы Maor Kern (Pivot / Epsio Labs, 2026-10-28 жарияланған), Hacker News талқылауы, 2026-11-01 жағдайы бойынша 175 ұпай. Олардың сандары жазбада қалай берілсе, солай келтірілді; өз сандарымызды өзіміз өлшедік.

Pivot жазбасы нені өлшеді

Тест бір сұраудан тұрады: ClickBench "hits" кестесі бойынша GROUP BY UserID (шамамен 99 миллион жол, шамамен 17 миллион бірегей пайдаланушы), 128 ГБ DDR5 бар AMD EPYC 9124 bare-metal серверінің бір ядросына бекітілген. 17 миллион кілтке арналған қарапайым хеш-кесте ешбір кэшке сыймайды, сондықтан іздеудің барлығына жуығы RAM-ға барады. Жолдарды алдымен 4096 бөлікке бөліп, әрқайсысына шағын хеш-кесте берсе, жұмыс көбейеді, бірақ әр кесте кэште қалады:

Көрсеткіш (бір ядро) Қарапайым хеш-кесте Radix бөлу
Уақыт, 1-ші / 2-ші іске қосу 3.9 с / 3.6 с 3.3 с / 2.7 с
Жадты күтетін слоттар 50.1% 23.5%
Пайдалы жұмыс слоттары 16.1% 32.2%
DRAM-нан оқулар 76.2 млн 25.7 млн

Бөлінген нұсқа көбірек операция орындайды (19.4 млрд, 11.4 млрд-қа қарсы), бірақ бәрібір бірінші аяқтайды. Автордың оңтайландырылған нұсқасы бір ядрода 1.85 с, барлық 16 ядрода 0.17 с жұмыс істеді. Сабақ бір дерекқорға ғана қатысты емес: top ішіндегі "CPU 100%" ядроның бос тұрмағанын білдіреді, оның есептеп жатқанын емес.

Өзіңіз өлшеңіз: memlat.js

Кідірісті көрудің классикалық тәсілі - pointer chase: әр ұяшықта келесісінің индексі сақталған, кездейсоқ ретпен, бір кэш-сызық (64 байт) қашықтықта орналасқан массив. Әр оқу алдыңғысына тәуелді, сондықтан процессор деректі алдын ала жүктей де, оқуларды қатар орындай да алмайды, ал бір қадамның уақыты жұмыс жиыны тұрған деңгейдің кідірісіне тең. Блог машинамызда C компиляторы жоқ, сондықтан бұл Bun үшін JavaScript: JIT циклды бірнеше машиналық нұсқаулыққа айналдырады, бұл әр санға аздап қосады. Абсолюттік мәндерді емес, сатыларды салыстырыңыз. memlat.js деп сақтаңыз:

// memlat.js - pointer-chase memory latency by working-set size (bun memlat.js)
import { readFileSync, readdirSync } from 'node:fs'

const cpu = readFileSync('/proc/cpuinfo', 'utf8').match(/model name\s*:\s*(.+)/)?.[1] ?? '?'
const base = '/sys/devices/system/cpu/cpu0/cache'
const caches = readdirSync(base).filter(d => d.startsWith('index')).map(d => {
  const r = f => readFileSync(`${base}/${d}/${f}`, 'utf8').trim()
  return `L${r('level')}${r('type') === 'Data' ? 'd' : r('type') === 'Instruction' ? 'i' : ''} ${r('size')}`
})
console.log(`CPU: ${cpu}\nCaches: ${caches.join(', ')}`)

// one random cycle through n slots, 64 bytes (16 x int32) apart: one cache line per hop
function ring(bytes) {
  const n = Math.max(2, Math.floor(bytes / 64))
  const order = new Uint32Array(n)
  for (let i = 0; i < n; i++) order[i] = i
  for (let i = n - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    const t = order[i]; order[i] = order[j]; order[j] = t
  }
  const a = new Int32Array(n * 16)
  for (let i = 0; i < n; i++) a[order[i] * 16] = order[(i + 1) % n] * 16
  return a
}

function chase(a, hops) {
  let p = 0
  for (let i = 0; i < hops; i++) p = a[p]
  return p
}

const hops = 20_000_000
console.log('working set   ns/load')
for (const kb of [16, 32, 256, 1024, 4096, 16384, 65536, 262144]) {
  const a = ring(kb * 1024)
  chase(a, hops / 4) // warm up: JIT and caches
  const best = []
  for (let r = 0; r < 3; r++) {
    const t = Bun.nanoseconds()
    const sink = chase(a, hops)
    best.push((Bun.nanoseconds() - t) / hops)
    if (sink < 0) console.log(sink)
  }
  const label = kb >= 1024 ? `${kb / 1024} MB` : `${kb} KB`
  console.log(`${label.padStart(10)}   ${Math.min(...best).toFixed(1).padStart(7)}`)
}
bun memlat.js

Нәтиже, DCXV бұлттық серверінде Bun 1.4.4 арқылы 2026-11-01 іске қосылды:

CPU: Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz
Caches: L2 4096K, L1d 32K, L3 16384K, L1i 32K
working set   ns/load
     16 KB       2.0
     32 KB       2.2
    256 KB      12.5
      1 MB      24.3
      4 MB     122.2
     16 MB     138.4
     64 MB     164.7
    256 MB     205.1

Сол таңғы екінші іске қосу 1 МБ-қа дейін ең көбі 2 нс, одан жоғары ең көбі 12 нс айырмашылық берді:

Жұмыс жиыны бір оқуға нс, іске қосу 1 / 2 Қай жерде тұрады
32 КБ 2.2 / 2.4 L1 деректер кэші
256 КБ 12.5 / 10.5 L2, ішінара L3
1 МБ 24.3 / 24.3 L3
16 МБ 138.4 / 137.2 бет кестелерін аралау, L3 және DRAM
256 МБ 205.1 / 193.5 DRAM

Сандар не айтады

  1. Қонақ жүйе нақты кэштерді көрмейді. ВМ 4 МБ L2 және 16 МБ L3 көрсетеді; Intel Xeon E5-2698 v4 үшін 50 МБ кэш көрсетеді (Intel ark, 2026-11-01 тексерілді). Гипервизор өз топологиясын ұсынады, ал бұлттық сервердегі lscpu кремнийді емес, соны оқиды. Жазуларға сенбей, жабдықты өлшеңіз.
  2. Құлдырау кэш толмай тұрып-ақ басталады. 1 МБ мен 4 МБ аралығында кідіріс бес есе өседі, бұл 50 МБ-тан әлдеқайда төмен. 4 КБ беттермен 4 МБ бойынша кездейсоқ аралау 1 024 бетті қозғайды, бұл TLB сыйғызатыннан көп, ал ВМ ішінде TLB жіберіп алуы қонақтың да, хосттың да бет кестелерін аралайды; оның үстіне L3 сокеттің басқа ядроларымен ортақ. Бұл себептерді біз бөліп қарамадық. Практикалық қорытынды бірдей: ВМ-де жылдам жұмыс жиыныңыз бірнеше мегабайт қана деп жоспарлаңыз.
  3. Көп RAM жылдам RAM дегенді білдірмейді. 1 МБ-тан 256 МБ-қа дейін бір оқудың құны шамамен сегіз есе өседі. Қосымша гигабайттар жылдамдық емес, көлем береді; кідіріске тірелген тапсырманы Pivot бөлуі көрсеткендей кішірек ыстық жиын жылдамдатады.

Сервер жалдағанда бұл нені білдіреді

  • Бұлттық серверлер веб-қосымшалардың, API мен шағын дерекқорлардың көпшілігіне жарайды: олардың ыстық деректері кэшке сыяды, және олар RAM-ды күтпей тұрып-ақ желіні не дискіні күтеді. Көлемді өлшенген жад қолданысы бойынша таңдаңыз, біздің бұлттық сервер көлемін таңдау нұсқаулығындағыдай.
  • Арнайы серверлер үлкен жұмыс жиыны күні бойы кездейсоқ оқылғанда өзін ақтайды: аналитика, үлкен хеш-біріктірулер, жадтағы кэштер, индекстері RAM-ға енді сыймайтын PostgreSQL сервері. Сіз көршілерсіз бүкіл L3 мен жадтың барлық арнасын аласыз және TLB жіберіп алуларын азайтатын huge pages қоса аласыз. Конфигурацияны арнайы сервер бетінде жинаңыз.
  • Кез келген жаңартудан бұрын тестті қолыңыздағы серверде іске қосып, баяу тапсырмаңыз кідіріске тірелетінін тексеріңіз. Ядроларды екі есе көбейту уақытының жартысын күтумен өткізетін бір ағынға көмектеспейді. Жадтың өзі биыл қымбаттады, қараңыз: 2026 жылғы сервер RAM, сондықтан ең арзан шешім көбіне оған азырақ жүгінетін код.

Сатып алмас бұрын тексеріңіз

Прага мен Ковильядағы Tier III дата-орталықтарымыз бұлттық серверлерді және арнайы серверлерді ұсынады. Бұлттық серверді іске қосып, memlat.js-ті өз жүктемеңіздің қасында орындаңыз да, нәтижені sales@dcxv.com мекенжайына жіберіңіз: арнайы сервер сандарды өзгерте ме, соны шешуге көмектесеміз.

АҚШ кеңестеріндегі 10 000 пікір: ДОО клиенттеріне не береді
clouddedicatedinfrastructure

АҚШ кеңестеріндегі 10 000 пікір: ДОО клиенттеріне не береді

Жаңа деректер жинағы АҚШ кеңестеріндегі дата-орталықтар туралы 10 202 пікірді қамтиды: 90,5% қарсы, су бірінші орында. Біз қайта санап, мәнін түсіндіреміз.

Бұлттық сервердегі жад кідірісі: болжам емес, өлшем
clouddedicatedinfrastructure

Бұлттық сервердегі жад кідірісі: болжам емес, өлшем

Танымал жазба бос емес CPU жиі тек RAM-ды күтеді дейді. Біз өз бұлттық серверімізде L1-ден DRAM-ға дейінгі кідірісті өлшеп, оның не беретінін түсіндіреміз.

Альтман DRAM жадын дата-орталықта қалайды: сервер RAM 2026
cloudaipricinginfrastructure

Альтман DRAM жадын дата-орталықта қалайды: сервер RAM 2026

Сэм Альтман ДК жады бос тұрады, оның орны дата-орталықта дейді. 2026 жылғы DRAM тапшылығы сервер жалдаушыларға не береді және RAM өлшейтін скрипт.

PHP2Shell: сервердегі PHP RCE осалдықтарын тексеру және жабу
clouddedicatedhosting

PHP2Shell: сервердегі PHP RCE осалдықтарын тексеру және жабу

PHP2Shell (CVE-2026-109618, CVE-2026-109619) аутентификациясыз сұранысқа PHP-де код орындатады. Түзетілген нұсқалар, тексерілген скрипт, php.ini шаралары және жаңарту жоспары.

Brotli CVE-2026-111497: Node.js, Bun және Python жаңарту
cloudnetworkinginfrastructure

Brotli CVE-2026-111497: Node.js, Bun және Python жаңарту

Brotli декодеріндегі осалдық (CVE-2026-111497) Node.js пен Bun-дағы fetch() немесе Python HTTP-клиенттері арқылы код орындатады. Түзетілген нұсқалар, тексеру скрипті, қайта құру.