חדשות היום

שימוש בEvent Trace מסייע בניתוח התנהגות מערכות זמן אמת ומשפר משמעותית את תפוקת המערכת

כוונון ו”כיול” נכון של מערך רמות העדיפות לThreads, עשוי לשפר את זמני הcontext switching ולעלות את תפוקת המערכת הכללית בכ80%!
אפליקציות תוכנה לזמן-אמת הנן מרובות משימה (tasks or threads), כל משימה מבצעת חלק מסוים של המערכת בפיקוחה של מערכת ההפעלה (RTOS). במערכות זמן-אמת רמת העדיפות (priority) ל- thread משקפת באופן יחסי לשאר הthreads את חשיבות המשימה, ותפקיד הRTOS הנו לנהל ולהעניק את “זכות” הפעולה למשימה החשובה ביותר בכל רגע נתון.
ישנן מספר שיטות נפוצות לחלוקת העבודה בין המשימות, השכיחה שבהן הנה preemptive scheduling, אשר דואגת תמיד להעניק זכות למשימה בעלת רמת העדיפות הגבוהה ביותר מבין השאר.
בל נשכח שהמטרה העיקרית הנה להשיג את התפוקה הגבוהה ביותר של המערכת שאותה אנו מיישמים, אשר לדוגמא באה לידי ביטוי בעיבוד והעברת כמה שיותר packets, streamed video frames וכיוצ”ב, בזמן נתון.
מטרתו העיקרית של השימוש בpreemptive scheduling היא השגת תגובה מהירה במיתוג ומעבר ממשימה נוכחית למשימה בעלת עדיפות גבוהה יותר, אולם מטרה זו לעיתים אינה עולה בקנה אחד עם הרצון להשיג תפוקת מערכת גבוהה, וזאת מכיוון שהפעלת מנגנון    preemptive scheduling, לכשעצמה מוסיפה overhead המכביד על התפוקה וביצועי המערכת. תגובה מהירה ותפוקה גבוהה הנם לעיתים בגדר דבר והיפוכו.
ישנן דרכים ושיטות שונות המאפשרות לשפר את הקונפליקט הנ”ל.
לדוגמא, אפשר לשקול שלא להעניק רמת עדיפות ייחודית לכל thread אלא לאחד מספר threads לרמת עדיפות שווה, פעולה שסביר תשפר את רמת התפוקה של המערכת מבלי לפגוע ביכולת התגובה שלה.
בנוסף לכך ניתן לשלב שימוש ב round-robin כך שיתאפשר שכל thread בקבוצת threads בעלת רמת עדיפות זהה, יתבצע עד השלמת המשימה, כל אחד בתורו ובאופן שווה.
למערכת ההפעלה ThreadX של Express Logic קיימת טכניקה ייחודית הקרויה preemption-threshold.
טכניקה זו מאפשרת לשלב שתי אסטרטגיות scheduling, “עדיפות ייחודית לכל thread ” ו”עדיפות זהה לקבוצת threads”  ולקבוע את קו הגבול ביניהן, כלומר את הסף המחלק בין קבוצות threads, כאשר האחת תקבל רמת עדיפות אחידה לכל הthreads והשנייה עדיפות ייחודית לכל  threadכאשר רמת עדיפותם הנה גבוהה יותר מהקבוצה האחידה. ניהול ה- scheduling של אלו שמתחת לסף יתבצע בשיטת round-robin.
ניתן גם לשנות את הסף מעלה או מטה באופן דינאמי, כך שהמערכת תכוונן סף זה בזמן אמת בהתאם להתנהגויות שלה והטוויות מראש שתקבענה ע”י מפתח המערכת.
בשיטה זו ניתן לקבוע עדיפות ייחודית לכל הthreads שבמערכת, כדי שתכנס לתוקף במידה וthreads מסוימים יעברו לקטגוריית “עדיפות ייחודית” כתוצאה משינוי הסף.

TraceX™
כדי להחליט מהן השיטות האופטימאליות לשימוש במערכת מסוימת, אפשר להיעזר בנתח תוכנה כדוגמת ה- TraceX של Express Logic, המהווה   real-time event trace tool ומאפשר הקלטה והצגת אירועים שהתרחשו בזמן אמת  ברמת מערכת ההפעלה על כל מרכיביה העיקריים, כמו  מיתוג מthread לthread על ציר הזמן באופן גראפי.
TraceX מאפשר ניתוח של ההתרחשויות כל האירועים לשם הבנה מעמיקה של התנהגות המערכת במצבים שונים של שילובי שיטות הscheduling השונות, וזאת לשם בחירת השילוב האופטימאלי להשגת שני היעדים העיקריים: תגובה מהירה ותפוקה גבוהה.  המטרה לזהות מצבי מיתוג (context-switch) מרובים ומיותרים ולהפחית את מספרם ככל האפשר אך ללא פגיעה בתגובת המערכת הדרושה.

