பெரிய பக்கங்களின் நன்மைகள் மற்றும் தீமைகள்

பெரிய பக்கங்களின் நன்மைகள் மற்றும் தீமைகள்

பாடநெறி மாணவர்களுக்காக தயாரிக்கப்பட்ட கட்டுரையின் மொழிபெயர்ப்பு "லினக்ஸ் நிர்வாகி".

முன்பு, லினக்ஸில் Hugepages ஐ எவ்வாறு சோதிப்பது மற்றும் செயல்படுத்துவது என்பது பற்றி பேசினேன்.
நீங்கள் உண்மையில் Hugepages பயன்படுத்த ஒரு இடம் இருந்தால் மட்டுமே இந்த கட்டுரை பயனுள்ளதாக இருக்கும். Hugepages மாயமாக உற்பத்தித்திறனை மேம்படுத்தும் என்ற எதிர்பார்ப்பால் ஏமாற்றப்பட்ட பலரை நான் சந்தித்திருக்கிறேன். இருப்பினும், பெரிய பேஜிங் ஒரு சிக்கலான தலைப்பு மற்றும் தவறாகப் பயன்படுத்தினால் செயல்திறனைக் குறைக்கலாம்.

பகுதி 1: லினக்ஸில் பெரிய பக்கங்கள் இயக்கப்பட்டுள்ளதா என்பதைச் சரிபார்த்தல் (அசல் இங்கே)

பிரச்சனை:
உங்கள் கணினியில் HugePages இயக்கப்பட்டுள்ளதா என்பதை நீங்கள் சரிபார்க்க வேண்டும்.

தீர்வு:
இது மிகவும் எளிமையானது:

cat /sys/kernel/mm/transparent_hugepage/enabled

இது போன்ற ஒன்றை நீங்கள் பெறுவீர்கள்:

always [madvise] never

கிடைக்கக்கூடிய விருப்பங்களின் பட்டியலைக் காண்பீர்கள் (எப்போதும், வெறித்தனமான, ஒருபோதும்), மற்றும் தற்போது செயலில் உள்ள விருப்பம் அடைப்புக்குறிக்குள் இணைக்கப்படும் (இயல்புநிலையாக வெறித்தனமாக).

வெறித்தனமாக என்று அர்த்தம் transparent hugepages பெரிய பக்கங்களைப் பயன்படுத்தி வெளிப்படையாகக் கோரும் நினைவகப் பகுதிகளுக்கு மட்டுமே இயக்கப்பட்டது பைத்தியம் (2).

எப்போதும் என்று அர்த்தம் transparent hugepages எல்லா செயல்முறைகளுக்கும் எப்போதும் இயக்கப்படும். இது வழக்கமாக செயல்திறனை மேம்படுத்துகிறது, ஆனால் பல செயல்முறைகள் சிறிய அளவிலான நினைவகத்தை உட்கொண்டால், ஒட்டுமொத்த நினைவக சுமை வியத்தகு அளவில் அதிகரிக்கும்.

ஒருபோதும் என்று அர்த்தம் transparent hugepages madvise ஐப் பயன்படுத்தி கோரப்பட்டாலும் சேர்க்கப்படாது. மேலும் அறிய, தொடர்பு கொள்ளவும் ஆவணங்கள் லினக்ஸ் கர்னல்கள்.

இயல்புநிலை மதிப்பை எவ்வாறு மாற்றுவது

விருப்பம் 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 ஐப் பயன்படுத்துவதால் ஏற்படும் நன்மைகள், தீமைகள் மற்றும் சாத்தியமான இடர்பாடுகள் ஆகியவற்றைத் தேர்ந்தெடுத்து விளக்க முயற்சிப்போம். ஹூஜ்பேஜ்கள் ஒரு சஞ்சீவி என்று நினைத்து ஏமாற்றும் நபர்களுக்கு தொழில்நுட்ப ரீதியாக சிக்கலான மற்றும் மிதமிஞ்சிய கட்டுரையைப் புரிந்துகொள்வது கடினமாக இருக்கும் என்பதால், எளிமைக்காக துல்லியத்தை நான் தியாகம் செய்வேன். நிறைய தலைப்புகள் மிகவும் சிக்கலானவை மற்றும் மிகவும் எளிமைப்படுத்தப்பட்டவை என்பதை நினைவில் கொள்வது மதிப்பு.

