HugePages артықшылықтары мен кемшіліктері

HugePages артықшылықтары мен кемшіліктері

Курс студенттері үшін дайындалған мақаланың аудармасы «Linux әкімшісі».

Бұрын мен Linux жүйесінде Hugepages-ті сынау және қосу туралы айтқан болатынмын.
Бұл мақала тек сізде Hugepages-ті пайдаланатын орыныңыз болған жағдайда ғана пайдалы болады. Мен Hugepages өнімділікті сиқырлы түрде жақсартады деген үмітпен алданған көптеген адамдарды кездестірдім. Дегенмен, үлкен пейджинг - күрделі тақырып және дұрыс пайдаланылмаса өнімділікті төмендетуі мүмкін.

1-бөлім: Linux жүйесінде үлкен беттердің қосылғанын тексеру (түпнұсқа осында)

Мәселе:
Жүйеде HugePages қосылғанын тексеру керек.

шешім:
Бұл өте қарапайым:

cat /sys/kernel/mm/transparent_hugepage/enabled

Сіз келесідей нәрсені аласыз:

always [madvise] never

Сіз қол жетімді опциялардың тізімін көресіз (әрқашан, ақылсыз, ешқашан) және ағымдағы белсенді опция жақшаға алынады (әдепкі бойынша жынды).

жынды дегенді білдіреді transparent hugepages пайдалану арқылы үлкен беттерді анық сұрайтын жад аймақтары үшін ғана қосылған Madvise(2).

әрқашан дегенді білдіреді transparent hugepages барлық процестер үшін әрқашан қосулы. Бұл әдетте өнімділікті жақсартады, бірақ көптеген процестер жадтың аз мөлшерін тұтынатын пайдалану жағдайы болса, жалпы жад жүктемесі күрт артуы мүмкін.

ешқашан да дегенді білдіреді transparent hugepages madvise арқылы сұралғанда да қосылмайды. Қосымша ақпарат алу үшін хабарласыңыз құжаттама Linux ядролары.

Әдепкі мәнді қалай өзгертуге болады

1 нұсқасы: Тікелей өзгерту sysfs (қайта жүктегеннен кейін параметр әдепкі мәніне оралады):

echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabled

2 нұсқасы: Өзгертілген конфигурациямен ядроны қайта құрастыру арқылы жүйенің әдепкі мәнін өзгертіңіз (бұл опция теңшелетін ядроны пайдалансаңыз ғана ұсынылады):

  • Әрқашан әдепкі бойынша орнату үшін мынаны пайдаланыңыз:
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Madvise параметрін әдепкі етіп орнату үшін мынаны пайдаланыңыз:
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

2-бөлім: HugePages артықшылықтары мен кемшіліктері

Біз Hugepages қолданудың артықшылықтарын, кемшіліктерін және мүмкін болатын қателіктерін таңдаулы түрде түсіндіруге тырысамыз. Технологиялық тұрғыдан күрделі және педантикалық мақаланы Hugepages панацея деп санайтын адамдар үшін түсіну қиын болатындықтан, мен қарапайымдылық үшін дәлдікті құрбан етемін. Көптеген тақырыптар шынымен күрделі және сондықтан айтарлықтай жеңілдетілгенін есте ұстаған жөн.

Әңгіме Linux жүйесінде жұмыс істейтін 64 биттік x86 жүйелері туралы болып жатқанын және мен жай ғана жүйе мөлдір үлкен беттерді қолдайды деп болжағанымды ескеріңіз (өйткені үлкен беттердің қайта жазылмауы кемшілік емес), кез келген қазіргі дерлік Linux-тегідей. қоршаған орта.

Мен төмендегі сілтемелерде қосымша техникалық сипаттаманы қосамын.

Виртуалды жады

Егер сіз C++ бағдарламашысы болсаңыз, жадтағы нысандардың нақты мекенжайлары (көрсеткіш мәндері) бар екенін білесіз.

Дегенмен, бұл адрестер жадтағы физикалық адрестерді міндетті түрде көрсетпейді (RAM мекенжайлары). Олар виртуалды жадтағы мекенжайларды көрсетеді. Процессорда ядроның виртуалды жадыны физикалық орынға салыстыруға көмектесетін арнайы MMU (жадты басқару блогы) модулі бар.

Бұл тәсілдің көптеген артықшылықтары бар, бірақ ең маңыздылары:

  • Өнімділік (әртүрлі себептер бойынша);
  • Бағдарламаны оқшаулау, яғни ешбір программа басқа программаның жадынан оқи алмайды.