The Context-Switch
context-switch הנו תהליך מורכב שבו מערכת ההפעלה שומרת את כל הנתונים  שבהם הthread הנוכחי משתמש (את ה context שלו) בזיכרון הstack שלו, כמו לדוגמא תוכן האוגרים, program counter ונתונים חשובים אחרים ולחילופין מערכת ההפעלה טוענת מהstack את הcontext של הthread שאמור להיכנס לפעולה במקום הthread שפעולתו תופסק מיד לאחר המיתוג. את נתוני הcontext של הthread היוצא שנשמרו, מערכת ההפעלה תטען חזרה ברגע שהthread יכנס לפעולה מחודשת.
אפשר לומר שcontext-switch הנה הפעולה הצורכת-זמן המשמעותית ביותר מבין שאר פעולות מערכת ההפעלה. לעיתים היא אף צורכת מאות מחזורי CPU.
להלן רשימת הפעולות המתבצעות במהלך context-switch אופייני:

בעוד שיצרני מערכות ההפעלה משקיעים מאמצים בייעול וקיצור זמני ביצוע הcontext-switch, שומה על מפתחי האפליקציה לצמצם ככל האפשר את השימוש בהם.
ככלל, כדאי לשמור על עיקרון שיוך קבוצות threads לרמת עדיפות זהה.
שיוך מספר threads לרמת עדיפות זהה יקנה למערכת יתרונות נוספים כמו, פשטות בהרכשת רמת עדיפות במעבר תכונות מ thread אחד למשנהו בירושה, ויישום round-robin או      time-slicing.
קיימת חשיבות בשימוש במנגנונים הללו ביישום במערכות זמן-אמת, ולכן חובה לשייך קבוצות threads לאותה רמת עדיפות, אחרת יישום המערכת יהיה מסובך למדי או אפילו בלתי אפשרי.

מערכת ההפעלה ThreadX של Express Logic, מאפשרת שימוש במגוון מנגנוני  scheduling, כמו unique thread priorities, רמת עדיפות זהה לקבוצת threads מסויימת, או שילוב של שניהם.
במאמר זה, אשתמש בThreadX כדי ליישם אפליקציית דוגמא ע”י כל אחת מהאסטרטגיות הנ”ל, ואשתמש בTraceX כדי למדוד ולהציג את ההבדלים בתפוקה ובביצועי האפליקציה בין אסטרטגית מנגנון סדרי עדיפות אחת למשניה. נוכל לראות שאכן השימוש בשיוך קבוצות threads לרמת עדיפות זהה מייעל את ביצועי המערכת.

מערכת דוגמא
מקרה פשוט אך שכיח הנו כאשר thread מסוים מצוי במצב “ממתין” למסר שיגיע      לmessage queue שלו, וכאשר המסר נקלט הthread “הממתין” הופך למצב “ready”.
כלומר מוכן לפעולה מיידית. באחריות מערכת ההפעלה לעקוב ולזהות בכל רגע נתון את הthreads המצויים בסטטוס “ready”, את אלו המצויים בwaiting”” ואת המצבים אשר thread הופך ממצב “waiting” ל”ready”. כאשר thread הופך ל”ready” ובמידה והעדיפות שלו גבוהה מזה הפעיל נוכחית, הRTOS מבצע פעולת context switch ומכניס את הthread החדש לפעולה.
כדי להמחיש את ההשפעה של שיטות השיוך השונות של רמת העדיפות לthreads על כמות מיתוגי הcontext, נשתמש לדוגמא במערכת בעלת ארבעה threads: A,B,C,D.
בדוגמא הזו D הנו “יצרן” והשאר הנם “צרכנים”, כאשר D שולח 3 מסרים לכל אחד מהmessage queue של שאר הthreads, ובסכ”ה תשעה.
כל אחד מ A,B,C בודק האם הגיע אליו מסר מD, ובמידה והגיע הוא קולט אותו. במידה וטרם הגיע, הthread נמצא בהמתנה עד שיגיע מסר עבורו. כאשר נקלט מסר, הthreads ממשיכים להמתין למסר נוסף.
מחזור אחד של שליחת 3 מסרים מD לכל אחד משלושת הthreads ייקרא “cycle”, כפי שמתואר באיור-3.
הקוד ליישום דוגמא זו ייראה כך (איור 4):