லினக்ஸில் இயங்கும் 64-பிட் x86 சிஸ்டம்களைப் பற்றி நாங்கள் பேசுகிறோம் என்பதையும், எந்தவொரு நவீன லினக்ஸிலும் உள்ளதைப் போலவே, வெளிப்படையான பெரிய பக்கங்களை (பெரிய பக்கங்கள் மேலெழுதப்படாமல் இருப்பது ஒரு பாதகமாக இல்லை என்பதால்) கணினி ஆதரிக்கிறது என்று நான் கருதுகிறேன். சூழல்.

மேலும் தொழில்நுட்ப விளக்கத்தை கீழே உள்ள இணைப்புகளில் இணைக்கிறேன்.

மெய்நிகர் நினைவகம்

நீங்கள் C++ புரோகிராமர் என்றால், நினைவகத்தில் உள்ள பொருள்களுக்கு குறிப்பிட்ட முகவரிகள் (சுட்டி மதிப்புகள்) இருப்பதை நீங்கள் அறிவீர்கள்.

இருப்பினும், இந்த முகவரிகள் நினைவகத்தில் உள்ள இயற்பியல் முகவரிகளை (RAM முகவரிகள்) பிரதிபலிக்க வேண்டிய அவசியமில்லை. அவை மெய்நிகர் நினைவகத்தில் முகவரிகளைக் குறிக்கின்றன. செயலியில் ஒரு சிறப்பு MMU (நினைவக மேலாண்மை அலகு) தொகுதி உள்ளது, இது கர்னல் மெய்நிகர் நினைவகத்தை ஒரு இயற்பியல் இருப்பிடத்திற்கு வரைபடமாக்க உதவுகிறது.

இந்த அணுகுமுறை பல நன்மைகளைக் கொண்டுள்ளது, ஆனால் மிக முக்கியமானவை:

  • செயல்திறன் (பல்வேறு காரணங்களுக்காக);
  • நிரல் தனிமைப்படுத்தல், அதாவது, எந்த நிரலும் மற்றொரு நிரலின் நினைவகத்திலிருந்து படிக்க முடியாது.

பக்கங்கள் என்றால் என்ன?

மெய்நிகர் நினைவகம் பக்கங்களாக பிரிக்கப்பட்டுள்ளது. ஒவ்வொரு பக்கமும் ஒரு குறிப்பிட்ட இயற்பியல் நினைவகத்தை சுட்டிக்காட்டுகிறது, அது ரேமில் உள்ள ஒரு பகுதியை சுட்டிக்காட்டலாம் அல்லது வீடியோ அட்டை போன்ற இயற்பியல் சாதனத்திற்கு ஒதுக்கப்பட்ட முகவரியை சுட்டிக்காட்டலாம்.

நீங்கள் கையாளும் பெரும்பாலான பக்கங்கள் RAM ஐ சுட்டிக்காட்டுகின்றன அல்லது மாற்றப்படுகின்றன, அதாவது அவை உங்கள் வன் அல்லது SSD இல் சேமிக்கப்படும். கர்னல் ஒவ்வொரு பக்கத்தின் இயற்பியல் அமைப்பையும் நிர்வகிக்கிறது. ஏமாற்றப்பட்ட பக்கம் அணுகப்பட்டால், நினைவகத்தை அணுக முயற்சிக்கும் நூலை கர்னல் நிறுத்தி, பக்கத்தை ஹார்ட் டிரைவ்/எஸ்எஸ்டியில் இருந்து RAM இல் படித்து, பின்னர் தொடரிழையை இயக்கும்.

இந்த செயல்முறை ஸ்ட்ரீம் வெளிப்படையானது, அதாவது HDD/SSD இலிருந்து நேரடியாகப் படிக்க வேண்டிய அவசியமில்லை. சாதாரண பக்கங்களின் அளவு 4096 பைட்டுகள். பெரிய பக்கங்களின் அளவு 2 மெகாபைட்கள்.