Беттер дегеніміз не?

Виртуалды жады беттерге бөлінген. Әрбір жеке бет белгілі бір физикалық жадты көрсетеді, ол жедел жадтағы аумақты көрсете алады немесе бейне карта сияқты физикалық құрылғыға тағайындалған мекенжайды көрсете алады.

Сіз қарастыратын беттердің көпшілігі жедел жадты көрсетеді немесе ауыстырылады, яғни олар қатты дискіде немесе SSD-де сақталады. Ядро әрбір беттің физикалық орналасуын басқарады. Жалған бетке қатынасу болса, ядро ​​жадқа кіруге әрекеттеніп жатқан ағынды тоқтатады, бетті қатты диск/SSD-ден ЖЖҚ-ға оқиды, содан кейін ағынды орындауды жалғастырады.

Бұл процесс ағынды мөлдір, яғни ол HDD/SSD-ден тікелей оқылмайды. Қалыпты беттердің өлшемі 4096 байт. Үлкен беттердің өлшемі - 2 мегабайт.

Аударма-ассоциативті буфер (TLB)

Бағдарлама жад бетіне кіргенде, орталық процессор деректерді қай физикалық беттен оқу керектігін білуі керек (яғни виртуалды мекенжай картасы бар).

Ядрода пайдаланылатын беттер туралы барлық ақпаратты қамтитын деректер құрылымы (бет кестесі) бар. Бұл деректер құрылымын пайдалана отырып, виртуалды мекенжайды физикалық мекенжайға салыстыруға болады.

Дегенмен, беттер кестесі өте күрделі және баяу, сондықтан процесс жадқа кірген сайын біз бүкіл деректер құрылымын талдай алмаймыз.

Бақытымызға орай, біздің процессорымызда виртуалды және физикалық мекенжайлар арасындағы салыстыруды кэштейтін TLB бар. Бұл бірінші қатынау әрекетінде бет кестесін талдау қажет болғанымен, бетке кейінгі барлық кірулерді жылдам жұмыс істеуге мүмкіндік беретін TLB жүйесінде өңдеуге болатынын білдіреді.

Ол физикалық құрылғы ретінде іске асырылғандықтан (бұл оны бірінші кезекте жылдам етеді), оның сыйымдылығы шектеулі. Сондықтан көбірек беттерге қол жеткізгіңіз келсе, TLB олардың барлығы үшін салыстыруларды сақтай алмайды, бұл сіздің бағдарламаңыздың әлдеқайда баяу жұмыс істеуіне себеп болады.

Құтқаруға Гигепж келеді

Сонымен, TLB толып кетпеу үшін не істей аламыз? (Бағдарлама әлі де бірдей жад көлемін қажет етеді деп есептейміз).

Дәл осы жерде Хугепжс келеді. Тек бір TLB жазбасын қажет ететін 4096 байттың орнына, бір TLB жазбасы енді үлкен 2 мегабайтты көрсете алады. TLB-де 512 жазба бар делік, мұнда Hugepagesсіз біз сәйкес келе аламыз:

4096 b⋅512=2 MB

Сонда олармен қалай салыстыруға болады:

2 MB⋅512=1 GB

Сондықтан Hugepages керемет. Олар көп күш жұмсамай-ақ өнімділікті арттыра алады. Бірақ бұл жерде маңызды ескертулер бар.

Үлкен беттерді бұрмалау

Ядро әрбір жад беті қаншалықты жиі пайдаланылатынын автоматты түрде бақылайды. Физикалық жад (ЖЖҚ) жеткіліксіз болса, маңыздырақ беттер үшін жедел жадты босату үшін ядро ​​маңызды емес (сирек қолданылатын) беттерді қатты дискіге жылжытады.
Негізінде бұл Hugepages-ке де қатысты. Дегенмен, ядро ​​​​жеке байттарды емес, бүкіл беттерді ғана ауыстыра алады.

Бізде осындай бағдарлама бар делік:

char* mymemory = malloc(2*1024*1024); // Возьмем это за одну Hugepage!
// Заполним mymemory какими-либо данными
// Сделаем много других вещей,
// которые приведут к подмене страницы mymemory
// ...
// Запросим доступ только к первому байту
putchar(mymemory[0]); 

Бұл жағдайда сіз бір байтты оқуыңыз үшін ядроға қатты диск/SSD-ден 2 мегабайт ақпаратты ауыстыру (оқу) қажет болады. Кәдімгі беттерге келетін болсақ, қатты диск/SSD-ден тек 4096 байтты оқу керек.