שתי אסטרטגיות –
שני מקרים
כדי להמחיש כיצד שתי השיטות משפיעות על מספר הcontext-switches שיתבצעו ע”י המערכת, נבחן שני מקרים, כאשר באחד נקבע שכל ה threads יהיו בעלי רמת עדיפות אחת ויופעלו ב round-robin ובמקרה השני לכל אחד תהיה רמת עדיפות אחרת. בכל אחד משני המקרים, נמדוד את מספר ה context-switches שיתרחשו במערכת, וכמו כן נמדוד את הזמן שייקח להשלים את אותה כמות עבודה.
מקרה 1 – כל ארבעת הthreads ישויכו לאותה רמת עדיפות (A=4, B=4, C=4, D=4)
ניתן לראות על פי תוצאת ה execution flow trace כפי שהוקלטה ע”י ה TraceX, את אופן השתלשלות האירועים במקרה מס’ 1. אגב, שייכנו לכל ה threads  (A,B,C,D)את אותה רמת עדיפות:4, וינוהלו בשיטת round-robin, וסדר פעולתם יהיה ע”פ סדר יצירתם.
מיד לאחר שthread D סיים את הפצת המסרים לשאר הthreads, כל אחד בתורו יקלוט 3 מסרים שנשלחו עבורו, וחוזר חלילה, כאשר:
QR – Queue Read, אירוע שבו בוצעה קליטה מוצלחת של מסר ע”י הthread.
IS – Internal Suspend, מצב שבו הqueue ריק והthread נכנס להמתנה, הRTOS מבצע מיתוג context לthread הבא בתור ע”פ פעולת מנגנון הround-robin, קרי D יחל לשלוח שוב מסרים.
QS – Queue Send, אירוע שבו D שולח מסר.
IR – Internal Resume, אירוע שבו D thread ממתין להשלמת קליטת המסר בqueue הנמען, אך חייב להמתין לתורו ע”פ הסדר הנקבע ע”י מנגנון הround-robin בכדי לשלוח את המסר הבא.
ניתן לראות כי במקרה מס’ 1 מתרחש context-switch בודד בכל פעם שthread (A,B,C) ממתין למסר, או שD השלים את שליחת המסרים. כלומר במחזור פעולת מערכת אחת, סך הכול התרחשו 4 מיתוגים.

מקרה 2 – כל אחד מארבעת הthreads מקבל רמת עדיפות ייחודית
הקצאת רמות העדיפות תהיה כדלקמן:
A=1 ,B=2, C=3, D=4.
מכיוון שלכל אחד מהthreads יש רמת עדיפות ייחודית, מערכת ההפעלה תמיד תעניק את זכות הריצה לthread בעל העדיפות הגבוהה מבין כל שאר הthreads המצויים במצב “ready”.
איור מס’ 8 מציג תמונה מחזורית של פעולת המערכת. ניתן לראות שמיד עם שליחת מסר מD לA, מתרחש מצב IR, כפי שקורה במקרה 1, אך בהמשך,שלא כפי שמתרחש במקרה 1, מכיוון שהthreads הממתינים למסר הנם בעלי עדיפות גבוהה משל D, הRTOS מפקיע את פעולת D ומבצע context-switches ע”פ סדר העדיפות לA, ולאחר מכן B ולבסוף C, סה”כ מתרחשים 9 מיתוגים שבהם הושלמה שליחת המסרים מD לשלושת הqueues, ובנוסף תתרחש סידרה של 9 מיתוגים נוספים שבהם תושלם קליטת המסרים של כל הthreads מהqueues שלהם.
ניתן לראות בבירור כי במקרה 2 המבוסס אסטרטגיית “עדיפות ייחודית”
בוצעו פי 4.5 מיתוגי context מאשר אלו שהתרחשו במקרה 1, המבוסס אסטרטגיית “עדיפות זהה” – round-robin.
כדי להשלים את התמונה, שנותר לנו להשוות את ביצועי זמן האמת בין שני המקרים.

ניתוח זמנים
כדי למדוד את ביצועי הזמן, נמנה את מספר מחזורי השעון שנדרשו במחזור אחד של האפליקציה בכל אחד משני המקרים.
ע”פ נתוני ה execution trace שקיבלנו מהTraceX, כפי שמובאים באיור מס’ 10, ניתן לראות שמחזור שלם של האפליקציה במקרה 1 ארך 1,024 ticks ומקרה 2 ארך 1,861 ticks.
שעון הCPU , הנו 200MHZ ,כלומר:
מחזור שלם במקרה 1 ארך 5.076 מילישניות
מחזור שלם במקרה 2 ארך 8.788 מילישניות
אגב, ה -RTOS , הנו כמובן ThreadX וזמן הcontext-switch (@200MHZ) הנו קצר באופן בולט, כ-0.35 מיקרו שניות!

מסקנות
השימוש באסטרטגיית “עדיפות-זהה” לקבוצת threads יכול להוות יתרון משמעותי בהשגת מערכת זמן אמת בעלת ביצועים ותפוקה גבוהים. כמובן שכלל זה אינו חד משמעי ויש לשקול שילוב של אסטרטגיות שונות בהתאם לצרכי המערכת.  ניתן לקבוע עדיפות ייחודית גבוהה
לthreads קריטיים ועדיפות זהה לקבוצת או קבוצות threads מסוימות.
ניתן גם לשלב את רעיון הpreemption-threshold כאשר לאחר ניסוי ותעייה נקבע את מיקום הסף שלו בנקודה אופטימאלית, שמחד תענה לצרכיי המערכת בתהליכים קריטיים בזמן, ומאידך תייעל את ניהול שאר התהליכים ע”י צמצום כמות המיתוגים.
כמובן ששימוש בכלים כמו הTraceX  יסייע בהבנה וניתוח של התנהגות המערכת וכוונון נכון להשגת ביצועים אופטימאליים.
*הכתבה נמסרה באדיבות צביקה אלמוג – סאייטסיס, כלי פיתוח בע”מ
נציגת Express Logic, ThreadX

תגובות סגורות