மொழிபெயர்ப்பு-தொடர்புடைய இடையக (TLB)

ஒரு நிரல் நினைவகத்தின் பக்கத்தை அணுகும் போது, ​​எந்த இயற்பியல் பக்கத்திலிருந்து தரவைப் படிக்க வேண்டும் என்பதை CPU அறிந்திருக்க வேண்டும் (அதாவது, மெய்நிகர் முகவரி வரைபடம் உள்ளது).

கர்னலில் ஒரு தரவு அமைப்பு (பக்க அட்டவணை) உள்ளது, அதில் பயன்படுத்தப்படும் பக்கங்களைப் பற்றிய அனைத்து தகவல்களும் உள்ளன. இந்த தரவு கட்டமைப்பைப் பயன்படுத்தி, நீங்கள் ஒரு மெய்நிகர் முகவரியை ஒரு இயற்பியல் முகவரிக்கு வரைபடமாக்கலாம்.

இருப்பினும், பக்க அட்டவணை மிகவும் சிக்கலானது மற்றும் மெதுவாக உள்ளது, எனவே ஒரு செயல்முறை நினைவகத்தை அணுகும் ஒவ்வொரு முறையும் முழு தரவு கட்டமைப்பையும் பகுப்பாய்வு செய்ய முடியாது.

அதிர்ஷ்டவசமாக, எங்கள் செயலியில் ஒரு TLB உள்ளது, இது மெய்நிகர் மற்றும் இயற்பியல் முகவரிகளுக்கு இடையே மேப்பிங்கை தேக்குகிறது. இதன் பொருள், முதல் அணுகல் முயற்சியில் பக்க அட்டவணையை அலச வேண்டும் என்றாலும், பக்கத்திற்கான அனைத்து அடுத்தடுத்த அணுகல்களையும் TLB இல் கையாளலாம், இது விரைவான செயல்பாட்டை அனுமதிக்கிறது.

இது ஒரு இயற்பியல் சாதனமாக செயல்படுத்தப்படுவதால் (இது முதல் இடத்தில் வேகமாக இருக்கும்), அதன் திறன் குறைவாக உள்ளது. எனவே நீங்கள் கூடுதல் பக்கங்களை அணுக விரும்பினால், TLB அனைத்து மேப்பிங்குகளையும் சேமிக்க முடியாது, இதனால் உங்கள் நிரல் மிகவும் மெதுவாக இயங்கும்.

பெரிய பக்கங்கள் மீட்புக்கு வருகின்றன

TLB வழிதல் தவிர்க்க நாம் என்ன செய்யலாம்? (நிரலுக்கு இன்னும் அதே அளவு நினைவகம் தேவை என்று நாங்கள் கருதுகிறோம்).

இங்குதான் Hugepages வருகிறது. ஒரு TLB நுழைவு தேவைப்படும் 4096 பைட்டுகளுக்குப் பதிலாக, ஒரு TLB உள்ளீடு இப்போது 2 மெகாபைட்களை குறிக்கும். TLB இல் 512 உள்ளீடுகள் உள்ளன என்று வைத்துக்கொள்வோம், இங்கே பெரிய பக்கங்கள் இல்லாமல் நாம் பொருத்தலாம்:

4096 b⋅512=2 MB

பிறகு அவர்களுடன் எப்படி ஒப்பிடலாம்:

2 MB⋅512=1 GB

இதனால்தான் Hugepages அருமை. அவர்கள் அதிக முயற்சி இல்லாமல் உற்பத்தியை மேம்படுத்த முடியும். ஆனால் இங்கே குறிப்பிடத்தக்க எச்சரிக்கைகள் உள்ளன.

பெரிய பக்கங்கள் ஏமாற்றுதல்

