eBPF/BCC ಬಳಸಿಕೊಂಡು ಹೆಚ್ಚಿನ Ceph ಲೇಟೆನ್ಸಿಯಿಂದ ಕರ್ನಲ್ ಪ್ಯಾಚ್‌ಗೆ

eBPF/BCC ಬಳಸಿಕೊಂಡು ಹೆಚ್ಚಿನ Ceph ಲೇಟೆನ್ಸಿಯಿಂದ ಕರ್ನಲ್ ಪ್ಯಾಚ್‌ಗೆ

Linux ಕರ್ನಲ್ ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಡೀಬಗ್ ಮಾಡಲು ಹೆಚ್ಚಿನ ಸಂಖ್ಯೆಯ ಸಾಧನಗಳನ್ನು ಹೊಂದಿದೆ. ಅವುಗಳಲ್ಲಿ ಹೆಚ್ಚಿನವು ಅಪ್ಲಿಕೇಶನ್ ಕಾರ್ಯಕ್ಷಮತೆಯ ಮೇಲೆ ನಕಾರಾತ್ಮಕ ಪರಿಣಾಮ ಬೀರುತ್ತವೆ ಮತ್ತು ಉತ್ಪಾದನೆಯಲ್ಲಿ ಬಳಸಲಾಗುವುದಿಲ್ಲ.

ಒಂದೆರಡು ವರ್ಷಗಳ ಹಿಂದೆ ಇತ್ತು ಮತ್ತೊಂದು ಉಪಕರಣವನ್ನು ಅಭಿವೃದ್ಧಿಪಡಿಸಲಾಗಿದೆ - ಇಬಿಪಿಎಫ್. ಕರ್ನಲ್ ಮತ್ತು ಬಳಕೆದಾರರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಕಡಿಮೆ ಓವರ್‌ಹೆಡ್‌ನೊಂದಿಗೆ ಮತ್ತು ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಮರುನಿರ್ಮಾಣ ಮಾಡುವ ಅಗತ್ಯವಿಲ್ಲದೆ ಮತ್ತು ಕರ್ನಲ್‌ಗೆ ಮೂರನೇ ವ್ಯಕ್ತಿಯ ಮಾಡ್ಯೂಲ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಇದು ಸಾಧ್ಯವಾಗಿಸುತ್ತದೆ.

eBPF ಅನ್ನು ಬಳಸುವ ಅನೇಕ ಅಪ್ಲಿಕೇಶನ್ ಉಪಯುಕ್ತತೆಗಳು ಈಗಾಗಲೇ ಇವೆ, ಮತ್ತು ಈ ಲೇಖನದಲ್ಲಿ ನಾವು ಲೈಬ್ರರಿಯ ಆಧಾರದ ಮೇಲೆ ನಿಮ್ಮ ಸ್ವಂತ ಪ್ರೊಫೈಲಿಂಗ್ ಉಪಯುಕ್ತತೆಯನ್ನು ಹೇಗೆ ಬರೆಯಬೇಕೆಂದು ನೋಡೋಣ. ಪೈಥಾನ್BCC. ಲೇಖನವು ನೈಜ ಘಟನೆಗಳನ್ನು ಆಧರಿಸಿದೆ. ನಿರ್ದಿಷ್ಟ ಸಂದರ್ಭಗಳಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಉಪಯುಕ್ತತೆಗಳನ್ನು ಹೇಗೆ ಬಳಸಬಹುದು ಎಂಬುದನ್ನು ತೋರಿಸಲು ನಾವು ಸಮಸ್ಯೆಯಿಂದ ಸರಿಪಡಿಸಲು ಹೋಗುತ್ತೇವೆ.

ಸೆಫ್ ನಿಧಾನ

Ceph ಕ್ಲಸ್ಟರ್‌ಗೆ ಹೊಸ ಹೋಸ್ಟ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ. ಕೆಲವು ಡೇಟಾವನ್ನು ಅದಕ್ಕೆ ಸ್ಥಳಾಂತರಿಸಿದ ನಂತರ, ಅದರ ಮೂಲಕ ಬರೆಯುವ ವಿನಂತಿಗಳನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವ ವೇಗವು ಇತರ ಸರ್ವರ್‌ಗಳಿಗಿಂತ ಕಡಿಮೆಯಾಗಿದೆ ಎಂದು ನಾವು ಗಮನಿಸಿದ್ದೇವೆ.

eBPF/BCC ಬಳಸಿಕೊಂಡು ಹೆಚ್ಚಿನ Ceph ಲೇಟೆನ್ಸಿಯಿಂದ ಕರ್ನಲ್ ಪ್ಯಾಚ್‌ಗೆ
ಇತರ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ಗಳಿಗಿಂತ ಭಿನ್ನವಾಗಿ, ಈ ಹೋಸ್ಟ್ bcache ಮತ್ತು ಹೊಸ ಲಿನಕ್ಸ್ 4.15 ಕರ್ನಲ್ ಅನ್ನು ಬಳಸಿದೆ. ಈ ಕಾನ್ಫಿಗರೇಶನ್‌ನ ಹೋಸ್ಟ್ ಅನ್ನು ಇಲ್ಲಿ ಬಳಸಿರುವುದು ಇದೇ ಮೊದಲು. ಮತ್ತು ಆ ಕ್ಷಣದಲ್ಲಿ ಸಮಸ್ಯೆಯ ಮೂಲವು ಸೈದ್ಧಾಂತಿಕವಾಗಿ ಯಾವುದಾದರೂ ಆಗಿರಬಹುದು ಎಂದು ಸ್ಪಷ್ಟವಾಯಿತು.

ಹೋಸ್ಟ್ ಅನ್ನು ತನಿಖೆ ಮಾಡಲಾಗುತ್ತಿದೆ

ceph-osd ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ ಏನಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ನೋಡುವ ಮೂಲಕ ಪ್ರಾರಂಭಿಸೋಣ. ಇದಕ್ಕಾಗಿ ನಾವು ಬಳಸುತ್ತೇವೆ ಪರಿಪೂರ್ಣ и ಫ್ಲೇಮ್ಸ್ಕೋಪ್ (ಇದರ ಬಗ್ಗೆ ನೀವು ಹೆಚ್ಚು ಓದಬಹುದು ಇಲ್ಲಿ):

