איך להריץ Async Profiler

לפעמים, לכתוב קוד שפשוט עובד זה לא מספיק. לפעמים אנחנו נרצה מה באמת קורה עם הקוד שלנו בזמן ריצה.
כמו למשל מה מצב הזיכרון, איך המעבד עובד וכו'.
אחד מהכלים הכי פופולריים היום שמאפשרים לנו לחקור את הקרביים שלנו הוא ה-Async Profiler.
בפוסט הזה אני אסביר מה הוא בכלל פרופיילר, מהו ה-Async Profiler ואיך משתמשים בו.

אלה מכם שמעדיפים הרצאות מוקלטות, אני ממליץ בחום על ההרצאה של דורון סקלר שאפשר למצוא אותה כאן

מבוא לפרופיילרים בג'אווה

מה זה פרופיילר

Java Profiler הוא כלי אשר מאפשר לנו לנטר מיבנים ופעולות בבייטקוד בג'אווה ברמת ה-JVM.
זה כולל:

  • יצירת אובייקטים
  • פעולות איטרטיביות (כולל רקורסיביות)
  • קריאה למתודות
  • יצירה והרצה של threads
  • פעולת של garbage collection.

סוגים של פרופיילרים

יש לנו שני סוגים עיקריים של פרופיילרים.
הראשון נקרא Sampling Profilers – פרופיילרים מהסוג הזה דוגמים את מצב הסטאק של האפליקציה שלנו תוך כדי ריצה על מנת לאסוף את המידע המבוקש.
יש להם overhead (השפעה על הקוד שרץ) קטן, ואנחנו יכולים לשלוט על כמה מידע הם אוספים.

הסוג השני נקרא Bytecode injection profilers. פרופיילרים מהסוג הזה מזריקים קוד ברמת הבייטקוד על מנת לאסוף את המידע שלהם. יש להם השפעה מאוד גדולה על הזמני ריצה של הקוד, ולכן פחות נהוג להשתמש בהם על קוד בפרודקשיין.

Sampling Profilers

כיוון שבפוסט הזה אנחנו נתמקד בAsync Profiler, אנחנו נצלול קצת יותר להבין מהם ה-sampling profilers, בגלל שה-Async Profiler הוא פרופיילר מסוג סמפלינג.
אז הסמפלינג פרופיילרים בודקים את הסטאק של האפליקצהי שלנו באינטרוולים קבועים. למשל, ה-Async Profiler דוגם את האפליקציה 100 פעמים בשניה (כל 20ms), אבל כמובן שאפשר לקנפג אותו לדגום באינטרוולים אחרים.
הפרופיילרים הללו משתמשים ב-API של ג'אווה על מנת לאסוף את המידע מתוך האפליקציה.

אך לפרופיילרים מהסוג הזה יש בעיה מסויימת הנקראת Safepoint Bias. בקצרה, כאשר אנחנו מנסים למשוך מידע מאפליקציית ג'אוה, ה-JVM מחזיר לנו מידע בנקודות זמן מסוימות, הנקראות Safepoints. הבעיה היא שהאפליקציה שלנו עושה עוד הרבה עבודה בין SafePoints שונים, ולכן אנחנו לא מקבלים את המידע השלם על מה קורה בקוד שלו.

Async Profiler

אז אחרי שהבנו מהם פרופיילרים באופן כללי, בואו נתמקד בפרופיילר שבאנו לדבר עליו, והוא ה-Async Profiler.

מהו ה-Async Profiler

ה-Async Profiler פותח על ידי מפתח ג'אווה בשם Andrei Pnagin.
ה-Async Profiler הוא פרופיילר מהסוג הראשון, כלומר Sampling Profiler.
הוא אינו סובל מבעיית ה-Safepoint Bias כיוון שהוא משתמש בAPI לא רשמי אשר בודק את הסטאק של האפליקציה שלנו בצורה אסיכנרונית,
ובצורה הזאת הוא מצליח לאסוף מידע גם מנקודות זמן שאינן Safepoints.

