CPU Pinning: מדוע השירות מתנדנד תחת עומס שיא
כל עוד השירות אינו בעומס, זמן התגובה יציב — וזה מרדים את הדעת. בשיא, אותן בקשות בדיוק מעובדות לעיתים מהר ולעיתים לאט באופן ניכר, אף שהעומס הממוצע על המעבדים רחוק מהמגבלה. בדרך כלל הבעיה אינה במחסור בכוח עיבוד, אלא באופן שבו הליבות מוקצות בין תהליכוני העבודה.
מתזמן המשימות אינו יודע אילו תהליכונים עובדים יחד, ומעביר אותם בחופשיות בין ליבות. כל העברה היא אובדן מטמון מחומם והרס הלוקאליות של הזיכרון, ואיתם גם את יכולת החיזוי של זמן התגובה.
ככל שיש יותר תהליכונים מקבילים על אותה ליבה, כך ההחלפות תכופות יותר: פיזור השהיות התגובה גדל, והנפילות תחת עומס נהיות מורגשות למשתמש הרבה לפני מיצוי המשאבים.
CPU Pinning ובידוד ליבות מסירים את אי-הוודאות הזו ברמת מערכת ההפעלה. תהליכונים קריטיים מוצמדים לליבות ייעודיות ואינם נודדים עוד, ואילו תהליכי שירות מועברים לליבות האחרות — המתזמן מפסיק להתנגש בין עומס היישום למשימות רקע. הליבה נשארת מחוממת, וזמן העיבוד מפסיק להיות תלוי במה שקרה עוד במכונה באותו רגע.
את זה בודקים במדידות, לא בדיבורים: פיזור השהיות התגובה תחת שיא לפני ואחרי ההצמדה. בהמשך נפרט כיצד לבחור ליבות, מה בדיוק לבודד וכיצד לוודא שהאי-יציבות נעלמה ולא עברה למקום אחר.
מה נותן הצמדת ליבות: תגובה יציבה ויכולת חיזוי
מתזמן הליבה כברירת מחדל מאזן עומס ומעביר תהליכונים בין מעבדים כדי שהעומס יהיה אחיד. עבור שירותים עם דרישות קשיחות לזמן תגובה זה הופך לרעידות בהשהיה: התהליכון נוחת פעם על ליבה «חמה» ופעם על ליבה שזה עתה התפנתה, מאבד מטמון חם וממתין לתורו.
הצמדת ליבות מצמידה את תהליכוני העבודה ואת מטפלי הפסיקות שלהם לקבוצה קבועה — הנדידות פוסקות, ופיזור זמן העיבוד יורד ממילישניות לעשרות מיקרושניות.
השכבה השנייה — בידוד: ליבות ייעודיות מוצאות מהמתזמן הכללי באמצעות פרמטרי אתחול, מגבלות של קבוצות בקרה ופיזור תורי פסיקות. שירותי מערכת, בנייות רקע ועומס זר מפסיקים לחלוק עם השירות את המטמון ואת מחזורי השעון.
בליבת Linux הדבר נעשה באמצעים סטנדרטיים, ולכן התצורה ניתנת לשחזור ומועברת בין שרתים באותו תפקיד בלי טלאים קנייניים.
לא משתנה ההשהיה הממוצעת, אלא הזנב שלה. בהצמדה ובידוד, קוונטילים מסדר גבוה מפסיקים לקפוץ תחת שיא: זמן עיבוד הבקשה באחוזון ה-95 וה-99 מתקרב לחציון, והתנהגות השירות ניתנת לחיזוי.
בדיוק התרחיש הזה — תחרות על משאב — יוצר את מחלקת הכשלים הקלאסית: פורמלית יש כוח עיבוד פנוי, אך חלק מהבקשות נכנסות לפסק זמן בגלל זמן מעבד «גזול».
מכאן האפקט המדיד. הקיבולת מתוכננת לפי מדדים יציבים, ולא עם מרווח «לרעש»; נעלמת הצורך להחזיק רפליקות מיותרות רק כדי להחליק קפיצות. מדידות סטנד מתחילות להתאים לפרודקשן — הפחתת ההשהיה מאושרת באופן חוזר, לא חד-פעמי.
סכמות הצמדה: ליבות ייעודיות, משותפות והיברידיות
בחירת סכמת הצמדה היא פשרה בין יכולת החיזוי של ההשהיות לניצול החומרה. על אותו מארח חיים בדרך כלל גם שירות רגיש לזמן תגובה וגם משימות רגילות, ולכן חשוב לא «להצמיד הכול», אלא לפזר בין קבוצות: מה מקבל ליבה מובטחת, מה לחלוק במאגר משותף, ומה להשאיר כעתודה.
| וריאנט | מתי מתאים | במה מוגבל |
|---|---|---|
| ליבות ייעודיות | עיבוד עם סף השהיה קשיח: תהליכוני קלט/פלט, טלמטריה, מתזמני משימות | מספר הליבות קבוע וניתן במלואו; כשהשירות אינו פעיל, המשאב אינו מועבר למשימות אחרות |
| מאגר ליבות משותף | שירותים עם עומס משתנה, חישובי אצווה, תורי רקע | המתזמן מעביר תהליכים בין ליבות, תהליכוני שירות מתחרים — פיזור ההשהיות גדל |
| סכמה היברידית | מארח משולב: חלק מהעומס קריטי, חלק לא | התצורה מורכבת יותר; בשינוי מספר הליבות או תפקידי הצומת יש לחשב מחדש את הפריסה |
| הצמדה רכה | דרוש יציבות בלי גבולות קשיחים: העדפה לפי ליבות, לא איסור | אין ערובות: במחסור במשאבים המתזמן נוטש את ההעדפה |
בידוד מתהליכי שירות
ההצמדה לבדה, בלי בידוד, נותנת מעט: אם אל הליבה הייעודית עדיין מגיעים מטפלי פסיקות, טיימרים ותהליכוני שירות מערכת, ה-jitter חוזר.
לכן משלימים את מסכת ההצמדה בהחרגת ליבות מהתזמון הכללי ובהצמדה מפורשת של פסיקות לקבוצת שירות — אז התהליכון הקריטי מקבל פיזור צפוי של עשרות מיקרושניות במקום פרצי מילישניות.
הקריטריון המעשי לבחירה הוא פיזור ההשהיות הנמדד תחת עומס שיא, ולא עיקרון נוקשה. סדר סביר: להתחיל בהצמדה רכה, להפיק פרופיל, ורק אם היסטוגרמת ההשהיות אינה עומדת בדרישה — לעבור לליבות ייעודיות ולפריסה היברידית.
כיצד אנו מיישמים CPU Pinning: ממדידה ועד מסירה
רצף העבודות אינו תלוי בפרופיל העומס: תחילה מתעדים את התנהגות המערכת בפועל, אחר כך מתכננים את הסכמה, ורק לבסוף משנים את התצורה. כל כוונון בלי מדידת בסיס הוא ניחוש: לא ברור מה בדיוק גרם לאפקט ומה יישבר במהדורה הבאה. להלן הסדר שבו אנו מובילים CPU Pinning מהסטנד הראשון ועד מסירת התמיכה.
- מדידת ההתנהגות הנוכחית. מפיקים פרופיל השהיות תחת התרחיש היעד: התפלגות זמן התגובה, האחוזון ה-99, משך החריגות הגרועות ביותר, תדירות החלפות ההקשר והנדידות של משימות בין ליבות. התוצאה — חתך בסיס, שאיתו משווים כל דבר בהמשך.
- תכנון סכמת הקצאת הליבות. קובעים אילו ליבות מוקדשות ליישום, ואילו נשארות למערכת, לעיבוד פסיקות ולתהליכוני שירות. מתחשבים בטופולוגיית NUMA ובמטמונים משותפים כדי שתהליכונים לא יתחרו על אותו זיכרון.
- הגדרת הבידוד. מזינים פרמטרי בידוד ליבות ומסכות זיקה, מעבירים מטפלי פסיקות לליבות ייעודיות, ומכבים מצבי חיסכון באנרגיה שמוסיפים פיזור. את השינויים מנסחים כתצורה, ולא כתיקונים ידניים במכונה חיה.
- בדיקה תחת עומס. מריצים את פרופיל היעד במצב שיא ומשולב: בודקים שפיזור ההשהיות נשמר עם גידול במספר החיבורים, ומוודאים שתהליכי מערכת אינם רעבים על הליבות שנותרו.
- בדיקת נסיגה. מוודאים שאת הסכמה ניתן להסיר בהחזרת התצורה בלי לבנות מחדש את הצומת, ושההידרדרות בעת הסרת הבידוד צפויה — זו תעודת ביטוח לזמן תקלות.
- מסירת התמיכה. מוסרים את סכמת ההקצאה, התצורות, המדדים וספי ההפעלה, נוהל לשינויים במתזמן והוראה קצרה למשמרת תורנית.
כל שלב נסגר בארטיפקט ובמדידה, ולא באמירה בעל-פה «נהיה טוב יותר» — לכן האפקט של הכוונון נראה במספרים, לא בתחושות.
מה נשאר לצוות שלכם לאחר הגדרת הבידוד
הגדרת הבידוד אינה מסתיימת בעובדה ש«העברנו את העומס לליבות ייעודיות», אלא בערכה שאיתה הצוות שלכם ממשיך לעבוד בעצמו. כל מה שאנו משנים בצמתים מתועד בקבצים במאגר שלכם: תצורות, סכמות, נהלים וסדרי בדיקה.
ערכה כזו נחוצה משום שהקצאת הליבות נשברת בשקט — שירות חדש על הצומת או עדכון מערכת מזיזים את ההצמדות, ופיזור ההשהיות חוזר לקדמותו.
- תצורות ליבות. קבצי עבודה של פרמטרי אתחול והגדרות שירות לכל מחלקת צמתים, עם הערות: אילו ערכים קריטיים, מה יקרה אם יתקנו אותם, ואילו שורות אסור לגעת בהן.
- סכמת הקצאת משאבים. מפת הצמדות: כמה ליבות הוקצו למערכת המבודדת, כמה נשארו למערכת ולמשימות שירות, וכיצד זה מפוזר לפי צמתים ותפקידים ספציפיים.
- נוהל תחזוקה. סדר עבודות מתוכננות: מה מופעל מחדש תוך כדי תנועה, מה דורש הוצאת הצומת מפעילות, וכיצד לוודא שאחרי עדכון ההצמדות במקומן.
- תיעוד הצומת. דרכון לכל צומת: תפקיד, הרכב הקבוצה המבודדת, שירותים מקושרים, בעלים מצד הצוות שלכם ונקודת פנייה בעת חריגה.
- סדר בדיקת שינויים. רשימת בקרה לפני פריסה: נטילת מדידות בסיס, השוואה לתקן, קריטריון שלפיו שינוי מוחזר בלי דיונים.
- ערכת מדידות ותבניות. סקריפטים לנטילת מדדי השהיות וערכי תקן לכל צומת — לפיהם רואים חריגה בלי השתתפות שלנו.
הערכה קשורה למאגרי התצורה ולמערכת בקרת הגרסאות שלכם, ולא לרשומות הפנימיות שלנו. בעוד חצי שנה מהנדס חדש יתמחה בקבצים האלה מהר יותר מאשר בהתכתבות.
מקרה בוחן: כיצד הסרנו ירידות תגובה בצומת עמוס
מה היה לפני השינויים
צומת עמוס החזיק שירות עם דרישות קשיחות לזמן תגובה, ולצידו, על אותן ליבות, חיו משימות רקע: בנייה מחדש של אינדקסים, שכפול, איסוף מדדים תקופתי. המתזמן העביר תהליכונים בחופשיות בין ליבות, המטמון התקרר, ותחת שיא פיזור ההשהיות התרחב למאות מיקרושניות.
המדדים הממוצעים נראו סביר — הבעיה הסתתרה בזנב ההתפלגות: קריאות נדירות, איטיות פי כמה מהרגיל, לא עמדו במגבלת הזמן ונכנסו לניסיונות חוזרים.
מה שינו
מטפלים קריטיים הוצמדו לקבוצת ליבות ייעודית, תהליכי שירות — לקבוצה נפרדת, והנדידות של תהליכונים ביניהן הושבתו. מליבות מבודדות הוסרו עיבוד הפסיקות ומשימות הליבה התקופתיות, והועברו לחלק השירות.
בצומת עם Kubernetes הפרידו טווחי ליבות לעומסי עבודה ולעומסי מערכת, כדי שפודים עם משימות רקע לא ייפלו פיזית על הליבות המוצמדות.
מה השתנה לפי המדידות
- פיזור ההשהיות של המטפלים הצטמצם ממאות מיקרושניות לעשרות, והאחוזון התשעים ותשעה הפסיק לחרוג מההתפלגות העיקרית.
- בגידול של פי עשרה בעומס, הזנב גדל בעשרות אחוזים במקום גידול פי כמה — ההתנהגות תחת שיא הפכה צפויה.
- חלק הבקשות שלא עמדו במגבלת הזמן קטן בסדר גודל, וניסיונות חוזרים הפסיקו להוסיף עומס.
- בנייה מחדש של אינדקס מתבצעת במקביל לעיבוד בקשות בלי ירידה בתגובה.
במה שונה בידוד ליבות מתעדוף תהליכים?
תעדוף תהליכים משנה רק את סדר הגישה למעבד: מתזמן Linux נותן למשימה משקל גדול יותר, מציב אותה בתור מוקדם יותר ודוחק אותה החוצה לעתים רחוקות יותר. אבל התחרות על הליבה נשארת — תחת עומס התהליכון עדיין חולק אותה עם שכנים, עובר בין ליבות ומאפס מטמון. בדיוק ההחלפות והנדידות האלה יוצרות את פיזור התגובה שתופסים אחר כך כשיאי השהיה נדירים.
בידוד ליבות מסיר לא את סדר התור, אלא את התחרות עצמה. הליבות מוצאות מהמאגר הכללי של המתזמן, משימות זרות אינן נכנסות לשם, והתהליכון הקריטי מקבל את כל המשבצת הייעודית. החלפות הקשר כמעט אינן נותרות, הנדידה אסורה, ולכן רעידות ההשהיה מפסיקות להיות תלויות במה עסוקה שאר המכונה.
השוואת הגישות תלויה במחלקת המשימה, ולא בשאלה «מה טוב יותר». עדיפויות — חלוקת משאבים רכה: הן זולות, הפיכות ומתאימות לשירותים שבהם חשוב לחלק את המעבד בצורה הוגנת תחת זרם בקשות משותף.
בידוד — צעד מבני: הוא נותן יכולת חיזוי לטווח ארוך, אבל לוקח ליבות משאר התהליכים ודורש חישוב מרווח כוח עיבוד.
בפועל אנו מיישמים את שני המפלסים יחד: באמצעות עדיפויות מפרידים בין משימות רקע למשימות משתמש, ובאמצעות בידוד מגנים על מטפלים קריטיים — רשתיים, הצפנה, תהליכוני חילופי מידע עם מערכות חיצוניות.
הליבות הייעודיות מתועדות בתצורת המכונה כקוד, כדי שחלוקת המשאבים לא תאבד בעת הפעלה מחדש ותועבר לצומת חדש בלי עריכה ידנית.
ספקות טכניים נפוצים לפני יישום
לפני היישום צוותים שואלים את אותן שאלות: אם שירותים שכנים ייפגעו, מה לעשות עם חלוקת עומס שכבר נפרסה, וכיצד להחזיר שינויים. אנו מפרקים כל אחת מהן — זהו החלק העיקרי של העבודה, ולא ההצמדה עצמה של ליבות לתהליכים.
בידוד מוציא חלק מהליבות מהמתזמן הכללי, ולכן מתכננים אותו עם מרווח: מפיקים פרופיל עומס, מצמידים קבוצה אחת בכל פעם ועוקבים אחר ההשהיות אצל השכנים. הפריסה נשמרת באופן הצהרתי תחת בקרת גרסאות — החזרה מחזירה את מצב המערכת הקודם.
האם לא ניקח כוח עיבוד משירותים שכנים?
בידוד מקצה ליבות מחדש, לא מוסיף אותן. מחשבים כמה נשאר למאגר הכללי, שומרים מרווח לשיאים ומפעילים הצמדה קבוצה-אחת-בכל-פעם תוך בקרת התורים אצל השכנים.
אצלנו כבר נפרסה חלוקת עומס — האם נצטרך לעשות הכול מחדש?
לא. ההצמדה מוגדרת נקודתית עבור תהליכים עם דרישה לתגובה צפויה, דרך קבוצות בקרה סטנדרטיות של המתזמן. שאר השירותים ממשיכים לעבוד לפי הסכמה הנוכחית.
כיצד מוחזרים שינויים אם יהיה גרוע יותר?
פרמטרי הפריסה מנוהלים בגרסאות: החזרה היא החזרת הערכה הקודמת ויישום מחדש. התהליכים חוזרים למתזמן הכללי, וטריגרים להחזרה מוגדרים מראש — גידול בהשהיות, ירידה בתפוקה.
מה כלול בתמיכה לאחר הכוונון?
משאירים נראות: השהיות לפי כל ליבה מוצמדת, התראות על חריגה מהסף, הוראות לבעלי השירותים. את הפריסה בוחנים מחדש כשהעומס גדל — אחרת הבידוד מאבד את האפקט בהדרגה.
נדון במשימה: נחזור עם הערכה ותוכנית עבודה
כדי לחזור עם הערכת עבודה, ולא עם שיקולים כלליים, אנחנו צריכים נתוני מקור על הצומת — טופולוגיית חומרה, פרופיל עומס והתנהגות נוכחית של המתזמן. להלן רשימה של מה שכדאי לשלוח מראש; אם חלק מהנתונים חסר, נאסוף אותו בעצמנו בסטנד שלכם, אבל זה מאריך את הכנת ההערכה.
- פלט
lscpuעם טופולוגיה מלאה ופירוט לפי צומתי NUMA — ממנו רואים אילו ליבות חולקות מטמון ואפיק; - רשימת תהליכים ושירותים שזקוקים לתקציב השהיה קשיח, עם מדדים נוכחיים: חציון, p99, מקסימום ושיעור חריגות;
- פריסה נוכחית של פסיקות ותורי רשת לפי ליבות — מה הוצמד ידנית, מה נשאר ל-
irqbalance; - דרישה ל-jitter שיורי והידרדרות מותרת תחת עומס שיא;
- תצורת וירטואליזציה או מכולות: בידוד ליבות במארח, העברה לאורח, מגבלות מתזמן;
- חלון עבודה, מותרות אתחולים מחדש וקיום צומת חלופי למעבר;
- גישה לסטנד שמשחזר את פרופיל העומס הקרבי — אחרת אי אפשר להשוות מספרים לפני/אחרי.
לפי הנתונים האלה נחשב כמה ליבות עוברות לבידוד, אילו משימות מעבירים למערכת הכללית, היכן יידרש חלוקה מחדש של פסיקות והאם נדרשות מדיניות נפרדות לאורחים. ההערכה מגיעה יחד עם תוכנית יישום: סדר השינויים, נקודות החזרה, מדדי קבלה בכל שלב.
תארו את המשימה וצרפו את מה שיש — נחזור עם הערכת עבודה ותוכנית יישום לפרופיל העומס שלכם.