eBPF/BCC ಬಳಸಿಕೊಂಡು ಹೆಚ್ಚಿನ Ceph ಲೇಟೆನ್ಸಿಯಿಂದ ಕರ್ನಲ್ ಪ್ಯಾಚ್‌ಗೆ
ಚಿತ್ರವು ಕಾರ್ಯವನ್ನು ನಮಗೆ ಹೇಳುತ್ತದೆ fdatasync() ಕಾರ್ಯಗಳಿಗೆ ವಿನಂತಿಯನ್ನು ಕಳುಹಿಸಲು ಸಾಕಷ್ಟು ಸಮಯವನ್ನು ಕಳೆದರು generic_make_request(). ಇದರರ್ಥ ಸಮಸ್ಯೆಗಳ ಕಾರಣವು osd ಡೀಮನ್‌ನ ಹೊರಗೆ ಎಲ್ಲೋ ಇರುತ್ತದೆ. ಇದು ಕರ್ನಲ್ ಅಥವಾ ಡಿಸ್ಕ್ ಆಗಿರಬಹುದು. iostat ಔಟ್‌ಪುಟ್ bcache ಡಿಸ್ಕ್‌ಗಳಿಂದ ವಿನಂತಿಗಳನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವಲ್ಲಿ ಹೆಚ್ಚಿನ ಸುಪ್ತತೆಯನ್ನು ತೋರಿಸಿದೆ.

ಹೋಸ್ಟ್ ಅನ್ನು ಪರಿಶೀಲಿಸುವಾಗ, systemd-udevd ಡೀಮನ್ ಹೆಚ್ಚಿನ ಪ್ರಮಾಣದ CPU ಸಮಯವನ್ನು ಬಳಸುತ್ತದೆ ಎಂದು ನಾವು ಕಂಡುಕೊಂಡಿದ್ದೇವೆ - ಹಲವಾರು ಕೋರ್‌ಗಳಲ್ಲಿ ಸುಮಾರು 20%. ಇದು ವಿಚಿತ್ರ ವರ್ತನೆ, ಆದ್ದರಿಂದ ನೀವು ಏಕೆ ಕಂಡುಹಿಡಿಯಬೇಕು. Systemd-udevd ಯುವೆಂಟ್‌ಗಳೊಂದಿಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದರಿಂದ, ನಾವು ಅವುಗಳನ್ನು ನೋಡಲು ನಿರ್ಧರಿಸಿದ್ದೇವೆ udevadm ಮಾನಿಟರ್. ವ್ಯವಸ್ಥೆಯಲ್ಲಿನ ಪ್ರತಿ ಬ್ಲಾಕ್ ಸಾಧನಕ್ಕಾಗಿ ಹೆಚ್ಚಿನ ಸಂಖ್ಯೆಯ ಬದಲಾವಣೆಯ ಘಟನೆಗಳನ್ನು ರಚಿಸಲಾಗಿದೆ ಎಂದು ಅದು ತಿರುಗುತ್ತದೆ. ಇದು ತುಂಬಾ ಅಸಾಮಾನ್ಯವಾಗಿದೆ, ಆದ್ದರಿಂದ ಈ ಎಲ್ಲಾ ಘಟನೆಗಳನ್ನು ಏನು ಸೃಷ್ಟಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ನಾವು ನೋಡಬೇಕಾಗಿದೆ.

BCC ಟೂಲ್ಕಿಟ್ ಅನ್ನು ಬಳಸುವುದು

ನಾವು ಈಗಾಗಲೇ ಕಂಡುಕೊಂಡಂತೆ, ಕರ್ನಲ್ (ಮತ್ತು ಸಿಸ್ಟಮ್ ಕರೆಯಲ್ಲಿನ ಸೆಫ್ ಡೀಮನ್) ಬಹಳಷ್ಟು ಸಮಯವನ್ನು ಕಳೆಯುತ್ತದೆ generic_make_request(). ಈ ಕಾರ್ಯದ ವೇಗವನ್ನು ಅಳೆಯಲು ಪ್ರಯತ್ನಿಸೋಣ. IN ಬಿಸಿಸಿ ಈಗಾಗಲೇ ಅದ್ಭುತವಾದ ಉಪಯುಕ್ತತೆ ಇದೆ - ಕಾರ್ಯಸಾಧ್ಯತೆ. ಔಟ್‌ಪುಟ್‌ಗಳ ನಡುವಿನ 1 ಸೆಕೆಂಡ್ ಮಧ್ಯಂತರದೊಂದಿಗೆ ನಾವು ಡೀಮನ್ ಅನ್ನು ಅದರ PID ಮೂಲಕ ಪತ್ತೆಹಚ್ಚುತ್ತೇವೆ ಮತ್ತು ಫಲಿತಾಂಶವನ್ನು ಮಿಲಿಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಔಟ್‌ಪುಟ್ ಮಾಡುತ್ತೇವೆ.

eBPF/BCC ಬಳಸಿಕೊಂಡು ಹೆಚ್ಚಿನ Ceph ಲೇಟೆನ್ಸಿಯಿಂದ ಕರ್ನಲ್ ಪ್ಯಾಚ್‌ಗೆ
ಈ ವೈಶಿಷ್ಟ್ಯವು ಸಾಮಾನ್ಯವಾಗಿ ತ್ವರಿತವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಡಿವೈಸ್ ಡ್ರೈವರ್ ಕ್ಯೂಗೆ ವಿನಂತಿಯನ್ನು ರವಾನಿಸುವುದು ಮಾತ್ರ ಅದು ಮಾಡುತ್ತದೆ.

Bcache ವಾಸ್ತವವಾಗಿ ಮೂರು ಡಿಸ್ಕ್ಗಳನ್ನು ಒಳಗೊಂಡಿರುವ ಒಂದು ಸಂಕೀರ್ಣ ಸಾಧನವಾಗಿದೆ:

  • ಬ್ಯಾಕಿಂಗ್ ಸಾಧನ (ಕ್ಯಾಶ್ಡ್ ಡಿಸ್ಕ್), ಈ ಸಂದರ್ಭದಲ್ಲಿ ಇದು ನಿಧಾನವಾದ HDD ಆಗಿದೆ;
  • ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವ ಸಾಧನ (ಕ್ಯಾಶಿಂಗ್ ಡಿಸ್ಕ್), ಇಲ್ಲಿ ಇದು NVMe ಸಾಧನದ ಒಂದು ವಿಭಾಗವಾಗಿದೆ;
  • ಅಪ್ಲಿಕೇಶನ್ ರನ್ ಆಗುವ bcache ವರ್ಚುವಲ್ ಸಾಧನ.

ವಿನಂತಿಯ ಪ್ರಸರಣವು ನಿಧಾನವಾಗಿದೆ ಎಂದು ನಮಗೆ ತಿಳಿದಿದೆ, ಆದರೆ ಈ ಸಾಧನಗಳಲ್ಲಿ ಯಾವುದಕ್ಕಾಗಿ? ನಾವು ಇದನ್ನು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ವ್ಯವಹರಿಸುತ್ತೇವೆ.

