ஜாவாஸ்கிரிப்டில் உண்மையான மல்டித்ரெட்டிங்கைத் திறக்கவும். இந்த விரிவான வழிகாட்டி SharedArrayBuffer, Atomics, Web Workers மற்றும் உயர் செயல்திறன் கொண்ட வலைப் பயன்பாடுகளுக்கான பாதுகாப்புத் தேவைகளை உள்ளடக்கியது.
ஜாவாஸ்கிரிப்ட் SharedArrayBuffer: இணையத்தில் ஒரே நேர நிரலாக்கத்திற்கான ஒரு ஆழமான பார்வை
பல தசாப்தங்களாக, ஜாவாஸ்கிரிப்டின் ஒற்றை-திரெட் (single-threaded) தன்மை அதன் எளிமைக்கும் அதே சமயம் ஒரு குறிப்பிடத்தக்க செயல்திறன் தடைக்கும் காரணமாக இருந்து வருகிறது. நிகழ்வு வளைய மாதிரி (event loop model) பெரும்பாலான பயனர் இடைமுகப் பணிகளுக்கு அழகாக வேலை செய்கிறது, ஆனால் கணக்கீட்டு-தீவிர செயல்பாடுகளை எதிர்கொள்ளும்போது அது திணறுகிறது. நீண்ட நேரம் இயங்கும் கணக்கீடுகள் உலாவியை முடக்கி, ஒரு விரக்தியூட்டும் பயனர் அனுபவத்தை உருவாக்கும். வெப் வொர்க்கர்ஸ் (Web Workers) ஸ்கிரிப்ட்களை பின்னணியில் இயக்க அனுமதிப்பதன் மூலம் ஒரு பகுதி தீர்வை வழங்கினாலும், அவற்றுக்கென ஒரு பெரிய வரம்பு இருந்தது: திறனற்ற தரவுத் தொடர்பு.
இங்கேதான் SharedArrayBuffer
(SAB) வருகிறது, இது இணையத்தில் திரெட்களுக்கு இடையில் உண்மையான, குறைந்த-நிலை நினைவகப் பகிர்வை அறிமுகப்படுத்துவதன் மூலம் விளையாட்டை அடிப்படையில் மாற்றும் ஒரு சக்திவாய்ந்த அம்சமாகும். Atomics
ஆப்ஜெக்ட்டுடன் இணைந்து, SAB உயர்-செயல்திறன், ஒரே நேரப் பயன்பாடுகளின் ஒரு புதிய சகாப்தத்தை நேரடியாக உலாவியில் திறக்கிறது. இருப்பினும், பெரும் சக்தி பெரும் பொறுப்புடன் வருகிறது—மற்றும் சிக்கலுடன்.
இந்த வழிகாட்டி உங்களை ஜாவாஸ்கிரிப்டில் ஒரே நேர நிரலாக்க உலகிற்கு ஒரு ஆழமான பயணத்திற்கு அழைத்துச் செல்லும். அது நமக்கு ஏன் தேவை, SharedArrayBuffer
மற்றும் Atomics
எப்படி வேலை செய்கின்றன, நீங்கள் கவனிக்க வேண்டிய முக்கியமான பாதுகாப்புப் பரிசீலனைகள், மற்றும் நீங்கள் தொடங்குவதற்கான நடைமுறை உதாரணங்களை நாம் ஆராய்வோம்.
பழைய உலகம்: ஜாவாஸ்கிரிப்டின் ஒற்றை-திரெட் மாதிரி மற்றும் அதன் வரம்புகள்
நாம் தீர்வைப் பாராட்டுவதற்கு முன், நாம் சிக்கலை முழுமையாகப் புரிந்து கொள்ள வேண்டும். ஒரு உலாவியில் ஜாவாஸ்கிரிப்ட் இயக்கம் பாரம்பரியமாக ஒரு ஒற்றை திரெட்டில் நடக்கிறது, இது பெரும்பாலும் "முதன்மைத் திரெட்" அல்லது "UI திரெட்" என்று அழைக்கப்படுகிறது.
நிகழ்வு வளையம் (The Event Loop)
முதன்மைத் திரெட் எல்லாவற்றிற்கும் பொறுப்பாகும்: உங்கள் ஜாவாஸ்கிரிப்ட் குறியீட்டை இயக்குவது, பக்கத்தை ரெண்டரிங் செய்வது, பயனர் தொடர்புகளுக்கு (கிளிக்குகள் மற்றும் ஸ்க்ரோல்கள் போன்றவை) பதிலளிப்பது, மற்றும் CSS அனிமேஷன்களை இயக்குவது. இது ஒரு நிகழ்வு வளையத்தைப் பயன்படுத்தி இந்த பணிகளை நிர்வகிக்கிறது, இது தொடர்ந்து செய்திகளின் (பணிகளின்) வரிசையைச் செயலாக்குகிறது. ஒரு பணி முடிக்க நீண்ட நேரம் எடுத்தால், அது முழு வரிசையையும் தடுக்கிறது. வேறு எதுவும் நடக்காது—UI உறைகிறது, அனிமேஷன்கள் தடுமாறுகின்றன, மற்றும் பக்கம் பதிலளிக்காமல் போகிறது.
வெப் வொர்க்கர்ஸ்: சரியான திசையில் ஒரு படி
வெப் வொர்க்கர்ஸ் இந்தச் சிக்கலைக் குறைக்க அறிமுகப்படுத்தப்பட்டன. ஒரு வெப் வொர்க்கர் என்பது அடிப்படையில் ஒரு தனி பின்னணி திரெட்டில் இயங்கும் ஒரு ஸ்கிரிப்ட் ஆகும். நீங்கள் கனமான கணக்கீடுகளை ஒரு வொர்க்கருக்கு மாற்றி, முதன்மைத் திரெட்டை பயனர் இடைமுகத்தைக் கையாள சுதந்திரமாக வைத்திருக்கலாம்.
முதன்மைத் திரெட்டிற்கும் ஒரு வொர்க்கருக்கும் இடையிலான தொடர்பு postMessage()
API வழியாக நடக்கிறது. நீங்கள் தரவை அனுப்பும்போது, அது structured clone algorithm மூலம் கையாளப்படுகிறது. இதன் பொருள் தரவு வரிசைப்படுத்தப்பட்டு, நகலெடுக்கப்பட்டு, பின்னர் வொர்க்கரின் சூழலில் வரிசைப்படுத்தப்படுகிறது. இது பயனுள்ளதாக இருந்தாலும், பெரிய தரவுத்தொகுப்புகளுக்கு இந்த செயல்முறை குறிப்பிடத்தக்க குறைபாடுகளைக் கொண்டுள்ளது:
- செயல்திறன் கூடுதல் சுமை: மெகாபைட்கள் அல்லது ஜிகாபைட்கள் தரவை திரெட்களுக்கு இடையில் நகலெடுப்பது மெதுவாகவும் CPU-தீவிரமாகவும் இருக்கும்.
- நினைவகப் பயன்பாடு: இது நினைவகத்தில் தரவின் ஒரு பிரதியை உருவாக்குகிறது, இது நினைவகக் கட்டுப்பாடுகள் உள்ள சாதனங்களுக்கு ஒரு பெரிய பிரச்சினையாக இருக்கலாம்.
உலாவியில் ஒரு வீடியோ எடிட்டரை கற்பனை செய்து பாருங்கள். ஒரு முழு வீடியோ பிரேமை (இது பல மெகாபைட்களாக இருக்கலாம்) ஒரு நொடிக்கு 60 முறை செயலாக்க ஒரு வொர்க்கருக்கு முன்னும் பின்னுமாக அனுப்புவது தடைசெய்யும் அளவுக்கு விலை உயர்ந்ததாக இருக்கும். இந்த சரியான சிக்கலைத் தீர்க்கத்தான் SharedArrayBuffer
வடிவமைக்கப்பட்டது.
விளையாட்டை மாற்றுபவர்: SharedArrayBuffer
அறிமுகம்
ஒரு SharedArrayBuffer
என்பது ஒரு நிலையான-நீள மூல பைனரி தரவு இடையகம் (raw binary data buffer) ஆகும், இது ஒரு ArrayBuffer
ஐப் போன்றது. முக்கியமான வேறுபாடு என்னவென்றால், ஒரு SharedArrayBuffer
பல திரெட்களில் (எ.கா., முதன்மைத் திரெட் மற்றும் ஒன்று அல்லது அதற்கு மேற்பட்ட வெப் வொர்க்கர்ஸ்) பகிரப்படலாம். நீங்கள் postMessage()
ஐப் பயன்படுத்தி ஒரு SharedArrayBuffer
ஐ "அனுப்பும்போது", நீங்கள் ஒரு நகலை அனுப்பவில்லை; நீங்கள் அதே நினைவகத் தொகுதிக்கு ஒரு குறிப்பை அனுப்புகிறீர்கள்.
இதன் பொருள், ஒரு திரெட்டால் இடையகத்தின் தரவில் செய்யப்படும் எந்த மாற்றங்களும், அதற்கான குறிப்பைக் கொண்ட மற்ற எல்லா திரெட்களுக்கும் உடனடியாகத் தெரியும். இது விலை உயர்ந்த நகல்-மற்றும்-வரிசைப்படுத்தல் படியை நீக்குகிறது, இது கிட்டத்தட்ட உடனடி தரவுப் பகிர்வை செயல்படுத்துகிறது.
இதை இப்படி நினைத்துப் பாருங்கள்:
postMessage()
உடன் வெப் வொர்க்கர்ஸ்: இது இரண்டு சக ஊழியர்கள் ஒரு ஆவணத்தில் வேலை செய்து, நகல்களை மின்னஞ்சல் மூலம் முன்னும் பின்னுமாக அனுப்புவதைப் போன்றது. ஒவ்வொரு மாற்றத்திற்கும் ஒரு புதிய முழு நகலை அனுப்ப வேண்டும்.SharedArrayBuffer
உடன் வெப் வொர்க்கர்ஸ்: இது இரண்டு சக ஊழியர்கள் ஒரே ஆவணத்தில் ஒரு பகிரப்பட்ட ஆன்லைன் எடிட்டரில் (கூகிள் டாக்ஸ் போல) வேலை செய்வதைப் போன்றது. மாற்றங்கள் இருவருக்கும் நிகழ்நேரத்தில் தெரியும்.
பகிரப்பட்ட நினைவகத்தின் ஆபத்து: ரேஸ் கண்டிஷன்ஸ் (Race Conditions)
உடனடி நினைவகப் பகிர்வு சக்தி வாய்ந்தது, ஆனால் அது ஒரே நேர நிரலாக்க உலகிலிருந்து ஒரு கிளாசிக் சிக்கலையும் அறிமுகப்படுத்துகிறது: ரேஸ் கண்டிஷன்ஸ்.
ஒரு ரேஸ் கண்டிஷன் என்பது பல திரெட்கள் ஒரே பகிரப்பட்ட தரவை ஒரே நேரத்தில் அணுகி மாற்ற முயற்சிக்கும்போது ஏற்படுகிறது, மேலும் இறுதி முடிவு அவை இயங்கும் கணிக்க முடியாத வரிசையைப் பொறுத்தது. ஒரு SharedArrayBuffer
இல் சேமிக்கப்பட்ட ஒரு எளிய கவுண்டரைக் கவனியுங்கள். முதன்மைத் திரெட் மற்றும் ஒரு வொர்க்கர் இரண்டும் அதை அதிகரிக்க விரும்புகின்றன.
- திரெட் A தற்போதைய மதிப்பைப் படிக்கிறது, அது 5.
- திரெட் A புதிய மதிப்பை எழுதுவதற்கு முன், இயங்குதளம் அதை இடைநிறுத்தி திரெட் B க்கு மாறுகிறது.
- திரெட் B தற்போதைய மதிப்பைப் படிக்கிறது, அது இன்னும் 5.
- திரெட் B புதிய மதிப்பை (6) கணக்கிட்டு அதை நினைவகத்தில் மீண்டும் எழுதுகிறது.
- சிஸ்டம் மீண்டும் திரெட் A க்கு மாறுகிறது. திரெட் B எதையும் செய்ததாக அதற்குத் தெரியாது. அது விட்ட இடத்திலிருந்து மீண்டும் தொடங்கி, அதன் புதிய மதிப்பைக் கணக்கிட்டு (5 + 1 = 6) 6 ஐ நினைவகத்தில் மீண்டும் எழுதுகிறது.
கவுண்டர் இரண்டு முறை அதிகரிக்கப்பட்டாலும், இறுதி மதிப்பு 6, 7 அல்ல. செயல்பாடுகள் அணு (atomic) அல்ல—அவை குறுக்கிடக்கூடியவை, இது தரவு இழப்புக்கு வழிவகுத்தது. இதனால்தான் நீங்கள் ஒரு SharedArrayBuffer
ஐ அதன் முக்கிய கூட்டாளியான Atomics
ஆப்ஜெக்ட் இல்லாமல் பயன்படுத்த முடியாது.
பகிரப்பட்ட நினைவகத்தின் பாதுகாவலர்: Atomics
ஆப்ஜெக்ட்
Atomics
ஆப்ஜெக்ட், SharedArrayBuffer
ஆப்ஜெக்ட்களில் அணு செயல்பாடுகளைச் செய்வதற்கான ஒரு நிலையான முறைகளின் தொகுப்பை வழங்குகிறது. ஒரு அணு செயல்பாடு வேறு எந்த செயல்பாட்டாலும் குறுக்கிடப்படாமல் முழுமையாகச் செய்யப்படும் என்று உத்தரவாதம் அளிக்கப்படுகிறது. அது ஒன்று முழுமையாக நடக்கும் அல்லது hiç நடக்காது.
Atomics
ஐப் பயன்படுத்துவது பகிரப்பட்ட நினைவகத்தில் படி-மாற்று-எழுது செயல்பாடுகள் பாதுகாப்பாக செய்யப்படுவதை உறுதி செய்வதன் மூலம் ரேஸ் கண்டிஷன்ஸைத் தடுக்கிறது.
முக்கிய Atomics
முறைகள்
Atomics
வழங்கும் சில மிக முக்கியமான முறைகளைப் பார்ப்போம்.
Atomics.load(typedArray, index)
: ஒரு குறிப்பிட்ட குறியீட்டில் உள்ள மதிப்பை அணுரீதியாகப் படித்து அதைத் தருகிறது. இது நீங்கள் ஒரு முழுமையான, சிதைக்கப்படாத மதிப்பைப் படிக்கிறீர்கள் என்பதை உறுதி செய்கிறது.Atomics.store(typedArray, index, value)
: ஒரு குறிப்பிட்ட குறியீட்டில் ஒரு மதிப்பை அணுரீதியாகச் சேமித்து அந்த மதிப்பைத் தருகிறது. இது எழுதும் செயல்பாடு குறுக்கிடப்படவில்லை என்பதை உறுதி செய்கிறது.Atomics.add(typedArray, index, value)
: கொடுக்கப்பட்ட குறியீட்டில் உள்ள மதிப்புடன் ஒரு மதிப்பை அணுரீதியாகச் சேர்க்கிறது. இது அந்த நிலையில் உள்ள அசல் மதிப்பைத் தருகிறது. இதுx += value
என்பதன் அணு சமமானதாகும்.Atomics.sub(typedArray, index, value)
: கொடுக்கப்பட்ட குறியீட்டில் உள்ள மதிப்பிலிருந்து ஒரு மதிப்பைக் அணுரீதியாகக் கழிக்கிறது.Atomics.compareExchange(typedArray, index, expectedValue, replacementValue)
: இது ஒரு சக்திவாய்ந்த நிபந்தனை எழுதும் முறையாகும். இதுindex
இல் உள்ள மதிப்புexpectedValue
க்கு சமமாக உள்ளதா என சரிபார்க்கிறது. அப்படியானால், அதைreplacementValue
உடன் மாற்றி அசல்expectedValue
ஐத் தருகிறது. இல்லையெனில், அது எதையும் செய்யாது மற்றும் தற்போதைய மதிப்பைத் தருகிறது. இது பூட்டுகள் போன்ற சிக்கலான ஒத்திசைவு அடிப்படைகளைச் செயல்படுத்த ஒரு fondamentale கட்டிடத் தொகுதியாகும்.
ஒத்திசைவு: எளிய செயல்பாடுகளுக்கு அப்பால்
சில நேரங்களில் உங்களுக்கு பாதுகாப்பான வாசிப்பு மற்றும் எழுதுவதை விட அதிகம் தேவை. திரெட்கள் ஒருங்கிணைந்து ஒன்றுக்கொன்று காத்திருக்க வேண்டும். ஒரு பொதுவான எதிர்ப்பு-முறை "பிஸி-வெயிட்டிங்" (busy-waiting) ஆகும், இதில் ஒரு திரெட் ஒரு இறுக்கமான வளையத்தில் அமர்ந்து, ஒரு நினைவக இருப்பிடத்தை ஒரு மாற்றத்திற்காக தொடர்ந்து சரிபார்க்கிறது. இது CPU சுழற்சிகளை வீணாக்குகிறது மற்றும் பேட்டரி ஆயுளைக் குறைக்கிறது.
Atomics
wait()
மற்றும் notify()
உடன் மிகவும் திறமையான தீர்வை வழங்குகிறது.
Atomics.wait(typedArray, index, value, timeout)
: இது ஒரு திரெட்டை உறங்கச் சொல்கிறது. அதுindex
இல் உள்ள மதிப்பு இன்னும்value
தானா என்று சரிபார்க்கிறது. அப்படியானால், திரெட்Atomics.notify()
மூலம் எழுப்பப்படும் வரை அல்லது விருப்பத்தேர்வுtimeout
(மில்லி விநாடிகளில்) எட்டப்படும் வரை உறங்குகிறது.index
இல் உள்ள மதிப்பு ஏற்கனவே மாறிவிட்டால், அது உடனடியாகத் திரும்பும். இது நம்பமுடியாத அளவிற்கு திறமையானது, ஏனெனில் உறங்கும் திரெட் கிட்டத்தட்ட CPU வளங்களைப் பயன்படுத்துவதில்லை.Atomics.notify(typedArray, index, count)
: இதுAtomics.wait()
வழியாக ஒரு குறிப்பிட்ட நினைவக இருப்பிடத்தில் உறங்கும் திரெட்களை எழுப்பப் பயன்படுகிறது. இது அதிகபட்சம்count
காத்திருக்கும் திரெட்களை எழுப்பும் (அல்லதுcount
வழங்கப்படாவிட்டால் அல்லதுInfinity
ஆக இருந்தால் அனைத்தையும் எழுப்பும்).
அனைத்தையும் ஒன்றாக இணைத்தல்: ஒரு நடைமுறை வழிகாட்டி
இப்போது நாம் கோட்பாட்டைப் புரிந்து கொண்டோம், SharedArrayBuffer
ஐப் பயன்படுத்தி ஒரு தீர்வைச் செயல்படுத்தும் படிகளைப் பார்ப்போம்.
படி 1: பாதுகாப்பு முன்நிபந்தனை - கிராஸ்-ஆரிஜின் ஐசோலேஷன் (Cross-Origin Isolation)
இது டெவலப்பர்களுக்கான மிகவும் பொதுவான தடுமாற்றமாகும். பாதுகாப்பு காரணங்களுக்காக, SharedArrayBuffer
கிராஸ்-ஆரிஜின் ஐசோலேட்டட் (cross-origin isolated) நிலையில் உள்ள பக்கங்களில் மட்டுமே கிடைக்கிறது. இது ஸ்பெக்டர் போன்ற ஊகச் செயல்பாட்டு பாதிப்புகளைத் தணிக்க ஒரு பாதுகாப்பு நடவடிக்கையாகும், இது பகிரப்பட்ட நினைவகம் மூலம் சாத்தியமாகும் உயர்-தெளிவுத்திறன் டைமர்களைப் பயன்படுத்தி ஆரிஜின்களுக்கு இடையில் தரவைக் கசியச் செய்யக்கூடும்.
கிராஸ்-ஆரிஜின் ஐசோலேஷனை இயக்க, உங்கள் வலை சேவையகத்தை உங்கள் முக்கிய ஆவணத்திற்காக இரண்டு குறிப்பிட்ட HTTP ஹெடர்களை அனுப்ப உள்ளமைக்க வேண்டும்:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
(COOP): உங்கள் ஆவணத்தின் உலாவல் சூழலை மற்ற ஆவணங்களிலிருந்து தனிமைப்படுத்துகிறது, அவை உங்கள் சாளரப் பொருளுடன் நேரடியாகத் தொடர்புகொள்வதைத் தடுக்கிறது.Cross-Origin-Embedder-Policy: require-corp
(COEP): உங்கள் பக்கத்தால் ஏற்றப்பட்ட அனைத்து துணை வளங்களும் (படங்கள், ஸ்கிரிப்டுகள் மற்றும் iframeகள் போன்றவை) ஒரே ஆரிஜினிலிருந்து இருக்க வேண்டும் அல்லதுCross-Origin-Resource-Policy
ஹெடர் அல்லது CORS உடன் வெளிப்படையாக கிராஸ்-ஆரிஜின் ஏற்றக்கூடியதாகக் குறிக்கப்பட்டிருக்க வேண்டும்.
இதை அமைப்பது சவாலாக இருக்கலாம், குறிப்பாக நீங்கள் தேவையான ஹெடர்களை வழங்காத மூன்றாம் தரப்பு ஸ்கிரிப்டுகள் அல்லது வளங்களைச் சார்ந்திருந்தால். உங்கள் சேவையகத்தை உள்ளமைத்த பிறகு, உலாவியின் கன்சோலில் self.crossOriginIsolated
பண்பைச் சரிபார்த்து உங்கள் பக்கம் தனிமைப்படுத்தப்பட்டுள்ளதா என்பதை நீங்கள் சரிபார்க்கலாம். அது true
ஆக இருக்க வேண்டும்.
படி 2: இடையகத்தை உருவாக்குதல் மற்றும் பகிர்தல்
உங்கள் முக்கிய ஸ்கிரிப்டில், நீங்கள் SharedArrayBuffer
ஐயும், அதன் மீது Int32Array
போன்ற ஒரு TypedArray
ஐப் பயன்படுத்தி ஒரு "காட்சியையும்" உருவாக்குகிறீர்கள்.
main.js:
// முதலில் கிராஸ்-ஆரிஜின் ஐசோலேஷனைச் சரிபார்க்கவும்!
if (!self.crossOriginIsolated) {
console.error("இந்தப் பக்கம் கிராஸ்-ஆரிஜின் ஐசோலேட் செய்யப்படவில்லை. SharedArrayBuffer கிடைக்காது.");
} else {
// ஒரு 32-பிட் முழு எண்ணுக்கான பகிரப்பட்ட இடையகத்தை உருவாக்கவும்.
const buffer = new SharedArrayBuffer(4);
// இடையகத்தில் ஒரு காட்சியையும் உருவாக்கவும். அனைத்து அணு செயல்பாடுகளும் பார்வையில் நடக்கும்.
const int32Array = new Int32Array(buffer);
// குறியீடு 0 இல் மதிப்பைத் தொடங்கவும்.
int32Array[0] = 0;
// ஒரு புதிய வொர்க்கரை உருவாக்கவும்.
const worker = new Worker('worker.js');
// பகிரப்பட்ட இடையகத்தை வொர்க்கருக்கு அனுப்பவும். இது ஒரு குறிப்புப் பரிமாற்றம், நகல் அல்ல.
worker.postMessage({ buffer });
// வொர்க்கரிடமிருந்து வரும் செய்திகளைக் கேட்கவும்.
worker.onmessage = (event) => {
console.log(`வொர்க்கர் முடித்ததாக அறிவித்தது. இறுதி மதிப்பு: ${Atomics.load(int32Array, 0)}`);
};
}
படி 3: வொர்க்கரில் அணு செயல்பாடுகளைச் செய்தல்
வொர்க்கர் இடையகத்தைப் பெறுகிறது மற்றும் இப்போது அதில் அணு செயல்பாடுகளைச் செய்ய முடியும்.
worker.js:
self.onmessage = (event) => {
const { buffer } = event.data;
const int32Array = new Int32Array(buffer);
console.log("வொர்க்கர் பகிரப்பட்ட இடையகத்தைப் பெற்றது.");
// சில அணு செயல்பாடுகளைச் செய்வோம்.
for (let i = 0; i < 1000000; i++) {
// பகிரப்பட்ட மதிப்பை பாதுகாப்பாக அதிகரிக்கவும்.
Atomics.add(int32Array, 0, 1);
}
console.log("வொர்க்கர் அதிகரிப்பதை முடித்தது.");
// நாங்கள் முடித்துவிட்டோம் என்று முதன்மைத் திரெட்டுக்கு சமிக்ஞை செய்யவும்.
self.postMessage({ done: true });
};
படி 4: ஒரு மேம்பட்ட உதாரணம் - ஒத்திசைவுடன் இணை கூட்டல்
பல வொர்க்கர்களைப் பயன்படுத்தி ஒரு மிக நீண்ட எண்களின் வரிசையைக் கூட்டுவது போன்ற ஒரு யதார்த்தமான சிக்கலைச் சமாளிப்போம். திறமையான ஒத்திசைவுக்கு Atomics.wait()
மற்றும் Atomics.notify()
ஐப் பயன்படுத்துவோம்.
நமது பகிரப்பட்ட இடையகம் மூன்று பகுதிகளைக் கொண்டிருக்கும்:
- குறியீடு 0: ஒரு நிலைக் கொடி (0 = செயலாக்கத்தில், 1 = முடிந்தது).
- குறியீடு 1: எத்தனை வொர்க்கர்கள் முடித்துள்ளனர் என்பதற்கான ஒரு கவுண்டர்.
- குறியீடு 2: இறுதி கூட்டுத்தொகை.
main.js:
if (self.crossOriginIsolated) {
const NUM_WORKERS = 4;
const DATA_SIZE = 10_000_000;
// [நிலை, வொர்க்கர்கள்_முடிந்தது, முடிவு_குறைவு, முடிவு_அதிகம்]
// பெரிய கூட்டுத்தொகைகளுக்கு வழிதல் ஏற்படுவதைத் தவிர்க்க முடிவுக்கு இரண்டு 32-பிட் முழு எண்களைப் பயன்படுத்துகிறோம்.
const sharedBuffer = new SharedArrayBuffer(4 * 4); // 4 முழு எண்கள்
const sharedArray = new Int32Array(sharedBuffer);
// செயலாக்க சில சீரற்ற தரவை உருவாக்கவும்
const data = new Uint8Array(DATA_SIZE);
for (let i = 0; i < DATA_SIZE; i++) {
data[i] = Math.floor(Math.random() * 10);
}
const chunkSize = Math.ceil(DATA_SIZE / NUM_WORKERS);
for (let i = 0; i < NUM_WORKERS; i++) {
const worker = new Worker('sum_worker.js');
const start = i * chunkSize;
const end = Math.min(start + chunkSize, DATA_SIZE);
// வொர்க்கரின் தரவுத் துண்டிற்கான பகிரப்படாத பார்வையை உருவாக்கவும்
const dataChunk = data.subarray(start, end);
worker.postMessage({
sharedBuffer,
dataChunk // இது நகலெடுக்கப்படுகிறது
});
}
console.log('முதன்மைத் திரெட் இப்போது வொர்க்கர்கள் முடிப்பதற்காகக் காத்திருக்கிறது...');
// குறியீடு 0 இல் உள்ள நிலைக் கொடி 1 ஆக மாறும் வரை காத்திருக்கவும்
// இது ஒரு while loop ஐ விட மிகவும் சிறந்தது!
Atomics.wait(sharedArray, 0, 0); // sharedArray[0] 0 ஆக இருந்தால் காத்திருக்கவும்
console.log('முதன்மைத் திரெட் எழுப்பப்பட்டது!');
const finalSum = Atomics.load(sharedArray, 2);
console.log(`இறுதி இணை கூட்டுத்தொகை: ${finalSum}`);
} else {
console.error('பக்கம் கிராஸ்-ஆரிஜின் ஐசோலேட் செய்யப்படவில்லை.');
}
sum_worker.js:
self.onmessage = ({ data }) => {
const { sharedBuffer, dataChunk } = data;
const sharedArray = new Int32Array(sharedBuffer);
// இந்த வொர்க்கரின் துண்டிற்கான கூட்டுத்தொகையைக் கணக்கிடவும்
let localSum = 0;
for (let i = 0; i < dataChunk.length; i++) {
localSum += dataChunk[i];
}
// உள்ளூர் கூட்டுத்தொகையை பகிரப்பட்ட மொத்தத்துடன் அணுரீதியாகச் சேர்க்கவும்
Atomics.add(sharedArray, 2, localSum);
// 'வொர்க்கர்கள் முடித்த' கவுண்டரை அணுரீதியாக அதிகரிக்கவும்
const finishedCount = Atomics.add(sharedArray, 1, 1) + 1;
// இது முடிக்கும் கடைசி வொர்க்கர் என்றால்...
const NUM_WORKERS = 4; // ஒரு உண்மையான பயன்பாட்டில் இது அனுப்பப்பட வேண்டும்
if (finishedCount === NUM_WORKERS) {
console.log('கடைசி வொர்க்கர் முடிந்தது. முதன்மைத் திரெட்டுக்கு அறிவிக்கிறது.');
// 1. நிலைக் கொடியை 1 ஆக அமைக்கவும் (முடிந்தது)
Atomics.store(sharedArray, 0, 1);
// 2. குறியீடு 0 இல் காத்திருக்கும் முதன்மைத் திரெட்டுக்கு அறிவிக்கவும்
Atomics.notify(sharedArray, 0, 1);
}
};
நிஜ உலகப் பயன்பாட்டு வழக்குகள் மற்றும் பயன்பாடுகள்
இந்த சக்திவாய்ந்த ஆனால் சிக்கலான தொழில்நுட்பம் உண்மையில் எங்கே ஒரு வித்தியாசத்தை ஏற்படுத்துகிறது? பெரிய தரவுத்தொகுப்புகளில் கனமான, இணைக்கக்கூடிய கணக்கீடு தேவைப்படும் பயன்பாடுகளில் இது சிறந்து விளங்குகிறது.
- வெப்அசெம்பிளி (Wasm): இதுதான் முக்கிய பயன்பாட்டு வழக்கு. C++, Rust, மற்றும் Go போன்ற மொழிகள் மல்டித்ரெட்டிங்கிற்கு முதிர்ந்த ஆதரவைக் கொண்டுள்ளன. Wasm டெவலப்பர்கள் இந்த ஏற்கனவே உள்ள உயர்-செயல்திறன், மல்டி-த்ரெட்டட் பயன்பாடுகளை (கேம் என்ஜின்கள், CAD மென்பொருள் மற்றும் அறிவியல் மாதிரிகள் போன்றவை) உலாவியில் இயங்கத் தொகுக்க அனுமதிக்கிறது, திரெட் தகவல்தொடர்புக்கான அடிப்படை பொறிமுறையாக
SharedArrayBuffer
ஐப் பயன்படுத்துகிறது. - உலாவியில் தரவு செயலாக்கம்: பெரிய அளவிலான தரவு காட்சிப்படுத்தல், கிளையன்ட் பக்க இயந்திர கற்றல் மாதிரி அனுமானம், மற்றும் பாரிய அளவிலான தரவைச் செயலாக்கும் அறிவியல் உருவகப்படுத்துதல்கள் கணிசமாக துரிதப்படுத்தப்படலாம்.
- மீடியா எடிட்டிங்: உயர்-தெளிவுத்திறன் படங்களுக்கு வடிகட்டிகளைப் பயன்படுத்துவது அல்லது ஒரு ஒலி கோப்பில் ஆடியோ செயலாக்கத்தைச் செய்வது துண்டுகளாகப் பிரிக்கப்பட்டு பல வொர்க்கர்களால் இணையாகச் செயலாக்கப்படலாம், இது பயனருக்கு நிகழ்நேரக் கருத்தை வழங்குகிறது.
- உயர்-செயல்திறன் கேமிங்: நவீன கேம் என்ஜின்கள் இயற்பியல், AI, மற்றும் சொத்து ஏற்றுதலுக்கு மல்டித்ரெட்டிங்கை பெரிதும் நம்பியுள்ளன.
SharedArrayBuffer
உலாவியில் முழுமையாக இயங்கும் கன்சோல்-தரமான கேம்களை உருவாக்க உதவுகிறது.
சவால்கள் மற்றும் இறுதிப் பரிசீலனைகள்
SharedArrayBuffer
மாற்றத்தக்கதாக இருந்தாலும், அது ஒரு வெள்ளித் தோட்டா அல்ல. இது கவனமாகக் கையாள வேண்டிய ஒரு குறைந்த-நிலை கருவியாகும்.
- சிக்கலானது: ஒரே நேர நிரலாக்கம் notoirement கடினமானது. ரேஸ் கண்டிஷன்ஸ் மற்றும் டெட்லாக்குகளைப் பிழைதிருத்துவது நம்பமுடியாத அளவிற்கு சவாலாக இருக்கலாம். உங்கள் பயன்பாட்டு நிலை எவ்வாறு நிர்வகிக்கப்படுகிறது என்பதைப் பற்றி நீங்கள் வித்தியாசமாக சிந்திக்க வேண்டும்.
- டெட்லாக்குகள் (Deadlocks): இரண்டு அல்லது அதற்கு மேற்பட்ட திரெட்கள் என்றென்றும் தடுக்கப்படும்போது ஒரு டெட்லாக் ஏற்படுகிறது, ஒவ்வொன்றும் மற்றொன்று ஒரு வளத்தை விடுவிப்பதற்காகக் காத்திருக்கின்றன. நீங்கள் சிக்கலான பூட்டுதல் வழிமுறைகளைத் தவறாகச் செயல்படுத்தினால் இது நிகழலாம்.
- பாதுகாப்பு கூடுதல் சுமை: கிராஸ்-ஆரிஜின் ஐசோலேஷன் தேவை ஒரு குறிப்பிடத்தக்க தடையாகும். தேவையான CORS/CORP ஹெடர்களை அவர்கள் ஆதரிக்காவிட்டால், இது மூன்றாம் தரப்பு சேவைகள், விளம்பரங்கள் மற்றும் கட்டண நுழைவாயில்களுடனான ஒருங்கிணைப்புகளை உடைக்கக்கூடும்.
- ஒவ்வொரு பிரச்சனைக்கும் அல்ல: எளிய பின்னணிப் பணிகளுக்கு அல்லது I/O செயல்பாடுகளுக்கு,
postMessage()
உடன் பாரம்பரிய வெப் வொர்க்கர் மாதிரி பெரும்பாலும் எளிமையானதாகவும் போதுமானதாகவும் இருக்கும். பெரிய அளவிலான தரவை உள்ளடக்கிய தெளிவான, CPU-சார்ந்த தடை இருக்கும்போது மட்டுமேSharedArrayBuffer
ஐப் பயன்படுத்தவும்.
முடிவுரை
SharedArrayBuffer
, Atomics
மற்றும் வெப் வொர்க்கர்ஸுடன் இணைந்து, வலை மேம்பாட்டிற்கான ஒரு முன்னுதாரண மாற்றத்தைக் குறிக்கிறது. இது ஒற்றை-திரெட் மாதிரியின் எல்லைகளைத் தகர்த்து, ஒரு புதிய வகை சக்திவாய்ந்த, செயல்திறன்மிக்க, மற்றும் சிக்கலான பயன்பாடுகளை உலாவியில் அழைக்கிறது. இது கணக்கீட்டு-தீவிர பணிகளுக்காக வலைத் தளத்தை சொந்தப் பயன்பாட்டு மேம்பாட்டுடன் சமமான நிலையில் வைக்கிறது.
ஒரே நேர ஜாவாஸ்கிரிப்டിലേக்கான பயணம் சவாலானது, நிலை மேலாண்மை, ஒத்திசைவு மற்றும் பாதுகாப்பிற்கு ஒரு கடுமையான அணுகுமுறையைக் கோருகிறது. ஆனால் இணையத்தில் சாத்தியமானவற்றின் வரம்புகளைத் தள்ள விரும்பும் டெவலப்பர்களுக்கு—நிகழ்நேர ஆடியோ தொகுப்பிலிருந்து சிக்கலான 3D ரெண்டரிங் மற்றும் அறிவியல் கணினி வரை—SharedArrayBuffer
ஐ மாஸ்டர் செய்வது இனி ஒரு விருப்பம் மட்டுமல்ல; இது அடுத்த தலைமுறை வலைப் பயன்பாடுகளை உருவாக்குவதற்கான ஒரு அத்தியாவசியத் திறமையாகும்.