ஒவ்வொரு நினைவகப் பக்கமும் எவ்வளவு அடிக்கடி பயன்படுத்தப்படுகிறது என்பதை கர்னல் தானாகவே கண்காணிக்கும். போதுமான இயற்பியல் நினைவகம் (ரேம்) இல்லாவிட்டால், முக்கியமான பக்கங்களுக்கு சில ரேமை விடுவிக்க கர்னல் குறைவான முக்கியத்துவம் வாய்ந்த (குறைவாகப் பயன்படுத்தப்படும்) பக்கங்களை ஹார்ட் டிஸ்கிற்கு நகர்த்தும்.
கொள்கையளவில், பெரிய பக்கங்களுக்கும் இது பொருந்தும். இருப்பினும், கர்னல் முழு பக்கங்களையும் மட்டுமே மாற்ற முடியும், தனிப்பட்ட பைட்டுகள் அல்ல.

எங்களிடம் இது போன்ற ஒரு நிரல் உள்ளது என்று வைத்துக்கொள்வோம்:

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

இந்த நிலையில், கர்னல் ஒரு பைட்டைப் படிக்க, ஹார்ட் டிரைவ்/எஸ்எஸ்டியிலிருந்து 2 மெகாபைட் தகவல்களை மாற்ற வேண்டும் (படிக்க) வேண்டும். வழக்கமான பக்கங்களைப் பொறுத்தவரை, ஹார்ட் டிரைவ்/எஸ்எஸ்டியில் இருந்து 4096 பைட்டுகள் மட்டுமே படிக்க வேண்டும்.

எனவே, பெரிய பக்கம் மேலெழுதப்பட்டால், முழுப் பக்கத்தையும் அணுக வேண்டும் என்றால் மட்டுமே வேகமாகப் படிக்க முடியும். இதன் பொருள் நீங்கள் நினைவகத்தின் வெவ்வேறு பகுதிகளை தோராயமாக அணுக முயற்சிக்கிறீர்கள் மற்றும் இரண்டு கிலோபைட்களைப் படிக்கிறீர்கள் என்றால், நீங்கள் வழக்கமான பக்கங்களைப் பயன்படுத்த வேண்டும், வேறு எதையும் பற்றி கவலைப்பட வேண்டாம்.

மறுபுறம், நீங்கள் நினைவகத்தின் பெரும்பகுதியை தொடர்ச்சியாக அணுக வேண்டும் என்றால், பெரிய பக்கங்கள் உங்கள் செயல்திறனை மேம்படுத்தும். இருப்பினும், அதை நீங்களே சோதித்துப் பார்க்க வேண்டும் (சுருக்க மென்பொருள் மூலம் அல்ல) மற்றும் வேகமாக செயல்படுவதைப் பார்க்கவும்.

நினைவகத்தில் ஒதுக்கீடு

நீங்கள் C ஐ எழுதினால், குவியலில் இருந்து தன்னிச்சையாக சிறிய (அல்லது கிட்டத்தட்ட தன்னிச்சையாக பெரிய) அளவு நினைவகத்தைக் கோரலாம் என்பது உங்களுக்குத் தெரியும் malloc(). உங்களுக்கு 30 பைட்டுகள் நினைவகம் தேவை என்று வைத்துக்கொள்வோம்:

char* mymemory = malloc(30);

ஒரு புரோகிராமருக்கு, நீங்கள் இயக்க முறைமையிலிருந்து 30 பைட்டுகள் நினைவகத்தை "கோரிக்கிறீர்கள்" என்று தோன்றலாம் மற்றும் சில மெய்நிகர் நினைவகத்திற்கு ஒரு சுட்டிக்காட்டி திரும்பும். ஆனால் உண்மையில் malloc () செயல்பாட்டிற்குள் இருந்து அழைக்கும் ஒரு சி செயல்பாடாகும் brk மற்றும் sbrk இயக்க முறைமையிலிருந்து நினைவகத்தைக் கோர அல்லது இலவசம்.