ಈವೆಂಟ್‌ಗಳು ಸಮಸ್ಯೆಗಳನ್ನು ಉಂಟುಮಾಡುವ ಸಾಧ್ಯತೆಯಿದೆ ಎಂದು ನಮಗೆ ಈಗ ತಿಳಿದಿದೆ. ಅವರ ಪೀಳಿಗೆಗೆ ನಿಖರವಾಗಿ ಕಾರಣವೇನು ಎಂಬುದನ್ನು ಕಂಡುಹಿಡಿಯುವುದು ಅಷ್ಟು ಸುಲಭವಲ್ಲ. ಇದು ನಿಯತಕಾಲಿಕವಾಗಿ ಪ್ರಾರಂಭವಾಗುವ ಕೆಲವು ರೀತಿಯ ಸಾಫ್ಟ್‌ವೇರ್ ಎಂದು ಭಾವಿಸೋಣ. ಸ್ಕ್ರಿಪ್ಟ್ ಬಳಸಿ ಸಿಸ್ಟಮ್‌ನಲ್ಲಿ ಯಾವ ರೀತಿಯ ಸಾಫ್ಟ್‌ವೇರ್ ರನ್ ಆಗುತ್ತದೆ ಎಂದು ನೋಡೋಣ execsnoop ಅದೇ ನಿಂದ BCC ಯುಟಿಲಿಟಿ ಕಿಟ್. ಅದನ್ನು ರನ್ ಮಾಡೋಣ ಮತ್ತು ಔಟ್‌ಪುಟ್ ಅನ್ನು ಫೈಲ್‌ಗೆ ಕಳುಹಿಸೋಣ.

ಉದಾಹರಣೆಗೆ ಈ ರೀತಿ:

/usr/share/bcc/tools/execsnoop  | tee ./execdump

ನಾವು ಇಲ್ಲಿ execsnoop ನ ಸಂಪೂರ್ಣ ಔಟ್‌ಪುಟ್ ಅನ್ನು ತೋರಿಸುವುದಿಲ್ಲ, ಆದರೆ ನಮಗೆ ಆಸಕ್ತಿಯ ಒಂದು ಸಾಲು ಈ ರೀತಿ ಕಾಣುತ್ತದೆ:

sh 1764905 5802 0 sudo arcconf getconfig 1 AD | grep Temperature | awk -F '[:/]' '{print $2}' | sed 's/^ ([0-9]*) C.*/1/'

ಮೂರನೇ ಕಾಲಮ್ ಪ್ರಕ್ರಿಯೆಯ PPID (ಪೋಷಕ PID) ಆಗಿದೆ. PID 5802 ರೊಂದಿಗಿನ ಪ್ರಕ್ರಿಯೆಯು ನಮ್ಮ ಮೇಲ್ವಿಚಾರಣಾ ವ್ಯವಸ್ಥೆಯ ಥ್ರೆಡ್‌ಗಳಲ್ಲಿ ಒಂದಾಗಿದೆ. ಮಾನಿಟರಿಂಗ್ ಸಿಸ್ಟಮ್ನ ಸಂರಚನೆಯನ್ನು ಪರಿಶೀಲಿಸುವಾಗ, ತಪ್ಪಾದ ನಿಯತಾಂಕಗಳು ಕಂಡುಬಂದಿವೆ. HBA ಅಡಾಪ್ಟರ್ನ ತಾಪಮಾನವನ್ನು ಪ್ರತಿ 30 ಸೆಕೆಂಡುಗಳಿಗೆ ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತದೆ, ಇದು ಅಗತ್ಯಕ್ಕಿಂತ ಹೆಚ್ಚು ಬಾರಿ. ಚೆಕ್ ಮಧ್ಯಂತರವನ್ನು ದೀರ್ಘಾವಧಿಗೆ ಬದಲಾಯಿಸಿದ ನಂತರ, ಇತರ ಹೋಸ್ಟ್‌ಗಳಿಗೆ ಹೋಲಿಸಿದರೆ ಈ ಹೋಸ್ಟ್‌ನಲ್ಲಿ ವಿನಂತಿ ಪ್ರಕ್ರಿಯೆಯ ಲೇಟೆನ್ಸಿ ಇನ್ನು ಮುಂದೆ ಎದ್ದು ಕಾಣುವುದಿಲ್ಲ ಎಂದು ನಾವು ಕಂಡುಕೊಂಡಿದ್ದೇವೆ.

ಆದರೆ bcache ಸಾಧನವು ಏಕೆ ನಿಧಾನವಾಗಿದೆ ಎಂಬುದು ಇನ್ನೂ ಸ್ಪಷ್ಟವಾಗಿಲ್ಲ. ನಾವು ಒಂದೇ ರೀತಿಯ ಕಾನ್ಫಿಗರೇಶನ್‌ನೊಂದಿಗೆ ಪರೀಕ್ಷಾ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್ ಅನ್ನು ಸಿದ್ಧಪಡಿಸಿದ್ದೇವೆ ಮತ್ತು bcache ನಲ್ಲಿ fio ರನ್ ಮಾಡುವ ಮೂಲಕ ಸಮಸ್ಯೆಯನ್ನು ಪುನರುತ್ಪಾದಿಸಲು ಪ್ರಯತ್ನಿಸಿದ್ದೇವೆ, ಯೂವೆಂಟ್‌ಗಳನ್ನು ಉತ್ಪಾದಿಸಲು udevadm ಟ್ರಿಗ್ಗರ್ ಅನ್ನು ನಿಯತಕಾಲಿಕವಾಗಿ ಚಾಲನೆ ಮಾಡುತ್ತಿದ್ದೇವೆ.

BCC-ಆಧಾರಿತ ಪರಿಕರಗಳನ್ನು ಬರೆಯುವುದು

ನಿಧಾನವಾದ ಕರೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಮತ್ತು ಪ್ರದರ್ಶಿಸಲು ಸರಳವಾದ ಉಪಯುಕ್ತತೆಯನ್ನು ಬರೆಯಲು ಪ್ರಯತ್ನಿಸೋಣ generic_make_request(). ಈ ಕಾರ್ಯವನ್ನು ಕರೆಯಲಾದ ಡ್ರೈವ್‌ನ ಹೆಸರಿನಲ್ಲಿ ನಾವು ಆಸಕ್ತಿ ಹೊಂದಿದ್ದೇವೆ.

ಯೋಜನೆ ಸರಳವಾಗಿದೆ:

  • ನೋಂದಣಿ kprobe ಮೇಲೆ generic_make_request():
    • ನಾವು ಡಿಸ್ಕ್ ಹೆಸರನ್ನು ಮೆಮೊರಿಗೆ ಉಳಿಸುತ್ತೇವೆ, ಫಂಕ್ಷನ್ ಆರ್ಗ್ಯುಮೆಂಟ್ ಮೂಲಕ ಪ್ರವೇಶಿಸಬಹುದು;
    • ನಾವು ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್ ಅನ್ನು ಉಳಿಸುತ್ತೇವೆ.

  • ನೋಂದಣಿ kretprobe ನಿಂದ ಹಿಂತಿರುಗಲು generic_make_request():
    • ನಾವು ಪ್ರಸ್ತುತ ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್ ಅನ್ನು ಪಡೆಯುತ್ತೇವೆ;
    • ನಾವು ಉಳಿಸಿದ ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್‌ಗಾಗಿ ನೋಡುತ್ತೇವೆ ಮತ್ತು ಅದನ್ನು ಪ್ರಸ್ತುತದ ಜೊತೆಗೆ ಹೋಲಿಕೆ ಮಾಡುತ್ತೇವೆ;
    • ಫಲಿತಾಂಶವು ನಿರ್ದಿಷ್ಟಪಡಿಸಿದ ಒಂದಕ್ಕಿಂತ ಹೆಚ್ಚಿದ್ದರೆ, ನಾವು ಉಳಿಸಿದ ಡಿಸ್ಕ್ ಹೆಸರನ್ನು ಕಂಡುಹಿಡಿಯುತ್ತೇವೆ ಮತ್ತು ಅದನ್ನು ಟರ್ಮಿನಲ್ನಲ್ಲಿ ಪ್ರದರ್ಶಿಸುತ್ತೇವೆ.

