ಪ್ರಗತಿ ಲೇಬಲ್ನಲ್ಲಿ ಅಡಗಿದ್ದ ಔಟ್-ಆಫ್-ಮೆಮೊರಿ ಕ್ರ್ಯಾಶ್
ಸೆಪ್ಟೆಂಬರ್ ಕೊನೆಯಲ್ಲಿ ಒಂದು ಸಂಜೆ, ಬಳಕೆದಾರರ ವರ್ಕ್ಸ್ಪೇಸ್ನಲ್ಲಿರುವ AI ಏಜೆಂಟ್ ಒಂದು ತಿರುವಿನ ಮಧ್ಯದಲ್ಲಿ out-of-memory ದೋಷದೊಂದಿಗೆ ಕ್ರ್ಯಾಶ್ ಆಯಿತು. ಸ್ಪಷ್ಟ ಶಂಕಿತರು — ಹಲವು ಸಬ್-ಏಜೆಂಟ್ಗಳು ಏಕಕಾಲದಲ್ಲಿ ಚಲಿಸುವುದು, ಅಥವಾ ಸಂದರ್ಭ ತುಂಬಾ ದೊಡ್ಡದಾಗಿದ್ದು — ಇಬ್ಬರೂ ತಪ್ಪು. ನಿಜವಾದ ಕಾರಣ ಒಂದು ಸ್ಥಿತಿ ಲೇಬಲ್ ಆಗಿತ್ತು: ಮಾಡೆಲ್ ದೊಡ್ಡ ಶೆಲ್ ಕಮಾಂಡ್ ಅನ್ನು ಕೆಲವೇ ಅಕ್ಷರಗಳ ತುಣುಕುಗಳಲ್ಲಿ ಸ್ಟ್ರೀಮ್ ಮಾಡುತ್ತಿದ್ದಾಗ, ನಾವು ಪ್ರತಿ ತುಣುಕಿನಲ್ಲಿ ಇದುವರೆಗಿನ ಸಂಪೂರ್ಣ ಕಮಾಂಡ್ ಅನ್ನು ಪ್ರಗತಿ ಲೇಬಲ್ ಆಗಿ ಮತ್ತೆ ಕಳುಹಿಸುತ್ತಿದ್ದೆವು. ಒಂದು 124 KB ಕಮಾಂಡ್ ಸುಮಾರು 41,000 ಈವೆಂಟ್ಗಳು ಮತ್ತು ಸುಮಾರು 690 MB ಸರದಿಯಲ್ಲಿರುವ ಸ್ಟ್ರಿಂಗ್ಗಳಾಯಿತು.
ಏಜೆಂಟ್ ತನ್ನ ಕೆಲಸವನ್ನು ಹೇಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡುತ್ತದೆ
Mythex ನಲ್ಲಿ ನೀವು ನಿರ್ಮಿಸುವಾಗ, ಏಜೆಂಟ್ ನಿಮ್ಮ ಪ್ರಾಜೆಕ್ಟ್ನ ಖಾಸಗಿ ಕ್ಲೌಡ್ ಸ್ಯಾಂಡ್ಬಾಕ್ಸ್ನ ಒಳಗೆ ಚಲಿಸುತ್ತದೆ. ಮಾಡೆಲ್ ಬರೆಯುವಾಗ, ಅದರ ಔಟ್ಪುಟ್ ನಿಮ್ಮ ಬ್ರೌಸರ್ಗೆ ಸ್ಟ್ರೀಮ್ ಆಗುತ್ತದೆ: ಪಠ್ಯ ಪದ ಪದವಾಗಿ ಕಾಣಿಸುತ್ತದೆ, ಮತ್ತು ಅದು ಟೂಲ್ ಚಲಾಯಿಸಿದಾಗ — ಉದಾಹರಣೆಗೆ ಫೈಲ್ ಬರೆಯುವ ಶೆಲ್ ಕಮಾಂಡ್ — ಅದಕ್ಕಾಗಿ ಒಂದು ಲೇಬಲ್ ನೇರವಾಗಿ ಅಪ್ಡೇಟ್ ಆಗುತ್ತದೆ, ಆದ್ದರಿಂದ ಅದು ಏನು ಮಾಡುತ್ತಿದೆ ಎಂದು ನಿಮಗೆ ತಿಳಿಯುತ್ತದೆ.
ಮಾಡೆಲ್ ಸಣ್ಣ ತುಣುಕುಗಳಲ್ಲಿ ಸ್ಟ್ರೀಮ್ ಮಾಡುತ್ತದೆ. ನಾವು ಬಳಸುತ್ತಿದ್ದ ಮಾಡೆಲ್ನೊಂದಿಗೆ, ಆ ತುಣುಕುಗಳು ಹೆಚ್ಚಾಗಿ ಕೇವಲ ಮೂರು ಅಕ್ಷರ ಉದ್ದ ಇರುತ್ತಿದ್ದವು.
ಮೊದಲ ಊಹೆಗಳು ತಪ್ಪಾಗಿದ್ದವು
ಕ್ರ್ಯಾಶ್ ಸ್ಕೇಲಿಂಗ್ ಸಮಸ್ಯೆಯಂತೆ ಕಾಣುತ್ತಿತ್ತು, ಆದ್ದರಿಂದ ಅಲ್ಲಿಂದಲೇ ಆರಂಭಿಸಿದೆವು.
- ಸಮಾನಾಂತರ ಸಬ್-ಏಜೆಂಟ್ಗಳೇ? ತಿರುವಿನಲ್ಲಿ ಕೇವಲ ಎರಡು ಬಳಸಲ್ಪಟ್ಟಿದ್ದವು, ಪ್ರತಿಯೊಂದೂ ಸುಮಾರು 1.5 MB ಸ್ಥಿತಿ ಹಿಡಿದಿತ್ತು. ಅದು ಸಾಕಾಗದು.
- ಉಳಿಸಿಕೊಂಡ ಟ್ರೇಸ್ಗಳೇ? ನಮ್ಮ ಟ್ರೇಸಿಂಗ್ ರನ್ ಟ್ರೀ ಅನ್ನು ಮೆಮೊರಿಯಲ್ಲಿ ಇಟ್ಟುಕೊಂಡಿತ್ತು, ಆದರೆ ಕ್ರ್ಯಾಶ್ ಸಮಯದ ಹೀಪ್ ಗಾತ್ರಕ್ಕೆ ಅದು ಹತ್ತಿರವಿರಲಿಲ್ಲ.
ಎರಡೂ ಸಂಭವನೀಯ ಕಥೆಗಳಾಗಿದ್ದವು, ಮತ್ತು ಎರಡೂ ನಂಬಲು ಸುಲಭವಾಗಿದ್ದವು. ಯಾವುದೂ ವೈಫಲ್ಯವನ್ನು ಪುನರುತ್ಪಾದಿಸಲಿಲ್ಲ. ನಾವು ಪದೇ ಪದೇ ಕಲಿಯುತ್ತಿರುವ ಪಾಠ: ಒಂದು ಊಹೆ ಆ ವೈಫಲ್ಯವನ್ನು ಪುನರುತ್ಪಾದಿಸುವವರೆಗೆ ಅದು ಕಾರಣವಲ್ಲ.
ನಿಜವಾಗಿ ಪುನರುತ್ಪಾದಿಸುವುದು
ನಾವು ಉತ್ಪಾದನೆಯೊಂದಿಗೆ ಅದೇ ಮೆಮೊರಿ ಮಿತಿಗಳನ್ನು ಹೊಂದಿರುವ ಒಂದು ತಾತ್ಕಾಲಿಕ ಸ್ಯಾಂಡ್ಬಾಕ್ಸ್ ಅನ್ನು ನಿರ್ಮಿಸಿದೆವು, ಮತ್ತು ನೈಜ ತುಣುಕುಗಳಲ್ಲಿ ದೊಡ್ಡ ಫೈಲ್ ಅನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡುವ ನಕಲಿ ಮಾಡೆಲ್ ಅನ್ನು. ಸಾಕೆಟ್ನ ಮತ್ತೊಂದು ತುದಿಯಲ್ಲಿರುವ ಓದುಗ ನೈಜ ನೆಟ್ವರ್ಕ್ನಂತೆ ನಿಧಾನವಾಗಿರುವಂತೆ ಮಾಡಿದೆವು.
ಅದು ಕೆಲಸ ಮಾಡಿತು. ಹೀಪ್ ಏರಿತು ಮತ್ತು ಪ್ರಕ್ರಿಯೆ ಅದೇ ದೋಷದೊಂದಿಗೆ ಸತ್ತಿತು.
ಒಮ್ಮೆ ನಾವು ಅದನ್ನು ನೋಡಬಲ್ಲವಾದ ಮೇಲೆ ಯಾಂತ್ರಿಕತೆ ಸರಳವಾಗಿತ್ತು. ಮಾಡೆಲ್ ದೊಡ್ಡ ಕಮಾಂಡ್ ಬರೆಯುತ್ತಿದ್ದಾಗ — ಈ ಪ್ರಕರಣದಲ್ಲಿ 124 KB ಫೈಲ್ ಬರೆಯುವ heredoc — ನಮ್ಮ ಸ್ಟ್ರೀಮಿಂಗ್ ಕೋಡ್ ಪ್ರತಿ ತುಣುಕಿನಲ್ಲಿ ಟೂಲ್ನ ಲೇಬಲ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡುತ್ತಿತ್ತು. ಲೇಬಲ್ ಹೊಸ ಮೂರು ಅಕ್ಷರಗಳಲ್ಲ; ಅದು ಇದುವರೆಗಿನ ಸಂಪೂರ್ಣ ಕಮಾಂಡ್ ಆಗಿತ್ತು. ಆದ್ದರಿಂದ ಈವೆಂಟ್ಗಳು ಬೆಳೆದವು: 3 ಅಕ್ಷರ, ನಂತರ 6, ನಂತರ 9, … 124 KB ವರೆಗೆ, ಸುಮಾರು 41,000 ಬಾರಿ. ಸಾಕೆಟ್ ಅವು ಉತ್ಪಾದನೆಯಾದಷ್ಟು ವೇಗವಾಗಿ ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ, ಆದ್ದರಿಂದ ಅವು ಅದರ ರೈಟ್ ಬಫರ್ನಲ್ಲಿ ಸ್ಟ್ರಿಂಗ್ಗಳಾಗಿ ಸಂಗ್ರಹವಾದವು — ಸುಮಾರು 690 MB.
ಪರಿಹಾರ
- ಲೇಬಲ್ ಅನ್ನು ಮಿತಿಗೊಳಿಸಿ. ಸ್ಥಿತಿ ಲೇಬಲ್ ನಡೆಯುತ್ತಿರುವುದನ್ನು ಮಾತ್ರ ಹೇಳಬೇಕು. ಈಗ ಅದು 200 ಅಕ್ಷರಗಳಿಗೆ ಸೀಮಿತವಾಗಿದೆ, ಮತ್ತು ಭಾಗಶಃ ಕಮಾಂಡ್ ಅನ್ನು ಎಷ್ಟು ಬಾರಿ ಮರು-ಸ್ಕ್ಯಾನ್ ಮಾಡುತ್ತೇವೆ ಎಂಬುದನ್ನು ನಿಯಂತ್ರಿಸುತ್ತೇವೆ.
- ವರ್ಗ-ಆಧಾರಿತ ಸಂಯೋಜನೆಯನ್ನು ನಿಲ್ಲಿಸಿ. ಸ್ಟ್ರೀಮ್ ಮಾಡಿದ ತುಣುಕುಗಳನ್ನು ಪುನರಾವರ್ತಿತ ಸ್ಟ್ರಿಂಗ್ ಕಾನ್ಕ್ಯಾಟೆನೇಶನ್ನಿಂದ ಜೋಡಿಸುವುದು ದೊಡ್ಡ ಔಟ್ಪುಟ್ಗಳಿಗೆ O(n²). ರೇಖೀಯ ಸಮಯದಲ್ಲಿ ಸೇರಿಸುವ ಚಂಕ್-ಆಧಾರಿತ ವಿಧಾನಕ್ಕೆ ಬದಲಾಯಿಸಿದ್ದೇವೆ.
ನಂತರ ಪ್ರವಾಹದ ಔಟ್ಪುಟ್ನಲ್ಲಿ ಅನಿರ್ದಿಷ್ಟವಾಗಿ ಬೆಳೆಯಬಹುದಾದ ಬೇರೆ ಯಾವುದೇ ವಿಷಯಕ್ಕಾಗಿ ಹುಡುಕಿ, ಅದನ್ನು ಮಿತಿಗೊಳಿಸಿದೆವು:
- ಚಾಟ್ನಲ್ಲಿ ತೋರಿಸುವ ನೇರ ಕಮಾಂಡ್ ಔಟ್ಪುಟ್ ಬ್ಯಾಚ್ ಮಾಡಲಾಗಿದ್ದು ಕೊನೆಯ 8,000 ಅಕ್ಷರಗಳಿಗೆ ಸೀಮಿತವಾಗಿದೆ.
- ಪ್ರತ್ಯೇಕ ಈವೆಂಟ್ ಸಾಲುಗಳು 4 MB ಗೆ ಸೀಮಿತ.
- ಮರುಸಂಪರ್ಕದ ನಂತರ ಬ್ರೌಸರ್ ಹಿಡಿಯಲು ಬಳಸುವ ರೀಪ್ಲೇ ಬಫರ್ ಪ್ರತಿ ಪ್ರಾಜೆಕ್ಟ್ಗೆ 8 MB ಗೆ ಸೀಮಿತ.
- ಹಳೆಯ ಚೆಕ್ಪಾಯಿಂಟ್ಗಳನ್ನು ತಿರುವು ಮುಂದುವರಿದಂತೆ ಕತ್ತರಿಸಲಾಗುತ್ತದೆ, ಇತ್ತೀಚಿನ ಸ್ಥಿತಿ ಮತ್ತು ಹಿಂದಿನ ತಿರುವುಗಳಿಗೆ ಬೇಕಾದ ಆಂಕರ್ಗಳನ್ನು ಉಳಿಸಿಕೊಂಡು.
ಪ್ರವಾಹಗಳನ್ನು ಪ್ರಾಮಾಣಿಕವಾಗಿ ಪರೀಕ್ಷಿಸುವುದು
ಇದನ್ನು ಪರೀಕ್ಷಿಸುವುದು ಸರಿಯಾಗಿರುವುದಕ್ಕಿಂತ ಕಠಿಣವಾಗಿಸಿದ ಎರಡು ವಿಷಯಗಳು:
- ನೈಜ ಮಾಡೆಲ್ಗಳು ಸಹಕರಿಸುವುದಿಲ್ಲ. ಬೃಹತ್ ಫೈಲ್ ಮುದ್ರಿಸಲು ಮಾಡೆಲ್ಗೆ ಕೇಳಿದರೆ, ಅದು ಸಾಮಾನ್ಯವಾಗಿ ನಿರಾಕರಿಸುತ್ತದೆ, ಸಾರಾಂಶ ಮಾಡುತ್ತದೆ, ಅಥವಾ ಅದನ್ನು ಹೆಚ್ಚು ಸಮಂಜಸವಾಗಿ ಬರೆಯುತ್ತದೆ. ಪ್ರವಾಹಗಳನ್ನು ಪರೀಕ್ಷಿಸಲು, ನಿಮಗೆ ಹೇಳಿದ್ದನ್ನು ನಿಖರವಾಗಿ ಮಾಡುವ, ನೈಜ ಏಜೆಂಟ್ ಕೋಡ್ ಮೂಲಕ ಚಲಿಸುವ ಸ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಮಾಡೆಲ್ ಬೇಕು.
- ಸ್ಕ್ರಿಪ್ಟ್ಗಳು ಮಾಡೆಲ್ಗಳಂತೆ ವರ್ತಿಸಬೇಕು. ನಮ್ಮ ಮೊದಲ ಸ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಮಾಡೆಲ್ ಪ್ರತಿ ಉತ್ತರಕ್ಕೂ ಒಂದೇ ರೆಸ್ಪಾನ್ಸ್ ID ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡಿತು, ಆದ್ದರಿಂದ ಏಜೆಂಟ್ ಫ್ರೇಮ್ವರ್ಕ್ ಪ್ರತಿ ಉತ್ತರವನ್ನು ಹಿಂದಿನದರ ಬದಲಿ ಎಂದು ಪರಿಗಣಿಸಿ ತಿರುವುಗಳನ್ನು ಬೇಗನೆ ಕೊನೆಗೊಳಿಸಿತು. ಅದು UI ರಿಫ್ರೆಶ್ ದೋಷದಂತೆ ಕಂಡಿತು. ಅದು ಹಾಗಲ್ಲ — ಪರೀಕ್ಷಾ ಹಾರ್ನೆಸ್ ನಮಗೆ ಸುಳ್ಳು ಹೇಳುತ್ತಿತ್ತು. ನಾವು ಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ಮಾಡೆಲ್ನ ನೈಜ ಸಂದರ್ಭ ಮಿತಿಯನ್ನು ಜಾರಿಗೊಳಿಸಬೇಕಾಯಿತು, ಇಲ್ಲದಿದ್ದರೆ ಮೆಮೊರಿ ಸಂಖ್ಯೆಗಳು ವಾಸ್ತವಿಕವಾಗಿರಲಿಲ್ಲ.
ನಾವು ಕಲಿತದ್ದು
- ಸ್ಟ್ರೀಮಿಂಗ್ UI ಗಳು ಸಣ್ಣ ತಪ್ಪುಗಳನ್ನು ಗುಣಿಸುತ್ತವೆ. "ಪ್ರತಿ ತುಣುಕಿಗೆ" ಕಳುಹಿಸುವ ಯಾವುದಾದರೂ ಹತ್ತಾರು ಸಾವಿರ ಬಾರಿ ಕಳುಹಿಸಲ್ಪಡುತ್ತದೆ. ಡೆಲ್ಟಾಗಳನ್ನು ಕಳುಹಿಸಿ, ಅಥವಾ ಪೇಲೋಡ್ ಅನ್ನು ಮಿತಿಗೊಳಿಸಿ.
- ನಿಧಾನ ಗಡಿ ದಾಟುವ ಪ್ರತಿ ಬಫರ್ ಅನ್ನು ಮಿತಿಗೊಳಿಸಿ. ಸಾಕೆಟ್ಗಳು, ರೀಪ್ಲೇ ಲಾಗ್ಗಳು ಮತ್ತು ಚೆಕ್ಪಾಯಿಂಟ್ಗಳಿಗೆ ಎಲ್ಲಕ್ಕೂ ಮೇಲ್ಮಿತಿ ಬೇಕು.
- ಪುನರುತ್ಪಾದಿಸಿ, ನಂತರ ಸರಿಪಡಿಸಿ. ನಮ್ಮ ಮೊದಲ ಎರಡು ವಿವರಣೆಗಳು ಸರಿಯಾಗಿ ಕೇಳಿಸಿದವು ಆದರೆ ತಪ್ಪಾಗಿದ್ದವು.
ನೀವು ಇತ್ತೀಚೆಗೆ ಏಜೆಂಟ್ ನಿಂತುಹೋಗದೆ Mythex ಚಾಟ್ನಲ್ಲಿ ತುಂಬಾ ದೊಡ್ಡ ಫೈಲ್ ಕಾಣಿಸಿಕೊಂಡದ್ದನ್ನು ನೋಡಿದ್ದರೆ, ಇದು ಅದರ ಒಂದು ಕಾರಣ.