இருப்பினும், ஒவ்வொரு ஒதுக்கீட்டிற்கும் அதிகமான நினைவகத்தைக் கோருவது திறமையற்றது; சில நினைவக பிரிவு ஏற்கனவே விடுவிக்கப்பட்டிருக்கலாம் (free()), மற்றும் நாம் அதை மீண்டும் பயன்படுத்தலாம். malloc() விடுவிக்கப்பட்ட நினைவகத்தை மீண்டும் பயன்படுத்த மிகவும் சிக்கலான வழிமுறைகளை செயல்படுத்துகிறது.

அதே நேரத்தில், எல்லாமே உங்களுக்குத் தெரியாமல் நடக்கும், எனவே நீங்கள் ஏன் கவலைப்பட வேண்டும்? ஆனால் சவால் என்பதால் free() என்று அர்த்தம் இல்லை நினைவகம் உடனடியாக இயக்க முறைமைக்கு திரும்பும்.

நினைவக சிதைவு போன்ற ஒன்று உள்ளது. தீவிர நிகழ்வுகளில், சில பைட்டுகள் மட்டுமே பயன்படுத்தப்படும் குவியல் பிரிவுகள் உள்ளன, இடையில் உள்ள அனைத்தும் விடுவிக்கப்பட்டன. (free()).

நினைவக துண்டு துண்டானது நம்பமுடியாத சிக்கலான தலைப்பு என்பதை நினைவில் கொள்ளவும், மேலும் ஒரு நிரலில் சிறிய மாற்றங்கள் கூட குறிப்பிடத்தக்க தாக்கத்தை ஏற்படுத்தும். பெரும்பாலான சந்தர்ப்பங்களில், நிரல்கள் குறிப்பிடத்தக்க நினைவக சிதைவை ஏற்படுத்தாது, ஆனால் குவியலின் சில பகுதியில் துண்டு துண்டாக இருப்பதில் சிக்கல் இருந்தால், பெரிய பக்கங்கள் நிலைமையை மோசமாக்கும் என்பதை நீங்கள் அறிந்திருக்க வேண்டும்.

பெரிய பக்கங்களின் தேர்ந்தெடுக்கப்பட்ட பயன்பாடு

இந்தக் கட்டுரையைப் படித்த பிறகு, உங்கள் நிரலின் எந்தப் பகுதிகள் பெரிய பக்கங்களைப் பயன்படுத்துவதன் மூலம் பயனடையலாம் மற்றும் எது முடியாது என்பதை நீங்கள் தீர்மானித்துள்ளீர்கள். எனவே பெரிய பக்கங்கள் அனைத்தும் செயல்படுத்தப்பட வேண்டுமா?

அதிர்ஷ்டவசமாக நீங்கள் பயன்படுத்தலாம் madvise()அது பயனுள்ளதாக இருக்கும் அந்த நினைவக பகுதிகளில் மட்டும் பெரிய பேஜிங் செயல்படுத்த.

முதலில், பெரிய பக்கங்கள் 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)

இந்த முறை நினைவகத்தை எவ்வாறு நிர்வகிப்பது என்பது குறித்த கர்னலுக்கான ஆலோசனையாகும் என்பதை நினைவில் கொள்ளவும். கொடுக்கப்பட்ட நினைவகத்திற்கு கர்னல் தானாகவே பெரிய பக்கங்களைப் பயன்படுத்தும் என்று இது அர்த்தப்படுத்துவதில்லை.

ஆவணங்களைப் பார்க்கவும் (manpage)madviseநினைவக மேலாண்மை மற்றும் பற்றி மேலும் அறிய madvise(), இந்த தலைப்பு நம்பமுடியாத அளவிற்கு செங்குத்தான கற்றல் வளைவைக் கொண்டுள்ளது. எனவே, நீங்கள் அதில் உண்மையிலேயே சிறந்து விளங்க விரும்பினால், ஏதேனும் நேர்மறையான முடிவுகளை எதிர்பார்க்கும் முன் சில வாரங்களுக்குப் படித்து சோதிக்கத் தயாராகுங்கள்.

என்ன படிக்க வேண்டும்?

ஒரு கேள்வி இருக்கிறதா? கருத்துகளில் எழுதுங்கள்!

ஆதாரம்: www.habr.com

கருத்தைச் சேர்