Kprobes и kretprobes ಫ್ಲೈನಲ್ಲಿ ಫಂಕ್ಷನ್ ಕೋಡ್ ಅನ್ನು ಬದಲಾಯಿಸಲು ಬ್ರೇಕ್ಪಾಯಿಂಟ್ ಕಾರ್ಯವಿಧಾನವನ್ನು ಬಳಸಿ. ನೀವು ಓದಬಹುದು ದಸ್ತಾವೇಜನ್ನು и ಒಳ್ಳೆಯದು ಈ ವಿಷಯದ ಬಗ್ಗೆ ಲೇಖನ. ನೀವು ವಿವಿಧ ಉಪಯುಕ್ತತೆಗಳ ಕೋಡ್ ಅನ್ನು ನೋಡಿದರೆ ಬಿಸಿಸಿ, ನಂತರ ಅವರು ಒಂದೇ ರೀತಿಯ ರಚನೆಯನ್ನು ಹೊಂದಿದ್ದಾರೆ ಎಂದು ನೀವು ನೋಡಬಹುದು. ಆದ್ದರಿಂದ ಈ ಲೇಖನದಲ್ಲಿ ನಾವು ಪಾರ್ಸಿಂಗ್ ಸ್ಕ್ರಿಪ್ಟ್ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಬಿಟ್ಟುಬಿಡುತ್ತೇವೆ ಮತ್ತು BPF ಪ್ರೋಗ್ರಾಂಗೆ ಹೋಗುತ್ತೇವೆ.

ಪೈಥಾನ್ ಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿರುವ eBPF ಪಠ್ಯವು ಈ ರೀತಿ ಕಾಣುತ್ತದೆ:

bpf_text = “”” # Here will be the bpf program code “””

ಕಾರ್ಯಗಳ ನಡುವೆ ಡೇಟಾವನ್ನು ವಿನಿಮಯ ಮಾಡಲು, eBPF ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಬಳಸುತ್ತದೆ ಹ್ಯಾಶ್ ಕೋಷ್ಟಕಗಳು. ನಾವೂ ಹಾಗೆಯೇ ಮಾಡುತ್ತೇವೆ. ನಾವು ಪ್ರಕ್ರಿಯೆ PID ಅನ್ನು ಕೀಲಿಯಾಗಿ ಬಳಸುತ್ತೇವೆ ಮತ್ತು ರಚನೆಯನ್ನು ಮೌಲ್ಯವಾಗಿ ವ್ಯಾಖ್ಯಾನಿಸುತ್ತೇವೆ:

struct data_t {
	u64 pid;
	u64 ts;
	char comm[TASK_COMM_LEN];
	u64 lat;
	char disk[DISK_NAME_LEN];
};

BPF_HASH(p, u64, struct data_t);
BPF_PERF_OUTPUT(events);

ಇಲ್ಲಿ ನಾವು ಎಂಬ ಹ್ಯಾಶ್ ಟೇಬಲ್ ಅನ್ನು ನೋಂದಾಯಿಸುತ್ತೇವೆ p, ಕೀ ಪ್ರಕಾರದೊಂದಿಗೆ U64 ಮತ್ತು ಪ್ರಕಾರದ ಮೌಲ್ಯ struct data_t. ನಮ್ಮ BPF ಕಾರ್ಯಕ್ರಮದ ಸಂದರ್ಭದಲ್ಲಿ ಟೇಬಲ್ ಲಭ್ಯವಿರುತ್ತದೆ. BPF_PERF_OUTPUT ಮ್ಯಾಕ್ರೋ ಮತ್ತೊಂದು ಟೇಬಲ್ ಅನ್ನು ನೋಂದಾಯಿಸುತ್ತದೆ ಘಟನೆಗಳು, ಇದನ್ನು ಬಳಸಲಾಗುತ್ತದೆ ಡೇಟಾ ಪ್ರಸರಣ ಬಳಕೆದಾರ ಜಾಗಕ್ಕೆ.

ಕಾರ್ಯವನ್ನು ಕರೆಯುವ ಮತ್ತು ಅದರಿಂದ ಹಿಂತಿರುಗುವ ನಡುವಿನ ವಿಳಂಬವನ್ನು ಅಳೆಯುವಾಗ ಅಥವಾ ವಿಭಿನ್ನ ಕಾರ್ಯಗಳಿಗೆ ಕರೆಗಳ ನಡುವೆ, ಸ್ವೀಕರಿಸಿದ ಡೇಟಾವು ಒಂದೇ ಸಂದರ್ಭಕ್ಕೆ ಸೇರಿರಬೇಕು ಎಂದು ನೀವು ಗಣನೆಗೆ ತೆಗೆದುಕೊಳ್ಳಬೇಕಾಗುತ್ತದೆ. ಬೇರೆ ರೀತಿಯಲ್ಲಿ ಹೇಳುವುದಾದರೆ, ಕಾರ್ಯಗಳ ಸಂಭವನೀಯ ಸಮಾನಾಂತರ ಉಡಾವಣೆಯ ಬಗ್ಗೆ ನೀವು ನೆನಪಿಟ್ಟುಕೊಳ್ಳಬೇಕು. ಒಂದು ಪ್ರಕ್ರಿಯೆಯ ಸಂದರ್ಭದಲ್ಲಿ ಕಾರ್ಯವನ್ನು ಕರೆಯುವ ಮತ್ತು ಇನ್ನೊಂದು ಪ್ರಕ್ರಿಯೆಯ ಸಂದರ್ಭದಲ್ಲಿ ಆ ಕಾರ್ಯದಿಂದ ಹಿಂತಿರುಗುವ ನಡುವಿನ ಸುಪ್ತತೆಯನ್ನು ಅಳೆಯುವ ಸಾಮರ್ಥ್ಯವನ್ನು ನಾವು ಹೊಂದಿದ್ದೇವೆ, ಆದರೆ ಇದು ನಿಷ್ಪ್ರಯೋಜಕವಾಗಿದೆ. ಇಲ್ಲಿ ಉತ್ತಮ ಉದಾಹರಣೆಯಾಗಿರುತ್ತದೆ ಜೈವಿಕತೆ ಉಪಯುಕ್ತತೆ, ಅಲ್ಲಿ ಹ್ಯಾಶ್ ಟೇಬಲ್ ಕೀಯನ್ನು ಪಾಯಿಂಟರ್‌ಗೆ ಹೊಂದಿಸಲಾಗಿದೆ ರಚನಾತ್ಮಕ ವಿನಂತಿ, ಇದು ಒಂದು ಡಿಸ್ಕ್ ವಿನಂತಿಯನ್ನು ಪ್ರತಿಬಿಂಬಿಸುತ್ತದೆ.