Сондықтан, егер үлкен бет қайта анықталса, бүкіл бетке кіру қажет болса, оны оқу жылдамырақ болады. Бұл жадтың әртүрлі бөліктеріне кездейсоқ қол жеткізуге тырыссаңыз және бірнеше килобайтты оқып жатсаңыз, әдеттегі беттерді пайдаланып, басқа ештеңе туралы алаңдамау керек дегенді білдіреді.

Екінші жағынан, жадтың үлкен бөлігіне дәйекті түрде қол жеткізу қажет болса, үлкен беттер өнімділікті жақсартады. Дегенмен, оны өзіңіз сынап көруіңіз керек (дерексіз бағдарламалық жасақтамамен емес) және жылдамырақ жұмыс істейтінін көріңіз.

Жадта бөлу

Егер сіз C деп жазсаңыз, үймеден ерікті түрде шағын (немесе ерікті түрде үлкен дерлік) жад көлемін сұрауға болатынын білесіз. malloc(). Сізге 30 байт жад қажет делік:

char* mymemory = malloc(30);

Бағдарламалаушыға операциялық жүйеден 30 байт жадты «сұрайтын» және меңзерді кейбір виртуалды жадқа қайтарып жатқандай көрінуі мүмкін. Бірақ шын мәнінде malloc () функцияның ішінен шақыратын C функциясы ғана brk және sbrk операциялық жүйеден жадты сұрау немесе босату.

Дегенмен, әрбір бөлу үшін көбірек жадты сұрау тиімсіз; кейбір жад сегменті әлдеқашан босатылған болуы мүмкін (free()), және біз оны қайта пайдалана аламыз. malloc() бос жадты қайта пайдалану үшін өте күрделі алгоритмдерді жүзеге асырады.

Сонымен қатар, бәрі сіз үшін байқамай өтеді, сондықтан бұл сізді неге алаңдатуы керек? Бірақ қиындық болғандықтан free() бұл дегенді білдірмейді жад міндетті түрде операциялық жүйеге дереу қайтарылады.

Жадтың бөлшектенуі деген бар. Төтенше жағдайларда үйме сегменттер бар, оларда тек бірнеше байт пайдаланылады, ал олардың арасындағы барлығы босатылған. (free()).

Есіңізде болсын, жадты фрагментациялау өте күрделі тақырып және тіпті бағдарламадағы шамалы өзгертулер айтарлықтай әсер етуі мүмкін. Көп жағдайда бағдарламалар жадтың айтарлықтай фрагментациясын тудырмайды, бірақ үйіндінің кейбір аймағында фрагментация мәселесі болса, үлкен беттер жағдайды нашарлатуы мүмкін екенін білуіңіз керек.

Үлкен беттерді таңдаулы пайдалану

Осы мақаланы оқығаннан кейін сіз бағдарламаңыздың қай бөліктері үлкен беттерді пайдалану пайдалы болатынын және қайсысы болмайтынын анықтадыңыз. Сонымен, үлкен беттерді қосу керек пе?

Бақытымызға орай, сіз пайдалана аласыз madvise()тек пайдалы болатын жад аймақтары үшін үлкен бетті қосу.

Алдымен, bigpages madvise() режимінде жұмыс істеп тұрғанын тексеріңіз нұсқаулар мақаланың басында.

Содан кейін пайдаланыңыз madvise()ядроға үлкен беттерді қайда пайдалану керектігін айту үшін.

#include <sys/mman.h>
// Аллоцируйте большое количество памяти, которую будете использовать
size_t size = 256*1024*1024;
char* mymemory = malloc(size);
// Просто включите hugepages…
madvise(mymemory, size, MADV_HUGEPAGE);
// … и задайте следующее
madvise(mymemory, size, MADV_HUGEPAGE | MADV_SEQUENTIAL)

Бұл әдіс жадты қалай басқаруға болатыны туралы ядроға кеңес беру екенін ескеріңіз. Бұл ядро ​​берілген жад үшін үлкен беттерді автоматты түрде пайдаланады дегенді білдірмейді.

Құжаттамаға жүгініңіз (манбет) ақылсызжадты басқару туралы көбірек білу үшін және madvise(), бұл тақырыпта оқудың керемет қисығы бар. Сондықтан, егер сіз оны шынымен жақсы меңгергіңіз келсе, кез келген оң нәтиже күтпес бұрын бірнеше апта оқып, сынақтан өтуге дайындалыңыз.

Не оқу керек?

Сұрақ бар ма? Пікірлерге жазыңыз!

Ақпарат көзі: www.habr.com

пікір қалдыру