Hacker News

Зашто је прва Ц++ (м)алокација увек 72 КБ?

Коментари

1 min read Via joelsiks.com

Mewayz Team

Editorial Team

Hacker News
<х2>Мистерија иза ваше прве алокације Ц++ <п>Пишете једноставан Ц++ програм. Једна <стронг>нова инт. Четири бајта. Покренете <стронг>страце или свој омиљени меморијски профилер, и ето га — ваш процес је управо захтевао отприлике 72 КБ од оперативног система. Не 4 бајта. Не 64 бајта. Пуних 72 КБ. Ако сте икада зурили у тај број и питали се да ли вас је ваш алат лагао, нисте сами. Ово наизглед бизарно понашање једно је од најчешће постављаних питања међу Ц++ програмерима који по први пут копају по интерним елементима меморије, а одговор нас води на фасцинантно путовање кроз слојеве који се налазе између вашег кода и стварног хардвера. <х2>Шта се дешава када позовете <стронг>ново <п>Да бисте разумели цифру од 72 КБ, потребно је да пратите цео ланац доделе. Када ваш Ц++ код изврши <стронг>нев инт, компајлер то преводи у позив <стронг>оператору нев, који на већини Линук система делегира <стронг>маллоц од глибц-а. Али <стронг>маллоц не тражи директно од кернела 4 бајта меморије. Кернел ради на страницама — обично 4 КБ на к86_64 — и цена системског позива је огромна у односу на једноставан приступ меморији. Позивање <стронг>брк() или <стронг>ммап() за сваку појединачну алокацију учинило би да се било који нетривијални програм заустави. <п>Уместо тога, глибц-ов алокатор меморије — имплементација под називом <стронг>птмаллоц2, која сама потиче од класичног <стронг>длмаллоц Доуга Леа-а — делује као посредник. Захтева велике блокове меморије од кернела унапред, а затим их сече на мање делове како су вашем програму потребни. Ово је основни разлог зашто ваша прва 4-бајтна алокација покреће много већи захтев оперативном систему. Алокатор није расипнички. То је стратешки. <х2>Сецирање 72 КБ: Где иду бајтови <п>Почетни трошкови доделе потичу од неколико различитих компоненти које време извршавања мора да иницијализује пре него што вам може предати чак и један бајт употребљиве меморије. Разумевање сваке компоненте објашњава зашто се број налази тамо где је. <п>Прво, глибц-ов маллоц иницијализује <стронг>главну арену — примарну књиговодствену структуру која прати све алокације на главној нити. Ова арена укључује метаподатке за хрпу, показиваче слободне листе и структуре корпе за различите величине алокације. Алокатор проширује паузу програма преко <стронг>сбрк(), а почетним проширењем управља интерни параметар под називом <стронг>М_ТОП_ПАД, који је подразумевано подешен на 128 КБ допуна. Међутим, стварни почетни захтев се прилагођава за поравнање странице и постојећу позицију прелома, што често резултира мањим првим захтевом — који се обично налази близу те бројке од 72 КБ у тек започетом процесу. <п>Друго, од глибц-а 2.26, алокатор иницијализује <стронг>локални кеш нити (тцацхе) при првој употреби. Ткеш меморија садржи 64 корпе (један по класи величине мале алокације), од којих свака може да држи до 7 кешираних делова. Сам <стронг>тцацхе_пертхреад_струцт троши око 1 КБ, али чин иницијализације покреће ширу поставку арене. Треће, Ц++ рунтиме је већ извршило алокације пре него што се ваш <стронг>маин() чак и покрене — статички конструктори, иостреам иницијализација бафера за <стронг>стд::цоут и пријатеље и подешавање локализације доприносе том почетном отиску гомиле. <х2>Систем арене и зашто је пре-додела паметна <п>Одлука да се унапред додели значајан део меморије уместо да се захтева по деловима није случајност имплементације. То је намерни инжењерски компромис укорењен у деценијама искуства системског програмирања. Сваки позив <стронг>брк() или <стронг>ммап() укључује промену контекста са корисничког простора на простор кернела, модификацију мапирања виртуелне меморије процеса и потенцијална ажурирања табеле страница. На савременом хардверу, један системски позив кошта отприлике 100-200 наносекунди — тривијално у изолацији, катастрофално на нивоу.<п>Размотрите програм који прави 10.000 малих алокација током иницијализације. Без пре-алокације, то би значило 10.000 системских позива, што би коштало отприлике 1-2 милисекунди чистих трошкова. Са алокатором заснованим на арени, прва алокација покреће један системски позив, а наредних 9.999 алокација се у потпуности сервисира у корисничком простору кроз аритметику показивача и операције повезане листе — свака траје отприлике 10-50 наносекунди. Математика је недвосмислена: пре-алокација побеђује по редоследу величине. <блоцккуоте> <п>Оних 72 КБ које видите при првој додели није изгубљена меморија – то је инвестиција у перформансе. Алокатор се клади да ће ваш програм ускоро извршити више алокација, иу практично сваком стварном сценарију, та опклада се одлично исплати. Цена неискоришћеног виртуелног адресног простора је у суштини нула на модерним 64-битним системима. <х2>Виртуелна меморија наспрам физичке меморије: зашто то није важно <п>Уобичајена брига програмера који се по први пут сусрећу са овим понашањем је расипање ресурса. Ако ми треба само 4 бајта, зашто мој програм троши 72 КБ? Кључни увид је да <стронг>виртуелна меморија није физичка меморија. Када глибц продужи паузу програма за 72 КБ, кернел ажурира мапирања виртуелне меморије процеса, али не подржава те странице одмах физичком РАМ-ом. Стварне физичке странице се додељују на захтев преко <стронг>грешке странице — само када ваш програм пише на одређену адресу, кернел му додељује стварну страницу меморије. <п>То значи да иако се виртуелна величина вашег процеса повећава за 72 КБ, његова <стронг>стална величина скупа (РСС) – количина физичке РАМ меморије која се стварно троши – повећава се само за странице које заиста додирнете. За један <стронг>нови инт, то је обично једна страница од 4 КБ, плус странице које метаподаци арене заузимају. Преостали виртуелни простор се налази тамо, спреман за употребу, не кошта ништа осим адресног простора — од чега имате 128 ТБ на 64-битном Линук систему. <п>Ова разлика је критична када се профилишу и надгледају производне апликације. Ако правите софтвер који треба да прати стварну потрошњу ресурса — било да се ради о СааС бацкенд-у, микросервису или цевоводу за анализу попут оних који раде на платформама као што је <стронг>Меваиз за пословне операције — увек треба да надгледате РСС уместо виртуелне величине. Алатке као што су <стронг>/проц/[пид]/смапс, <стронг>валгринд --тоол=массиф и <стронг>пмап могу да вам дају тачне отиске физичке меморије уместо да обмањују податке о виртуелној меморији. <х2>Како различити алокатори рукују првом алокацијом <п>Број од 72 КБ је специфичан за глибц-ов птмаллоц2. Други алокатори праве различите компромисе, а према томе се разликују и почетни трошкови алокације. Разумевање ових разлика је драгоцено када бирате алокатор за апликације које су осетљиве на перформансе. <ул> <ли><стронг>јемаллоц (користи га Фацебоок, ФрееБСД) — Користи грануларнију структуру арене са локалним кешовима. Почетни додатни трошкови имају тенденцију да буду већи (често 200+ КБ), али испоручују боље перформансе у више нити због смањене борбе за закључавање. <ли><стронг>тцмаллоц (Гоогле-ов Маллоц за кеширање нити) — Подразумевано додељује кеш меморију по нити од приближно 2 МБ, уз агресивну пре-алокацију. Почетни трошкови су већи, али накнадна мала издвајања су изузетно брза. <ли><стронг>мусл либц-ов маллоц — Користи много једноставнији дизајн заснован на <стронг>ммап за све алокације. Почетни трошкови су минимални (често само 4 КБ по додели), али су трошкови по додели већи због чешћих системских позива. <ли><стронг>мималлоц (Мицрософт) — Користи доделу засновану на сегментима са сегментима од 64 МБ. Прва алокација покреће виртуелну резервацију од 64 МБ (са минималном физичком посвећеношћу), адресни простор за трговину за изузетну локацију и пропусност. <п>Избор између ових алокатора у потпуности зависи од вашег оптерећења. За дуготрајне серверске апликације са тешком вишенитном алокацијом, јемаллоц или тцмаллоц обично надмашује глибц-ов подразумевани учинак. За уграђене системе са ограниченом меморијом, муслов једноставнији приступ може бити пожељнији упркос нижој пропусности. За већину десктоп и серверских апликација опште намене, почетни трошкови птмаллоц2 од 72 КБ представљају разумну подразумевану вредност која добро функционише без подешавања. <х2>Подешавање понашања почетне алокације <п>Ако су подразумевани почетни трошкови од 72 КБ заиста проблематични за ваш случај употребе — можда покрећете хиљаде краткотрајних процеса, од којих сваки чини само неколико алокација — глибц обезбеђује неколико подешавања преко <стронг>маллопт() и <стронг>МАЛЛОЦ_ породице варијабли окружења. <п>Параметар <стронг>М_ТОП_ПАД контролише колико додатне меморије алокатор захтева осим онога што је тренутно потребно. Постављање на 0 помоћу <стронг>маллопт(М_ТОП_ПАД, 0) говори алокатору да захтева само оно што је потребно, значајно смањујући почетне трошкове. Параметар <стронг>М_ММАП_ТХРЕСХОЛД контролише величину изнад које алокације користе <стронг>ммап уместо арене. <стронг>М_ТРИМ_ТХРЕСХОЛД контролише када се ослобођена меморија врати у ОС. А од глибц 2.26, подешавања <стронг>глибц.маллоц.тцацхе_цоунт и <стронг>глибц.маллоц.тцацхе_мак вам омогућавају да контролишете понашање кеша нити. <п>Међутим, реч опреза: подешавање ових параметара без пажљивог бенчмаркинга скоро увек погоршава ствари. Подразумеване вредности су изабране на основу опсежног профилисања у стварном свету и представљају слатку тачку за огромну већину радних оптерећења. Осим ако немате јаке доказе из производног профилисања да су маллоц оверхеад уско грло — и ако сте измерили утицај својих промена — оставите подразумеване вредности на миру. Превремена оптимизација алокатора је посебно подмукао облик бријања јака који је потрошио безброј инжењерских сати уз занемарљиву корист. <х2>Шта нас ово учи о системском програмирању <п>Мистерија прве алокације од 72 КБ је, у својој сржи, лекција о <стронг>слојевима апстракције. Ц++ вам даје илузију да <стронг>нови инт додељује 4 бајта. Језички стандард тако каже. Ваш ментални модел тако каже. Али између вашег кода и хардвера налази се гомила софистицираних система — Ц++ рунтиме, Ц библиотека алокатор, подсистем виртуелне меморије кернела и хардверски ММУ и ТЛБ — сваки додаје своје понашање, оптимизације и трошкове. <п>Ово није мана. То је цела поента системског софтвера. Сваки слој постоји да би решио прави проблем: алокатор постоји тако да не морате да упућујете системске позиве за сваку алокацију. Систем виртуелне меморије постоји тако да не морате директно да управљате физичком меморијом. Руковалац грешком странице постоји тако да се меморија предаје лењо и ефикасно. Сваки слој мења малу количину транспарентности за велику количину перформанси и погодности. <п>Програмери који граде најпоузданије системе са најбољим учинком су они који разумеју ове слојеве — не зато што морају стално да размишљају о њима, већ зато што када се деси нешто неочекивано (као што је мистериозна алокација од 72 КБ), они имају ментални модел да разумеју зашто. Без обзира да ли градите систем трговања у реалном времену, машину за игре или пословну платформу која опслужује хиљаде корисника, способност размишљања о томе шта ваш код заправо ради на нивоу система је оно што одваја компетентне програмере од изузетних. 72 КБ није грешка. Ваш алокатор бриљантно ради свој посао. <див стиле="бацкгроунд:#ф0ф9фф;бордер-лефт:4пк солид #3б82ф6;паддинг:20пк;маргин:24пк 0;бордер-радиус:0 8пк 8пк 0"> <х3 стиле="маргин:0 0 8пк;цолор:#1е3а5ф;фонт-сизе:18пк">Изградите свој пословни ОС данас <п стиле="маргин:0 0 12пк;цолор:#475569">Од слободњака до агенција, Меваиз покреће 138.000+ предузећа са 207 интегрисаних модула. Почните бесплатно, надоградите када растете. <а хреф="хттпс://апп.меваиз.цом/регистер" стиле="дисплаи:инлине-блоцк;бацкгроунд:#3б82ф6;цолор:#ффф;паддинг:10пк 24пк;бордер-радиус:6пк;тект-децоратион:ноне;фонт-веигхт:600">Направи бесплатан налог → <сцрипт типе="апплицатион/лд+јсон">{"@цонтект":"хттпс:\/\/сцхема.орг","@типе":"ФАКПаге","маинЕнтити":[{"@типе":"Куестион","наме":"Изградите свој пословни ОС данас","аццептедАнсвер":{"@типе":"Менаваи":"Менаваис агерс","Међуспремник фрееланце"," 138.000+ предузећа са 207 интегрисаних модула Почните бесплатно, надоградите када растете."}}]}

Try Mewayz Free

All-in-one platform for CRM, invoicing, projects, HR & more. No credit card required.

Start managing your business smarter today

Join 30,000+ businesses. Free forever plan · No credit card required.

Ready to put this into practice?

Join 30,000+ businesses using Mewayz. Free forever plan — no credit card required.

Start Free Trial →

Ready to take action?

Start your free Mewayz trial today

All-in-one business platform. No credit card required.

Start Free →

14-day free trial · No credit card · Cancel anytime