ಮುಂದೆ, ಅಧ್ಯಯನದ ಅಡಿಯಲ್ಲಿ ಕಾರ್ಯವನ್ನು ಕರೆಯುವಾಗ ರನ್ ಆಗುವ ಕೋಡ್ ಅನ್ನು ನಾವು ಬರೆಯಬೇಕಾಗಿದೆ:

void start(struct pt_regs *ctx, struct bio *bio) {
	u64 pid = bpf_get_current_pid_tgid();
	struct data_t data = {};
	u64 ts = bpf_ktime_get_ns();
	data.pid = pid;
	data.ts = ts;
	bpf_probe_read_str(&data.disk, sizeof(data.disk), (void*)bio->bi_disk->disk_name);
	p.update(&pid, &data);
}

ಇಲ್ಲಿ ಕರೆಯಲಾದ ಫಂಕ್ಷನ್‌ನ ಮೊದಲ ಆರ್ಗ್ಯುಮೆಂಟ್ ಅನ್ನು ಎರಡನೇ ಆರ್ಗ್ಯುಮೆಂಟ್ ಆಗಿ ಬದಲಾಯಿಸಲಾಗುತ್ತದೆ generic_make_request(). ಇದರ ನಂತರ, ನಾವು ಕೆಲಸ ಮಾಡುತ್ತಿರುವ ಸಂದರ್ಭದಲ್ಲಿ ನಾವು ಪ್ರಕ್ರಿಯೆಯ PID ಅನ್ನು ಪಡೆಯುತ್ತೇವೆ ಮತ್ತು ನ್ಯಾನೊಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪ್ರಸ್ತುತ ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್ ಅನ್ನು ಪಡೆಯುತ್ತೇವೆ. ನಾವು ಎಲ್ಲವನ್ನೂ ಹೊಸದಾಗಿ ಆಯ್ಕೆಮಾಡಿದ ಪತ್ರದಲ್ಲಿ ಬರೆಯುತ್ತೇವೆ ಡೇಟಾ_ಟಿ ಡೇಟಾ ರಚನೆ. ರಚನೆಯಿಂದ ನಾವು ಡಿಸ್ಕ್ ಹೆಸರನ್ನು ಪಡೆಯುತ್ತೇವೆ ಜೈವಿಕ, ಕರೆ ಮಾಡುವಾಗ ರವಾನಿಸಲಾಗಿದೆ generic_make_request(), ಮತ್ತು ಅದನ್ನು ಅದೇ ರಚನೆಯಲ್ಲಿ ಉಳಿಸಿ ಡೇಟಾ. ಹಿಂದೆ ಉಲ್ಲೇಖಿಸಲಾದ ಹ್ಯಾಶ್ ಟೇಬಲ್‌ಗೆ ನಮೂದನ್ನು ಸೇರಿಸುವುದು ಕೊನೆಯ ಹಂತವಾಗಿದೆ.

ನಿಂದ ಹಿಂತಿರುಗಿದ ನಂತರ ಕೆಳಗಿನ ಕಾರ್ಯವನ್ನು ಕರೆಯಲಾಗುವುದು generic_make_request():

void stop(struct pt_regs *ctx) {
    u64 pid = bpf_get_current_pid_tgid();
    u64 ts = bpf_ktime_get_ns();
    struct data_t* data = p.lookup(&pid);
    if (data != 0 && data->ts > 0) {
        bpf_get_current_comm(&data->comm, sizeof(data->comm));
        data->lat = (ts - data->ts)/1000;
        if (data->lat > MIN_US) {
            FACTOR
            data->pid >>= 32;
            events.perf_submit(ctx, data, sizeof(struct data_t));
        }
        p.delete(&pid);
    }
}

ಈ ಕಾರ್ಯವು ಹಿಂದಿನದಕ್ಕೆ ಹೋಲುತ್ತದೆ: ಪ್ರಕ್ರಿಯೆಯ PID ಮತ್ತು ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್ ಅನ್ನು ನಾವು ಕಂಡುಕೊಳ್ಳುತ್ತೇವೆ, ಆದರೆ ಹೊಸ ಡೇಟಾ ರಚನೆಗಾಗಿ ಮೆಮೊರಿಯನ್ನು ನಿಯೋಜಿಸುವುದಿಲ್ಲ. ಬದಲಿಗೆ, ನಾವು == ಪ್ರಸ್ತುತ PID ಅನ್ನು ಬಳಸಿಕೊಂಡು ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ರಚನೆಗಾಗಿ ಹ್ಯಾಶ್ ಟೇಬಲ್ ಅನ್ನು ಹುಡುಕುತ್ತೇವೆ. ರಚನೆಯು ಕಂಡುಬಂದರೆ, ನಾವು ಚಾಲನೆಯಲ್ಲಿರುವ ಪ್ರಕ್ರಿಯೆಯ ಹೆಸರನ್ನು ಕಂಡುಹಿಡಿಯುತ್ತೇವೆ ಮತ್ತು ಅದನ್ನು ಸೇರಿಸುತ್ತೇವೆ.

ಥ್ರೆಡ್ GID ಪಡೆಯಲು ನಾವು ಇಲ್ಲಿ ಬಳಸುವ ಬೈನರಿ ಶಿಫ್ಟ್ ಅಗತ್ಯವಿದೆ. ಆ. ನಾವು ಕೆಲಸ ಮಾಡುತ್ತಿರುವ ಸಂದರ್ಭದಲ್ಲಿ ಥ್ರೆಡ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿದ ಮುಖ್ಯ ಪ್ರಕ್ರಿಯೆಯ PID. ನಾವು ಕರೆಯುವ ಕಾರ್ಯ bpf_get_current_pid_tgid() ಥ್ರೆಡ್‌ನ GID ಮತ್ತು ಅದರ PID ಎರಡನ್ನೂ ಒಂದೇ 64-ಬಿಟ್ ಮೌಲ್ಯದಲ್ಲಿ ಹಿಂತಿರುಗಿಸುತ್ತದೆ.

