ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ನಿಜವಾದ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಅನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ. ಈ ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ SharedArrayBuffer, Atomics, ವೆಬ್ ವರ್ಕರ್ಗಳು, ಮತ್ತು ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗಾಗಿ ಭದ್ರತಾ ಅವಶ್ಯಕತೆಗಳನ್ನು ಒಳಗೊಂಡಿದೆ.
ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ SharedArrayBuffer: ವೆಬ್ನಲ್ಲಿ ಸಮಕಾಲೀನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ನ ಆಳವಾದ ನೋಟ
ದಶಕಗಳಿಂದ, ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನ ಸಿಂಗಲ್-ಥ್ರೆಡೆಡ್ ಸ್ವಭಾವವು ಅದರ ಸರಳತೆಗೆ ಮತ್ತು ಗಣನೀಯ ಕಾರ್ಯಕ್ಷಮತೆಯ ಅಡಚಣೆಗೆ ಕಾರಣವಾಗಿದೆ. ಈವೆಂಟ್ ಲೂಪ್ ಮಾದರಿಯು ಹೆಚ್ಚಿನ UI-ಚಾಲಿತ ಕಾರ್ಯಗಳಿಗೆ ಸುಂದರವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ, ಆದರೆ ಗಣನಾತ್ಮಕವಾಗಿ ತೀವ್ರವಾದ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಎದುರಿಸಿದಾಗ ಅದು ಹೆಣಗಾಡುತ್ತದೆ. ದೀರ್ಘಕಾಲದ ಲೆಕ್ಕಾಚಾರಗಳು ಬ್ರೌಸರ್ ಅನ್ನು ಫ್ರೀಜ್ ಮಾಡಬಹುದು, ಇದು ಬಳಕೆದಾರರಿಗೆ ನಿರಾಶಾದಾಯಕ ಅನುಭವವನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ. ವೆಬ್ ವರ್ಕರ್ಗಳು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಸ್ಕ್ರಿಪ್ಟ್ಗಳನ್ನು ಚಲಾಯಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುವ ಮೂಲಕ ಭಾಗಶಃ ಪರಿಹಾರವನ್ನು ನೀಡಿದರೂ, ಅವುಗಳು ತಮ್ಮದೇ ಆದ ಪ್ರಮುಖ ಮಿತಿಯೊಂದಿಗೆ ಬಂದವು: ಅಸಮರ್ಥ ಡೇಟಾ ಸಂವಹನ.
ಇದಕ್ಕೆ ಪರಿಹಾರವಾಗಿ ಬಂದಿದ್ದೇ SharedArrayBuffer
(SAB), ಇದು ವೆಬ್ನಲ್ಲಿ ಥ್ರೆಡ್ಗಳ ನಡುವೆ ನಿಜವಾದ, ಕೆಳಮಟ್ಟದ ಮೆಮೊರಿ ಹಂಚಿಕೆಯನ್ನು ಪರಿಚಯಿಸುವ ಮೂಲಕ ಆಟವನ್ನೇ ಮೂಲಭೂತವಾಗಿ ಬದಲಾಯಿಸುವ ಒಂದು ಶಕ್ತಿಶಾಲಿ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. Atomics
ಆಬ್ಜೆಕ್ಟ್ನೊಂದಿಗೆ ಜೋಡಿಯಾಗಿ, SAB ನೇರವಾಗಿ ಬ್ರೌಸರ್ನಲ್ಲಿ ಉನ್ನತ-ಕಾರ್ಯಕ್ಷಮತೆಯ, ಸಮಕಾಲೀನ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಹೊಸ ಯುಗವನ್ನು ತೆರೆಯುತ್ತದೆ. ಆದಾಗ್ಯೂ, ಹೆಚ್ಚಿನ ಶಕ್ತಿಯೊಂದಿಗೆ ಹೆಚ್ಚಿನ ಜವಾಬ್ದಾರಿ ಮತ್ತು ಸಂಕೀರ್ಣತೆಯೂ ಬರುತ್ತದೆ.
ಈ ಮಾರ್ಗದರ್ಶಿ ನಿಮ್ಮನ್ನು ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ಸಮಕಾಲೀನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ ಜಗತ್ತಿನಲ್ಲಿ ಆಳವಾಗಿ ಕೊಂಡೊಯ್ಯುತ್ತದೆ. ನಮಗೆ ಇದು ಏಕೆ ಬೇಕು, SharedArrayBuffer
ಮತ್ತು Atomics
ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ, ನೀವು ಪರಿಹರಿಸಬೇಕಾದ ನಿರ್ಣಾಯಕ ಭದ್ರತಾ ಪರಿಗಣನೆಗಳು ಮತ್ತು ಪ್ರಾರಂಭಿಸಲು ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳನ್ನು ನಾವು ಅನ್ವೇಷಿಸುತ್ತೇವೆ.
ಹಳೆಯ ಜಗತ್ತು: ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನ ಸಿಂಗಲ್-ಥ್ರೆಡೆಡ್ ಮಾದರಿ ಮತ್ತು ಅದರ ಮಿತಿಗಳು
ನಾವು ಪರಿಹಾರವನ್ನು ಶ್ಲಾಘಿಸುವ ಮೊದಲು, ನಾವು ಸಮಸ್ಯೆಯನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಅರ್ಥಮಾಡಿಕೊಳ್ಳಬೇಕು. ಬ್ರೌಸರ್ನಲ್ಲಿ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಎಕ್ಸಿಕ್ಯೂಶನ್ ಸಾಂಪ್ರದಾಯಿಕವಾಗಿ ಒಂದೇ ಥ್ರೆಡ್ನಲ್ಲಿ ನಡೆಯುತ್ತದೆ, ಇದನ್ನು ಸಾಮಾನ್ಯವಾಗಿ "ಮುಖ್ಯ ಥ್ರೆಡ್" ಅಥವಾ "UI ಥ್ರೆಡ್" ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ.
ಈವೆಂಟ್ ಲೂಪ್
ಮುಖ್ಯ ಥ್ರೆಡ್ ಎಲ್ಲದಕ್ಕೂ ಜವಾಬ್ದಾರವಾಗಿದೆ: ನಿಮ್ಮ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಕೋಡ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವುದು, ಪುಟವನ್ನು ರೆಂಡರಿಂಗ್ ಮಾಡುವುದು, ಬಳಕೆದಾರರ ಸಂವಹನಗಳಿಗೆ (ಕ್ಲಿಕ್ಗಳು ಮತ್ತು ಸ್ಕ್ರಾಲ್ಗಳಂತಹ) ಪ್ರತಿಕ್ರಿಯಿಸುವುದು, ಮತ್ತು CSS ಅನಿಮೇಷನ್ಗಳನ್ನು ಚಲಾಯಿಸುವುದು. ಇದು ಈವೆಂಟ್ ಲೂಪ್ ಬಳಸಿ ಈ ಕಾರ್ಯಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ, ಇದು ನಿರಂತರವಾಗಿ ಸಂದೇಶಗಳ (ಕಾರ್ಯಗಳ) ಸರದಿಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುತ್ತದೆ. ಒಂದು ಕಾರ್ಯವು ಪೂರ್ಣಗೊಳ್ಳಲು ಹೆಚ್ಚು ಸಮಯ ತೆಗೆದುಕೊಂಡರೆ, ಅದು ಇಡೀ ಸರದಿಯನ್ನು ನಿರ್ಬಂಧಿಸುತ್ತದೆ. ಬೇರೇನೂ ಆಗಲು ಸಾಧ್ಯವಿಲ್ಲ - UI ಫ್ರೀಜ್ ಆಗುತ್ತದೆ, ಅನಿಮೇಷನ್ಗಳು ತೊದಲುತ್ತವೆ, ಮತ್ತು ಪುಟವು ಪ್ರತಿಕ್ರಿಯಿಸುವುದಿಲ್ಲ.
ವೆಬ್ ವರ್ಕರ್ಗಳು: ಸರಿಯಾದ ದಿಕ್ಕಿನಲ್ಲಿ ಒಂದು ಹೆಜ್ಜೆ
ಈ ಸಮಸ್ಯೆಯನ್ನು ತಗ್ಗಿಸಲು ವೆಬ್ ವರ್ಕರ್ಗಳನ್ನು ಪರಿಚಯಿಸಲಾಯಿತು. ವೆಬ್ ವರ್ಕರ್ ಎನ್ನುವುದು ಮೂಲಭೂತವಾಗಿ ಪ್ರತ್ಯೇಕ ಹಿನ್ನೆಲೆ ಥ್ರೆಡ್ನಲ್ಲಿ ಚಾಲನೆಯಲ್ಲಿರುವ ಸ್ಕ್ರಿಪ್ಟ್ ಆಗಿದೆ. ನೀವು ಭಾರೀ ಗಣನೆಗಳನ್ನು ವರ್ಕರ್ಗೆ ಆಫ್ಲೋಡ್ ಮಾಡಬಹುದು, ಮುಖ್ಯ ಥ್ರೆಡ್ ಅನ್ನು ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ನಿರ್ವಹಿಸಲು ಮುಕ್ತವಾಗಿರಿಸಬಹುದು.
ಮುಖ್ಯ ಥ್ರೆಡ್ ಮತ್ತು ವರ್ಕರ್ ನಡುವಿನ ಸಂವಹನವು postMessage()
API ಮೂಲಕ ನಡೆಯುತ್ತದೆ. ನೀವು ಡೇಟಾವನ್ನು ಕಳುಹಿಸಿದಾಗ, ಅದನ್ನು ರಚನಾತ್ಮಕ ಕ್ಲೋನ್ ಅಲ್ಗಾರಿದಮ್ (structured clone algorithm) ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ. ಇದರರ್ಥ ಡೇಟಾವನ್ನು ಸೀರಿಯಲೈಸ್ ಮಾಡಿ, ನಕಲಿಸಿ, ತದನಂತರ ವರ್ಕರ್ನ ಸಂದರ್ಭದಲ್ಲಿ ಡಿಸೀರಿಯಲೈಸ್ ಮಾಡಲಾಗುತ್ತದೆ. ಇದು ಪರಿಣಾಮಕಾರಿಯಾಗಿದ್ದರೂ, ಈ ಪ್ರಕ್ರಿಯೆಯು ದೊಡ್ಡ ಡೇಟಾಸೆಟ್ಗಳಿಗೆ ಗಮನಾರ್ಹ ಅನಾನುಕೂಲಗಳನ್ನು ಹೊಂದಿದೆ:
- ಕಾರ್ಯಕ್ಷಮತೆಯ ಓವರ್ಹೆಡ್: ಥ್ರೆಡ್ಗಳ ನಡುವೆ ಮೆಗಾಬೈಟ್ಗಳು ಅಥವಾ ಗಿಗಾಬೈಟ್ಗಳಷ್ಟು ಡೇಟಾವನ್ನು ನಕಲಿಸುವುದು ನಿಧಾನ ಮತ್ತು CPU-ತೀವ್ರವಾಗಿರುತ್ತದೆ.
- ಮೆಮೊರಿ ಬಳಕೆ: ಇದು ಮೆಮೊರಿಯಲ್ಲಿ ಡೇಟಾದ ನಕಲನ್ನು ರಚಿಸುತ್ತದೆ, ಇದು ಮೆಮೊರಿ-ನಿರ್ಬಂಧಿತ ಸಾಧನಗಳಿಗೆ ಒಂದು ಪ್ರಮುಖ ಸಮಸ್ಯೆಯಾಗಬಹುದು.
ಬ್ರೌಸರ್ನಲ್ಲಿನ ವೀಡಿಯೊ ಎಡಿಟರ್ ಅನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಿ. ಸಂಪೂರ್ಣ ವೀಡಿಯೊ ಫ್ರೇಮ್ ಅನ್ನು (ಇದು ಹಲವಾರು ಮೆಗಾಬೈಟ್ಗಳಿರಬಹುದು) ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸೆಕೆಂಡಿಗೆ 60 ಬಾರಿ ವರ್ಕರ್ಗೆ ಹಿಂದಕ್ಕೆ ಮತ್ತು ಮುಂದಕ್ಕೆ ಕಳುಹಿಸುವುದು ನಿಷೇಧಾತ್ಮಕವಾಗಿ ದುಬಾರಿಯಾಗುತ್ತದೆ. `SharedArrayBuffer` ಅನ್ನು ಈ ನಿಖರವಾದ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ.
ಆಟವನ್ನೇ ಬದಲಾಯಿಸಿದ್ದು: SharedArrayBuffer
ನ ಪರಿಚಯ
ಒಂದು SharedArrayBuffer
ಎನ್ನುವುದು 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` ಆಬ್ಜೆಕ್ಟ್ಗಳ ಮೇಲೆ ಅಟಾಮಿಕ್ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಸ್ಥಿರ ವಿಧಾನಗಳ ಒಂದು ಗುಂಪನ್ನು ಒದಗಿಸುತ್ತದೆ. ಒಂದು ಅಟಾಮಿಕ್ ಕಾರ್ಯಾಚರಣೆಯು ಯಾವುದೇ ಇತರ ಕಾರ್ಯಾಚರಣೆಯಿಂದ ಅಡ್ಡಿಪಡಿಸದೆ ಸಂಪೂರ್ಣವಾಗಿ ನಿರ್ವಹಿಸಲ್ಪಡುತ್ತದೆ ಎಂದು ಖಾತರಿಪಡಿಸಲಾಗಿದೆ. ಅದು ಸಂಪೂರ್ಣವಾಗಿ ಸಂಭವಿಸುತ್ತದೆ ಅಥವಾ ಇಲ್ಲವೇ ಇಲ್ಲ.
`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
ಅನ್ನು ಹಿಂದಿರುಗಿಸುತ್ತದೆ. ಇಲ್ಲದಿದ್ದರೆ, ಅದು ಏನನ್ನೂ ಮಾಡುವುದಿಲ್ಲ ಮತ್ತು ಪ್ರಸ್ತುತ ಮೌಲ್ಯವನ್ನು ಹಿಂದಿರುಗಿಸುತ್ತದೆ. ಲಾಕ್ಗಳಂತಹ ಹೆಚ್ಚು ಸಂಕೀರ್ಣ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪ್ರಿಮಿಟಿವ್ಗಳನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಇದೊಂದು ಮೂಲಭೂತ ಬಿಲ್ಡಿಂಗ್ ಬ್ಲಾಕ್ ಆಗಿದೆ.
ಸಿಂಕ್ರೊನೈಸೇಶನ್: ಸರಳ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಮೀರಿ
ಕೆಲವೊಮ್ಮೆ ನಿಮಗೆ ಸುರಕ್ಷಿತ ಓದುವಿಕೆ ಮತ್ತು ಬರೆಯುವಿಕೆಗಿಂತ ಹೆಚ್ಚಿನದು ಬೇಕಾಗುತ್ತದೆ. ಥ್ರೆಡ್ಗಳು ಪರಸ್ಪರ ಸಮನ್ವಯ ಸಾಧಿಸಲು ಮತ್ತು ಕಾಯಲು ನಿಮಗೆ ಬೇಕಾಗುತ್ತದೆ. ಒಂದು ಸಾಮಾನ್ಯ ಆಂಟಿ-ಪ್ಯಾಟರ್ನ್ "ಬ್ಯುಸಿ-ವೇಯ್ಟಿಂಗ್" ಆಗಿದೆ, ಇದರಲ್ಲಿ ಒಂದು ಥ್ರೆಡ್ ಒಂದು ಬಿಗಿಯಾದ ಲೂಪ್ನಲ್ಲಿ ಕುಳಿತು, ಬದಲಾವಣೆಗಾಗಿ ಮೆಮೊರಿ ಸ್ಥಳವನ್ನು ನಿರಂತರವಾಗಿ ಪರಿಶೀಲಿಸುತ್ತದೆ. ಇದು 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: ಭದ್ರತಾ ಪೂರ್ವಾಪೇಕ್ಷಿತ - ಕ್ರಾಸ್-ಒರಿಜಿನ್ ಐಸೋಲೇಶನ್
ಇದು ಡೆವಲಪರ್ಗಳಿಗೆ ಅತ್ಯಂತ ಸಾಮಾನ್ಯವಾದ ಅಡಚಣೆಯಾಗಿದೆ. ಭದ್ರತಾ ಕಾರಣಗಳಿಗಾಗಿ, `SharedArrayBuffer` ಕೇವಲ ಕ್ರಾಸ್-ಒರಿಜಿನ್ ಐಸೋಲೇಟೆಡ್ ಸ್ಥಿತಿಯಲ್ಲಿರುವ ಪುಟಗಳಲ್ಲಿ ಮಾತ್ರ ಲಭ್ಯವಿದೆ. ಇದು ಸ್ಪೆಕ್ಟರ್ನಂತಹ ಸ್ಪೆಕ್ಯುಲೇಟಿವ್ ಎಕ್ಸಿಕ್ಯೂಶನ್ ದುರ್ಬಲತೆಗಳನ್ನು ತಗ್ಗಿಸಲು ಒಂದು ಭದ್ರತಾ ಕ್ರಮವಾಗಿದೆ, ಇದು ಸಂಭಾವ್ಯವಾಗಿ ಹಂಚಿದ ಮೆಮೊರಿಯಿಂದ ಸಾಧ್ಯವಾಗುವ ಹೈ-ರೆಸಲ್ಯೂಶನ್ ಟೈಮರ್ಗಳನ್ನು ಬಳಸಿ ಮೂಲಗಳಾದ್ಯಂತ ಡೇಟಾವನ್ನು ಸೋರಿಕೆ ಮಾಡಬಹುದು.
ಕ್ರಾಸ್-ಒರಿಜಿನ್ ಐಸೋಲೇಶನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು, ನಿಮ್ಮ ಮುಖ್ಯ ಡಾಕ್ಯುಮೆಂಟ್ಗಾಗಿ ಎರಡು ನಿರ್ದಿಷ್ಟ 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): ನಿಮ್ಮ ಪುಟದಿಂದ ಲೋಡ್ ಮಾಡಲಾದ ಎಲ್ಲಾ ಉಪ-ಸಂಪನ್ಮೂಲಗಳು (ಚಿತ್ರಗಳು, ಸ್ಕ್ರಿಪ್ಟ್ಗಳು, ಮತ್ತು ಐಫ್ರೇಮ್ಗಳಂತಹ) ಒಂದೇ ಮೂಲದಿಂದ ಇರಬೇಕು ಅಥವಾ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');
// ಹಂಚಿದ (SHARED) ಬಫರ್ ಅನ್ನು ವರ್ಕರ್ಗೆ ಕಳುಹಿಸಿ. ಇದು ಉಲ್ಲೇಖ ವರ್ಗಾವಣೆಯೇ ಹೊರತು ನಕಲು ಅಲ್ಲ.
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 ಆಗುವವರೆಗೆ ಕಾಯಿರಿ
// ಇದು ವೈಲ್ ಲೂಪ್ಗಿಂತ ಹೆಚ್ಚು ಉತ್ತಮವಾಗಿದೆ!
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` ಪರಿವರ್ತಕವಾಗಿದ್ದರೂ, ಇದು ಸರ್ವರೋಗ ನಿವಾರಕವಲ್ಲ. ಇದು ಎಚ್ಚರಿಕೆಯಿಂದ ನಿರ್ವಹಿಸಬೇಕಾದ ಕೆಳಮಟ್ಟದ ಸಾಧನವಾಗಿದೆ.
- ಸಂಕೀರ್ಣತೆ: ಸಮಕಾಲೀನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ ಕುಖ್ಯಾತವಾಗಿ ಕಷ್ಟಕರವಾಗಿದೆ. ರೇಸ್ ಕಂಡೀಷನ್ಸ್ ಮತ್ತು ಡೆಡ್ಲಾಕ್ಗಳನ್ನು ಡೀಬಗ್ ಮಾಡುವುದು ನಂಬಲಾಗದಷ್ಟು ಸವಾಲಾಗಿರಬಹುದು. ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಿತಿಯನ್ನು ಹೇಗೆ ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ನೀವು ವಿಭಿನ್ನವಾಗಿ ಯೋಚಿಸಬೇಕು.
- ಡೆಡ್ಲಾಕ್ಗಳು: ಡೆಡ್ಲಾಕ್ ಎಂದರೆ ಎರಡು ಅಥವಾ ಹೆಚ್ಚು ಥ್ರೆಡ್ಗಳು ಶಾಶ್ವತವಾಗಿ ನಿರ್ಬಂಧಿಸಲ್ಪಟ್ಟಾಗ ಸಂಭವಿಸುತ್ತದೆ, ಪ್ರತಿಯೊಂದೂ ಇನ್ನೊಂದು ಸಂಪನ್ಮೂಲವನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲು ಕಾಯುತ್ತಿರುತ್ತದೆ. ನೀವು ಸಂಕೀರ್ಣ ಲಾಕಿಂಗ್ ಕಾರ್ಯವಿಧಾನಗಳನ್ನು ತಪ್ಪಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸಿದರೆ ಇದು ಸಂಭವಿಸಬಹುದು.
- ಭದ್ರತಾ ಓವರ್ಹೆಡ್: ಕ್ರಾಸ್-ಒರಿಜಿನ್ ಐಸೋಲೇಶನ್ ಅವಶ್ಯಕತೆಯು ಒಂದು ಗಮನಾರ್ಹ ಅಡಚಣೆಯಾಗಿದೆ. ಮೂರನೇ-ಪಕ್ಷದ ಸೇವೆಗಳು, ಜಾಹೀರಾತುಗಳು, ಮತ್ತು ಪಾವತಿ ಗೇಟ್ವೇಗಳು ಅಗತ್ಯವಾದ CORS/CORP ಹೆಡರ್ಗಳನ್ನು ಬೆಂಬಲಿಸದಿದ್ದರೆ ಅವುಗಳೊಂದಿಗಿನ ಏಕೀಕರಣವನ್ನು ಇದು ಮುರಿಯಬಹುದು.
- ಪ್ರತಿ ಸಮಸ್ಯೆಗೆ ಅಲ್ಲ: ಸರಳ ಹಿನ್ನೆಲೆ ಕಾರ್ಯಗಳು ಅಥವಾ I/O ಕಾರ್ಯಾಚರಣೆಗಳಿಗಾಗಿ, `postMessage()` ನೊಂದಿಗೆ ಸಾಂಪ್ರದಾಯಿಕ ವೆಬ್ ವರ್ಕರ್ ಮಾದರಿಯು ಸಾಮಾನ್ಯವಾಗಿ ಸರಳ ಮತ್ತು ಸಾಕಾಗುತ್ತದೆ. ನೀವು ದೊಡ್ಡ ಪ್ರಮಾಣದ ಡೇಟಾವನ್ನು ಒಳಗೊಂಡ ಸ್ಪಷ್ಟವಾದ, CPU-ಬೌಂಡ್ ಅಡಚಣೆಯನ್ನು ಹೊಂದಿರುವಾಗ ಮಾತ್ರ `SharedArrayBuffer` ಅನ್ನು ಬಳಸಿ.
ತೀರ್ಮಾನ
`SharedArrayBuffer`, `Atomics` ಮತ್ತು ವೆಬ್ ವರ್ಕರ್ಗಳ ಜೊತೆಯಲ್ಲಿ, ವೆಬ್ ಅಭಿವೃದ್ಧಿಗೆ ಒಂದು ಮಾದರಿ ಬದಲಾವಣೆಯನ್ನು ಪ್ರತಿನಿಧಿಸುತ್ತದೆ. ಇದು ಸಿಂಗಲ್-ಥ್ರೆಡೆಡ್ ಮಾದರಿಯ ಗಡಿಗಳನ್ನು ಒಡೆಯುತ್ತದೆ, ಹೊಸ ವರ್ಗದ ಶಕ್ತಿಯುತ, ಕಾರ್ಯಕ್ಷಮತೆಯ, ಮತ್ತು ಸಂಕೀರ್ಣ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬ್ರೌಸರ್ಗೆ ಆಹ್ವಾನಿಸುತ್ತದೆ. ಇದು ವೆಬ್ ಪ್ಲಾಟ್ಫಾರ್ಮ್ ಅನ್ನು ಗಣನಾತ್ಮಕವಾಗಿ ತೀವ್ರವಾದ ಕಾರ್ಯಗಳಿಗಾಗಿ ನೇಟಿವ್ ಅಪ್ಲಿಕೇಶನ್ ಅಭಿವೃದ್ಧಿಯೊಂದಿಗೆ ಹೆಚ್ಚು ಸಮಾನವಾದ ನೆಲೆಯಲ್ಲಿ ಇರಿಸುತ್ತದೆ.
ಸಮಕಾಲೀನ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನ ಪ್ರಯಾಣವು ಸವಾಲಿನದ್ದಾಗಿದೆ, ಇದು ಸ್ಥಿತಿ ನಿರ್ವಹಣೆ, ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಮತ್ತು ಭದ್ರತೆಗೆ ಕಠಿಣವಾದ ವಿಧಾನವನ್ನು ಬಯಸುತ್ತದೆ. ಆದರೆ ವೆಬ್ನಲ್ಲಿ ಸಾಧ್ಯವಿರುವುದರ ಮಿತಿಗಳನ್ನು ತಳ್ಳಲು ನೋಡುತ್ತಿರುವ ಡೆವಲಪರ್ಗಳಿಗೆ - ನೈಜ-ಸಮಯದ ಆಡಿಯೊ ಸಂಶ್ಲೇಷಣೆಯಿಂದ ಸಂಕೀರ್ಣ 3D ರೆಂಡರಿಂಗ್ ಮತ್ತು ವೈಜ್ಞಾನಿಕ ಕಂಪ್ಯೂಟಿಂಗ್ವರೆಗೆ - `SharedArrayBuffer` ಅನ್ನು ಕರಗತ ಮಾಡಿಕೊಳ್ಳುವುದು ಇನ್ನು ಮುಂದೆ ಕೇವಲ ಒಂದು ಆಯ್ಕೆಯಲ್ಲ; ಇದು ಮುಂದಿನ ಪೀಳಿಗೆಯ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ನಿರ್ಮಿಸಲು ಅತ್ಯಗತ್ಯ ಕೌಶಲ್ಯವಾಗಿದೆ.