ה-Async Profiler יכול לאסוף מידע על כמה סוגים של איוונטים:

  • CPU – אסיפת מידע על פעולות האפליקציה על המעבד
  • הקצאות זיכרון – בדיקת הקצאת זיכרון על ה-Java Heap
  • ביצועי תוכנה וחומרה – למשל פספוסי קאש, page faults, שינויי קונטקסט ועוד.
  • בדיקת דדלוקים ומרוצים

איך מריצים Async Profiler

יש לנו שתי דרכים להריץ את הפרופיילר שלנו. הראשונה היא על ידי סקריפט באש אשר להוריד מהפרוייקט גיטהאב של Async Profiler
השניה היא להצמיד אותו דרך Java Agent.
בפוסט הזה אני אתרכז באופציה הראשונה (כי היא יותר קלה בעיני), אך חשוב לי שתדעו שאפשר בהחלט להשתמש בכל אחד.

על מנת להריץ את הפרופיילר עליכם ללכת לתיקייה שהורדתם, ולהריץ את הקובץ profiler.sh. לדוגמה:

./profiler.sh -d 10 -e cpu -f ./out.html jps

מה שאנחנו רואים פה הוא הרצה של הפרופיילר.
הפלאג הראשון -d מציין לפרופיילר כמה זמן עליו לרוץ בשניות. במקרה הזה אנחנו מדברים על 10 שניות.
הפלאג השני הוא -e והוא מייצג לנו אילו איוונטים אנחנו רוצים שהפרופיילר יאסוף. בדוגמה הזאת אנחנו מבקשים CPU, אבל יכולנו גם להעביר alloc על מנת לאסוף איוונטים של הקצאת זיכרון.
הפלאג השליש הוא -f שהוא מייצג לנו איפה לשמור את ה-output שלנו. באופן דיפולטיבי, Async Profiler שומר את המידע שלו בפורמט של FlameGraph.
הפלאג האחרון פה הוא jms, כאשר אנחנו מעבירים אותו, ה-Async Profiler יזהה לבד את הפרוסס של Java ויתחבר אליו אוטומטית. אם אתם רוצים לשלוט לאיזה פרוסס הפרופיילר יתחבר, אתם יכולים להעביר PID.

לאסוף כמה איוונטים ביחד

יש לנו אפשרות גם לאסוף כמה סוגים של איוונטים ביחד. למשל בצורה הבאה

./profiler -d 10 -e cpu,alloc -f ./out.html 23

במקרה הזה אנחנו מבקשים פרופיילר ל-10 שניות, עבור איוונטים של CPU ושל הקצאת זיכרון ביחד.
בנוסף הפעם העברתי PID עבור תהליך ספציפי שאני רוצה שהפרופיילר יאסוף עליו מידע.
על מנת לראות את רשימת האיוונטים המלאה עליכם להריץ

./profiler list

פורמטים נתמכים

כמו שכבר כתבתי למעלה, ה-Async Profiler מוציא את המידע בפורמט של FlameGraph באופן דיפולטיבי.
אך יש לנו אפשרות לבחור פורמטים אחרים, למשל אם אנחנו רוצים להשתמש בתוכנות יותר מקצועיות כמו JProfiler או YourKit.

./profiler -d 10 -e alloc -o jfr -f ./out.jfr 23

כאן אנחנו מעבירים פלאג חדש, -o שהוא מקבל את הפורמט שאנחנו רוצים לעבוד איתו, במקרה הזה אנחנו מבקשים את הפלט בפורמט של jfr.

פיצ'רים נוספים

יש ל-Async Profiler עוד הרבה מאוד פיצ'רים שאפשר להשתמש בהם.
אם אתם מעדיפים את הגרסה הכתובה, אפשר למצוא הכל ב-WIKI של הפרויקט
ואם אתם מעדיפים הרצאות, יש פלייליסט נהדר ביוטיוב על זה

סיכום

בפוסט הזה למדנו איך אנחנו יכולים להשתמש ב-Async Profiler על מנת לעקוב אחרי הקוד שלנו בזמן ריצה
ראינו אילו איוונטים הפרופיילר יכול לאסוף ואיך אנחנו יכולים להגדיר את הפרופיילר לאסוף דברים שונים למשך זמן שונה.

וכמו תמיד, אשמח לקבל כל הערה, הארה או שאלה שיש לכם

השאר תגובה

Scroll to Top