ಟರ್ಮಿನಲ್‌ಗೆ ಔಟ್‌ಪುಟ್ ಮಾಡುವಾಗ, ನಾವು ಪ್ರಸ್ತುತ ಥ್ರೆಡ್‌ನಲ್ಲಿ ಆಸಕ್ತಿ ಹೊಂದಿಲ್ಲ, ಆದರೆ ನಾವು ಮುಖ್ಯ ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ ಆಸಕ್ತಿ ಹೊಂದಿದ್ದೇವೆ. ನಿರ್ದಿಷ್ಟ ಮಿತಿಯೊಂದಿಗೆ ಪರಿಣಾಮವಾಗಿ ವಿಳಂಬವನ್ನು ಹೋಲಿಸಿದ ನಂತರ, ನಾವು ನಮ್ಮ ರಚನೆಯನ್ನು ಹಾದು ಹೋಗುತ್ತೇವೆ ಡೇಟಾ ಟೇಬಲ್ ಮೂಲಕ ಬಳಕೆದಾರರ ಜಾಗಕ್ಕೆ ಘಟನೆಗಳು, ಅದರ ನಂತರ ನಾವು ನಮೂದನ್ನು ಅಳಿಸುತ್ತೇವೆ p.

ಈ ಕೋಡ್ ಅನ್ನು ಲೋಡ್ ಮಾಡುವ ಪೈಥಾನ್ ಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿ, ನಾವು MIN_US ಮತ್ತು FACTOR ಅನ್ನು ವಿಳಂಬ ಮಿತಿಗಳು ಮತ್ತು ಸಮಯ ಘಟಕಗಳೊಂದಿಗೆ ಬದಲಾಯಿಸಬೇಕಾಗಿದೆ, ಅದನ್ನು ನಾವು ವಾದಗಳ ಮೂಲಕ ಹಾದುಹೋಗುತ್ತೇವೆ:

bpf_text = bpf_text.replace('MIN_US',str(min_usec))
if args.milliseconds:
	bpf_text = bpf_text.replace('FACTOR','data->lat /= 1000;')
	label = "msec"
else:
	bpf_text = bpf_text.replace('FACTOR','')
	label = "usec"

ಈಗ ನಾವು BPF ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಸಿದ್ಧಪಡಿಸಬೇಕಾಗಿದೆ BPF ಮ್ಯಾಕ್ರೋ ಮತ್ತು ಮಾದರಿಗಳನ್ನು ನೋಂದಾಯಿಸಿ:

b = BPF(text=bpf_text)
b.attach_kprobe(event="generic_make_request",fn_name="start")
b.attach_kretprobe(event="generic_make_request",fn_name="stop")

ನಾವೂ ನಿರ್ಧರಿಸಬೇಕಾಗುತ್ತದೆ struct data_t ನಮ್ಮ ಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿ, ಇಲ್ಲದಿದ್ದರೆ ನಾವು ಏನನ್ನೂ ಓದಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ:

TASK_COMM_LEN = 16	# linux/sched.h
DISK_NAME_LEN = 32	# linux/genhd.h
class Data(ct.Structure):
	_fields_ = [("pid", ct.c_ulonglong),
            	("ts", ct.c_ulonglong),
            	("comm", ct.c_char * TASK_COMM_LEN),
            	("lat", ct.c_ulonglong),
            	("disk",ct.c_char * DISK_NAME_LEN)]

ಟರ್ಮಿನಲ್‌ಗೆ ಡೇಟಾವನ್ನು ಔಟ್‌ಪುಟ್ ಮಾಡುವುದು ಕೊನೆಯ ಹಂತವಾಗಿದೆ:

def print_event(cpu, data, size):
    global start
    event = ct.cast(data, ct.POINTER(Data)).contents
    if start == 0:
        start = event.ts
    time_s = (float(event.ts - start)) / 1000000000
    print("%-18.9f %-16s %-6d   %-1s %s   %s" % (time_s, event.comm, event.pid, event.lat, label, event.disk))

b["events"].open_perf_buffer(print_event)
# format output
start = 0
while 1:
    try:
        b.perf_buffer_poll()
    except KeyboardInterrupt:
        exit()

ಸ್ಕ್ರಿಪ್ಟ್ ಸ್ವತಃ ಇಲ್ಲಿ ಲಭ್ಯವಿದೆ GITHub. fio ಚಾಲನೆಯಲ್ಲಿರುವ ಪರೀಕ್ಷಾ ವೇದಿಕೆಯಲ್ಲಿ ಅದನ್ನು ಚಲಾಯಿಸಲು ಪ್ರಯತ್ನಿಸೋಣ, bcache ಗೆ ಬರೆಯಿರಿ ಮತ್ತು udevadm ಮಾನಿಟರ್‌ಗೆ ಕರೆ ಮಾಡಿ:

eBPF/BCC ಬಳಸಿಕೊಂಡು ಹೆಚ್ಚಿನ Ceph ಲೇಟೆನ್ಸಿಯಿಂದ ಕರ್ನಲ್ ಪ್ಯಾಚ್‌ಗೆ
ಅಂತಿಮವಾಗಿ! ಈಗ ನಾವು ಸ್ಟಾಲಿಂಗ್ bcache ಸಾಧನದಂತೆ ತೋರುತ್ತಿರುವುದು ವಾಸ್ತವವಾಗಿ ಸ್ಥಗಿತಗೊಳಿಸುವ ಕರೆ ಎಂದು ನಾವು ನೋಡುತ್ತೇವೆ generic_make_request() ಕ್ಯಾಶ್ ಮಾಡಿದ ಡಿಸ್ಕ್ಗಾಗಿ.

ಕರ್ನಲ್ ಅನ್ನು ಅಗೆಯಿರಿ

ವಿನಂತಿ ಪ್ರಸರಣ ಸಮಯದಲ್ಲಿ ನಿಖರವಾಗಿ ಏನು ನಿಧಾನವಾಗುತ್ತಿದೆ? ವಿನಂತಿಯ ಲೆಕ್ಕಪತ್ರ ನಿರ್ವಹಣೆಯ ಪ್ರಾರಂಭಕ್ಕೂ ಮುಂಚೆಯೇ ವಿಳಂಬ ಸಂಭವಿಸುತ್ತದೆ ಎಂದು ನಾವು ನೋಡುತ್ತೇವೆ, ಅಂದರೆ. ಅದರ ಮೇಲಿನ ಅಂಕಿಅಂಶಗಳ ಹೆಚ್ಚಿನ ಔಟ್‌ಪುಟ್‌ಗಾಗಿ ನಿರ್ದಿಷ್ಟ ವಿನಂತಿಯ ಲೆಕ್ಕಪತ್ರ ನಿರ್ವಹಣೆ (/proc/diskstats ಅಥವಾ iostat) ಇನ್ನೂ ಪ್ರಾರಂಭವಾಗಿಲ್ಲ. ಸಮಸ್ಯೆಯನ್ನು ಪುನರುತ್ಪಾದಿಸುವಾಗ iostat ಅನ್ನು ಚಾಲನೆ ಮಾಡುವ ಮೂಲಕ ಇದನ್ನು ಸುಲಭವಾಗಿ ಪರಿಶೀಲಿಸಬಹುದು, ಅಥವಾ BCC ಸ್ಕ್ರಿಪ್ಟ್ ಜೈವಿಕತೆ, ಇದು ವಿನಂತಿಯ ಲೆಕ್ಕಪತ್ರದ ಪ್ರಾರಂಭ ಮತ್ತು ಅಂತ್ಯವನ್ನು ಆಧರಿಸಿದೆ. ಈ ಯಾವುದೇ ಉಪಯುಕ್ತತೆಗಳು ಕ್ಯಾಶ್ ಮಾಡಿದ ಡಿಸ್ಕ್‌ಗೆ ವಿನಂತಿಗಳಿಗಾಗಿ ಸಮಸ್ಯೆಗಳನ್ನು ತೋರಿಸುವುದಿಲ್ಲ.

ನಾವು ಕಾರ್ಯವನ್ನು ನೋಡಿದರೆ generic_make_request(), ನಂತರ ವಿನಂತಿಯು ಲೆಕ್ಕಪತ್ರವನ್ನು ಪ್ರಾರಂಭಿಸುವ ಮೊದಲು, ಇನ್ನೂ ಎರಡು ಕಾರ್ಯಗಳನ್ನು ಕರೆಯಲಾಗುತ್ತದೆ ಎಂದು ನಾವು ನೋಡುತ್ತೇವೆ. ಪ್ರಥಮ - generic_make_request_checks(), ಡಿಸ್ಕ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಸಂಬಂಧಿಸಿದಂತೆ ವಿನಂತಿಯ ನ್ಯಾಯಸಮ್ಮತತೆಯನ್ನು ಪರಿಶೀಲಿಸುತ್ತದೆ. ಎರಡನೇ - blk_queue_enter(), ಇದು ಆಸಕ್ತಿದಾಯಕ ಸವಾಲನ್ನು ಹೊಂದಿದೆ wait_event_interruptible():

ret = wait_event_interruptible(q->mq_freeze_wq,
	(atomic_read(&q->mq_freeze_depth) == 0 &&
	(preempt || !blk_queue_preempt_only(q))) ||
	blk_queue_dying(q));

ಅದರಲ್ಲಿ, ಕರ್ನಲ್ ಕ್ಯೂ ಅನ್ನು ಫ್ರೀಜ್ ಮಾಡಲು ಕಾಯುತ್ತದೆ. ವಿಳಂಬವನ್ನು ಅಳೆಯೋಣ blk_queue_enter():

~# /usr/share/bcc/tools/funclatency  blk_queue_enter -i 1 -m               	 
Tracing 1 functions for "blk_queue_enter"... Hit Ctrl-C to end.

 	msecs           	: count 	distribution
     	0 -> 1      	: 341  	|****************************************|

 	msecs           	: count 	distribution
     	0 -> 1      	: 316  	|****************************************|

 	msecs           	: count 	distribution
     	0 -> 1      	: 255  	|****************************************|
     	2 -> 3      	: 0    	|                                    	|
     	4 -> 7      	: 0    	|                                    	|
     	8 -> 15     	: 1    	|                                    	|

ನಾವು ಪರಿಹಾರದ ಸಮೀಪದಲ್ಲಿರುವಂತೆ ತೋರುತ್ತಿದೆ. ಸರದಿಯನ್ನು ಫ್ರೀಜ್ ಮಾಡಲು/ಫ್ರೀಜ್ ಮಾಡಲು ಬಳಸಲಾಗುವ ಕಾರ್ಯಗಳು blk_mq_freeze_queue и blk_mq_unfreeze_queue. ವಿನಂತಿಯ ಸರದಿಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅಗತ್ಯವಾದಾಗ ಅವುಗಳನ್ನು ಬಳಸಲಾಗುತ್ತದೆ, ಈ ಸರತಿಯಲ್ಲಿನ ವಿನಂತಿಗಳಿಗೆ ಸಂಭಾವ್ಯ ಅಪಾಯಕಾರಿ. ಕರೆ ಮಾಡಿದಾಗ blk_mq_freeze_queue() ಕಾರ್ಯ blk_freeze_queue_start() ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸಲಾಗಿದೆ q->mq_freeze_depth. ಇದರ ನಂತರ, ಕ್ಯೂ ಖಾಲಿಯಾಗಲು ಕರ್ನಲ್ ಕಾಯುತ್ತದೆ blk_mq_freeze_queue_wait().

ಈ ಸರದಿಯನ್ನು ತೆರವುಗೊಳಿಸಲು ತೆಗೆದುಕೊಳ್ಳುವ ಸಮಯವು ಡಿಸ್ಕ್ ಲೇಟೆನ್ಸಿಗೆ ಸಮನಾಗಿರುತ್ತದೆ ಏಕೆಂದರೆ ಕರ್ನಲ್ ಎಲ್ಲಾ ಸರತಿಯಲ್ಲಿರುವ ಕಾರ್ಯಾಚರಣೆಗಳು ಪೂರ್ಣಗೊಳ್ಳಲು ಕಾಯುತ್ತದೆ. ಕ್ಯೂ ಖಾಲಿಯಾದ ನಂತರ, ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಬದಲಾವಣೆಗಳನ್ನು ಅನ್ವಯಿಸಲಾಗುತ್ತದೆ. ಅದರ ನಂತರ ಅದನ್ನು ಕರೆಯಲಾಗುತ್ತದೆ blk_mq_unfreeze_queue(), ಕೌಂಟರ್ ಅನ್ನು ಕಡಿಮೆಗೊಳಿಸುವುದು ಫ್ರೀಜ್_ಆಳ.

ಈಗ ಪರಿಸ್ಥಿತಿಯನ್ನು ಸರಿಪಡಿಸಲು ನಮಗೆ ಸಾಕಷ್ಟು ತಿಳಿದಿದೆ. udevadm ಟ್ರಿಗ್ಗರ್ ಆಜ್ಞೆಯು ಬ್ಲಾಕ್ ಸಾಧನದ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಅನ್ವಯಿಸಲು ಕಾರಣವಾಗುತ್ತದೆ. ಈ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು udev ನಿಯಮಗಳಲ್ಲಿ ವಿವರಿಸಲಾಗಿದೆ. ಯಾವ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಕ್ಯೂ ಅನ್ನು ಫ್ರೀಜ್ ಮಾಡುತ್ತಿವೆ ಎಂಬುದನ್ನು sysfs ಮೂಲಕ ಬದಲಾಯಿಸಲು ಪ್ರಯತ್ನಿಸುವ ಮೂಲಕ ಅಥವಾ ಕರ್ನಲ್ ಮೂಲ ಕೋಡ್ ಅನ್ನು ನೋಡುವ ಮೂಲಕ ನಾವು ಕಂಡುಹಿಡಿಯಬಹುದು. ನಾವು BCC ಉಪಯುಕ್ತತೆಯನ್ನು ಸಹ ಪ್ರಯತ್ನಿಸಬಹುದು ಜಾಡಿನ, ಇದು ಟರ್ಮಿನಲ್‌ಗೆ ಪ್ರತಿ ಕರೆಗೆ ಕರ್ನಲ್ ಮತ್ತು ಯೂಸರ್‌ಸ್ಪೇಸ್ ಸ್ಟಾಕ್ ಟ್ರೇಸ್‌ಗಳನ್ನು ಔಟ್‌ಪುಟ್ ಮಾಡುತ್ತದೆ blk_freeze_queue, ಉದಾಹರಣೆಗೆ:

~# /usr/share/bcc/tools/trace blk_freeze_queue -K -U
PID 	TID 	COMM        	FUNC        	 
3809642 3809642 systemd-udevd   blk_freeze_queue
    	blk_freeze_queue+0x1 [kernel]
    	elevator_switch+0x29 [kernel]
    	elv_iosched_store+0x197 [kernel]
    	queue_attr_store+0x5c [kernel]
    	sysfs_kf_write+0x3c [kernel]
    	kernfs_fop_write+0x125 [kernel]
    	__vfs_write+0x1b [kernel]
    	vfs_write+0xb8 [kernel]
    	sys_write+0x55 [kernel]
    	do_syscall_64+0x73 [kernel]
    	entry_SYSCALL_64_after_hwframe+0x3d [kernel]
    	__write_nocancel+0x7 [libc-2.23.so]
    	[unknown]

3809631 3809631 systemd-udevd   blk_freeze_queue
    	blk_freeze_queue+0x1 [kernel]
    	queue_requests_store+0xb6 [kernel]
    	queue_attr_store+0x5c [kernel]
    	sysfs_kf_write+0x3c [kernel]
    	kernfs_fop_write+0x125 [kernel]
    	__vfs_write+0x1b [kernel]
    	vfs_write+0xb8 [kernel]
    	sys_write+0x55 [kernel]
    	do_syscall_64+0x73 [kernel]
    	entry_SYSCALL_64_after_hwframe+0x3d [kernel]
    	__write_nocancel+0x7 [libc-2.23.so]
    	[unknown]

Udev ನಿಯಮಗಳು ಬಹಳ ವಿರಳವಾಗಿ ಬದಲಾಗುತ್ತವೆ ಮತ್ತು ಸಾಮಾನ್ಯವಾಗಿ ಇದು ನಿಯಂತ್ರಿತ ರೀತಿಯಲ್ಲಿ ನಡೆಯುತ್ತದೆ. ಆದ್ದರಿಂದ ಈಗಾಗಲೇ ಹೊಂದಿಸಲಾದ ಮೌಲ್ಯಗಳನ್ನು ಅನ್ವಯಿಸುವುದರಿಂದ ವಿನಂತಿಯನ್ನು ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಡಿಸ್ಕ್‌ಗೆ ವರ್ಗಾಯಿಸುವಲ್ಲಿ ವಿಳಂಬವನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ ಎಂದು ನಾವು ನೋಡುತ್ತೇವೆ. ಸಹಜವಾಗಿ, ಡಿಸ್ಕ್ ಕಾನ್ಫಿಗರೇಶನ್‌ನಲ್ಲಿ ಯಾವುದೇ ಬದಲಾವಣೆಗಳಿಲ್ಲದಿದ್ದಾಗ udev ಈವೆಂಟ್‌ಗಳನ್ನು ರಚಿಸುವುದು (ಉದಾಹರಣೆಗೆ, ಸಾಧನವನ್ನು ಆರೋಹಿಸಲಾಗಿಲ್ಲ/ಡಿಸ್‌ಕನೆಕ್ಟ್ ಆಗಿಲ್ಲ) ಉತ್ತಮ ಅಭ್ಯಾಸವಲ್ಲ. ಆದಾಗ್ಯೂ, ನಾವು ಕರ್ನಲ್ ಅನಗತ್ಯ ಕೆಲಸವನ್ನು ಮಾಡದಂತೆ ಸಹಾಯ ಮಾಡಬಹುದು ಮತ್ತು ಅಗತ್ಯವಿಲ್ಲದಿದ್ದರೆ ವಿನಂತಿಯ ಸರತಿಯನ್ನು ಫ್ರೀಜ್ ಮಾಡಬಹುದು. ಮೂರು ಸಣ್ಣ ಒಪ್ಪಿಸುತ್ತೇನೆ ಪರಿಸ್ಥಿತಿಯನ್ನು ಸರಿಪಡಿಸಿ.

ತೀರ್ಮಾನ

eBPF ತುಂಬಾ ಹೊಂದಿಕೊಳ್ಳುವ ಮತ್ತು ಶಕ್ತಿಯುತ ಸಾಧನವಾಗಿದೆ. ಲೇಖನದಲ್ಲಿ ನಾವು ಒಂದು ಪ್ರಾಯೋಗಿಕ ಪ್ರಕರಣವನ್ನು ನೋಡಿದ್ದೇವೆ ಮತ್ತು ಏನು ಮಾಡಬಹುದು ಎಂಬುದರ ಒಂದು ಸಣ್ಣ ಭಾಗವನ್ನು ಪ್ರದರ್ಶಿಸಿದ್ದೇವೆ. ನೀವು BCC ಉಪಯುಕ್ತತೆಗಳನ್ನು ಅಭಿವೃದ್ಧಿಪಡಿಸಲು ಆಸಕ್ತಿ ಹೊಂದಿದ್ದರೆ, ಅದನ್ನು ನೋಡುವುದು ಯೋಗ್ಯವಾಗಿದೆ ಅಧಿಕೃತ ಟ್ಯುಟೋರಿಯಲ್, ಇದು ಮೂಲಭೂತ ಅಂಶಗಳನ್ನು ಚೆನ್ನಾಗಿ ವಿವರಿಸುತ್ತದೆ.

eBPF ಆಧಾರಿತ ಇತರ ಆಸಕ್ತಿದಾಯಕ ಡೀಬಗ್ ಮತ್ತು ಪ್ರೊಫೈಲಿಂಗ್ ಪರಿಕರಗಳಿವೆ. ಅವುಗಳಲ್ಲಿ ಒಂದು - bpftrace, ಇದು awk ತರಹದ ಭಾಷೆಯಲ್ಲಿ ಶಕ್ತಿಯುತ ಒನ್-ಲೈನರ್‌ಗಳು ಮತ್ತು ಸಣ್ಣ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಬರೆಯಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಇನ್ನೊಂದು - ebpf_exporter, ಕಡಿಮೆ ಮಟ್ಟದ, ಹೆಚ್ಚಿನ ರೆಸಲ್ಯೂಶನ್ ಮೆಟ್ರಿಕ್‌ಗಳನ್ನು ನೇರವಾಗಿ ನಿಮ್ಮ ಪ್ರಮೀತಿಯಸ್ ಸರ್ವರ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ, ನಂತರ ಸುಂದರವಾದ ದೃಶ್ಯೀಕರಣಗಳು ಮತ್ತು ಎಚ್ಚರಿಕೆಗಳನ್ನು ಪಡೆಯುವ ಸಾಮರ್ಥ್ಯದೊಂದಿಗೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