העיקרון הזה בעמוד התווך של הקיימוּת ב-Google Cloud Well-Architected Framework מספק המלצות לכתיבת תוכנה שמפחיתה את צריכת האנרגיה ואת העומס על השרת.
סקירה כללית של העקרונות
כשמפתחים אפליקציות בענן לפי השיטות המומלצות, אפשר לייעל את צריכת האנרגיה של משאבי תשתית הענן: AI, מחשוב, אחסון ורשת. בנוסף, אתם עוזרים להפחית את צריכת המים של מרכזי הנתונים ואת צריכת האנרגיה של מכשירי משתמשי הקצה כשהם ניגשים לאפליקציות שלכם.
כדי לפתח תוכנה חסכונית באנרגיה, צריך לשלב שיקולי קיימוּת לאורך כל מחזור החיים של התוכנה, החל מהתכנון והפיתוח ועד לפריסה, לתחזוקה ולארכוב. בספר האלקטרוני Build Software Sustainably של Google Cloud מוסבר בפירוט איך משתמשים ב-AI כדי לפתח תוכנות שמצמצמות את ההשפעה של עומסי העבודה בענן על הסביבה.
המלצות
ההמלצות בקטע הזה מקובצות לפי תחומי המיקוד הבאים:
- צמצום עבודת החישוב: העדיפו קוד קצר וממוקד שמבטל לוגיקה מיותרת ומונע חישובים מיותרים או עומס של תכונות.
- להשתמש באלגוריתמים ובמבני נתונים יעילים: בחרו אלגוריתמים יעילים מבחינת זמן וזיכרון, שמפחיתים את העומס על המעבד (CPU) ומצמצמים את השימוש בזיכרון.
- אופטימיזציה של פעולות המחשוב והנתונים: פיתוח במטרה להשתמש ביעילות בכל המשאבים הזמינים, כולל מעבד (CPU), זיכרון, קלט/פלט של דיסק ורשת. לדוגמה, כשמחליפים לולאות המתנה פעילה בלוגיקה מבוססת-אירועים, נמנעים מדגימה מיותרת.
- אופטימיזציה של ממשק המשתמש: כדי לצמצם את צריכת החשמל של מכשירי משתמשי הקצה, כדאי להשתמש באסטרטגיות כמו צמצום, דחיסה וטעינה מדורגת של תמונות ונכסים.
צמצום עבודת החישוב
כדי לכתוב תוכנה חסכונית באנרגיה, צריך לצמצם את כמות העבודה החישובית הכוללת שהאפליקציה מבצעת. כל הוראה מיותרת, לולאה עודפת ותכונה נוספת צורכות אנרגיה, זמן ומשאבים. כדי לפתח תוכנה שמבצעת חישובים מינימליים, כדאי להשתמש בהמלצות הבאות.
כתיבת קוד קצר וממוקד
כדי לכתוב קוד מינימלי שחיוני להשגת התוצאות הנדרשות, השתמשו בגישות הבאות:
- הימנעו מלוגיקה מיותרת ומעומס תכונות: כתבו קוד שמבצע רק את הפונקציות החיוניות. הימנעו מתכונות שמגדילות את התקורה החישובית ואת המורכבות, אבל לא מספקות ערך מדיד למשתמשים.
- Refactor: כדי לשפר את היעילות האנרגטית לאורך זמן, כדאי לבדוק את האפליקציות באופן קבוע כדי לזהות תכונות שלא בשימוש. צריך להסיר או לשנות את התכונות האלה בהתאם.
- הימנעו מפעולות מיותרות: אל תחשבו ערך או תפעילו פעולה עד שהתוצאה נדרשת. השתמשו בשיטות כמו הערכה עצלה, שמעכבת את החישובים עד שרכיב תלוי באפליקציה צריך את הפלט.
- תנו עדיפות לקריאוּת וליכולת השימוש החוזר בקוד: כתבו קוד קריא וניתן לשימוש חוזר. הגישה הזו מצמצמת את הכפילויות ופועלת לפי עיקרון ה-DRY (אל תחזרו על עצמכם), שיכול לעזור להפחית את פליטות הפחמן שנובעות מפיתוח ותחזוקה של תוכנות.
שימוש במטמון לקצה העורפי
שמירה במטמון בקצה העורפי מבטיחה שהאפליקציה לא תבצע את אותה פעולה שוב ושוב. שיעור גבוה של מציאות במטמון מוביל להפחתה כמעט לינארית בצריכת האנרגיה לכל בקשה. כדי להטמיע שמירה במטמון בקצה העורפי, אפשר להשתמש בשיטות הבאות:
- שמירת נתונים נפוצים במטמון: אחסון נתונים שניגשים אליהם לעיתים קרובות במיקום אחסון זמני עם ביצועים גבוהים. לדוגמה, אפשר להשתמש בשירות לשמירה במטמון בזיכרון כמו Memorystore. כשאפליקציה מאחזרת נתונים ממטמון, נפח השאילתות במסד הנתונים ופעולות הקלט/פלט בדיסק מצטמצם. כתוצאה מכך, העומס על מסדי הנתונים והשרתים בקצה העורפי פוחת.
- שמירת תגובות מה-API במטמון: כדי להימנע מקריאות מיותרות ויקרות לרשת, כדאי לשמור במטמון את התוצאות של בקשות API תכופות.
- תעדוף של שמירה במטמון בזיכרון: כדי למנוע פעולות קלט/פלט איטיות בדיסק ושאילתות מורכבות במסד הנתונים, כדאי לאחסן נתונים בזיכרון במהירות גבוהה (RAM).
- בוחרים אסטרטגיות מתאימות לכתיבה במטמון:
- אסטרטגיית הכתיבה דרך המטמון מבטיחה שהנתונים ייכתבו באופן סינכרוני למטמון וגם למאגר המתמיד. האסטרטגיה הזו מגדילה את הסבירות למציאה במטמון (cache hit), כך שהאחסון המתמיד מקבל פחות בקשות קריאה שצורכות הרבה אנרגיה.
- אסטרטגיית הכתיבה לאחור (write-behind) משפרת את הביצועים של אפליקציות שכוללות הרבה פעולות כתיבה. הנתונים נכתבים קודם במטמון, ומסד הנתונים מתעדכן באופן אסינכרוני מאוחר יותר. האסטרטגיה הזו מפחיתה את עומס הכתיבה המיידי במסדי נתונים איטיים יותר.
- שימוש במדיניות פינוי חכמה: כדי לשמור על מטמון קטן ויעיל. כדי להסיר נתונים ישנים או לא שימושיים ולמקסם את המקום הפנוי לנתונים שנדרשים לעיתים קרובות, השתמשו בכללי מדיניות כמו זמן חיים (TTL), הכי פחות בשימוש לאחרונה (LRU) והכי פחות בשימוש (LFU).
שימוש באלגוריתמים ובמבני נתונים יעילים
האלגוריתמים ומבני הנתונים שתבחרו יקבעו את מורכבות החישוב הגולמי של התוכנה. כשבוחרים אלגוריתמים ומבני נתונים מתאימים, מצמצמים את מספר מחזורי המעבד (CPU) ופעולות הזיכרון שנדרשים כדי להשלים משימה. פחות מחזורי מעבד ופעולות זיכרון מובילים לצריכת אנרגיה נמוכה יותר.
בחירת אלגוריתמים לסיבוכיות זמן אופטימלית
לתת עדיפות לאלגוריתמים שמשיגים את התוצאה הנדרשת בזמן הקצר ביותר. הגישה הזו עוזרת לצמצם את משך השימוש במשאבים. כדי לבחור אלגוריתמים שמשפרים את השימוש במשאבים, אפשר להשתמש בשיטות הבאות:
- התמקדו בהפחתת המורכבות: כדי להעריך את המורכבות, אל תסתכלו רק על מדדי זמן הריצה, אלא גם על המורכבות התיאורטית של האלגוריתם. לדוגמה, בהשוואה למיון בועות, מיון מיזוג מפחית באופן משמעותי את העומס החישובי ואת צריכת האנרגיה של מערכי נתונים גדולים.
- הימנעו מעבודה מיותרת: השתמשו בפונקציות מובנות שעברו אופטימיזציה בשפת התכנות או במסגרת שבחרתם. הפונקציות האלה מיושמות בדרך כלל בשפה ברמה נמוכה יותר וחסכונית יותר באנרגיה, כמו C או ++C, כך שהן מותאמות טוב יותר לחומרה הבסיסית בהשוואה לפונקציות בהתאמה אישית.
בחירת מבני נתונים יעילים
מבני הנתונים שתבחרו קובעים את המהירות שבה אפשר לאחזר, להוסיף או לעבד נתונים. המהירות הזו משפיעה על השימוש במעבד (CPU) ועל השימוש בזיכרון. כדי לבחור מבני נתונים יעילים, השתמשו בגישות הבאות:
- אופטימיזציה לחיפוש ולאחזור: לפעולות נפוצות כמו בדיקה אם פריט קיים או אחזור של ערך ספציפי, כדאי להשתמש במבני נתונים שמותאמים למהירות. לדוגמה, טבלאות גיבוב (hash maps) או קבוצות גיבוב (hash sets) מאפשרות חיפושים בזמן כמעט קבוע, וזו גישה חסכונית יותר באנרגיה מאשר חיפוש לינארי במערך.
- צמצום הזיכרון שבשימוש: מבני נתונים יעילים עוזרים לצמצם את הזיכרון הכולל שבשימוש באפליקציה. הפחתת הגישה לזיכרון והניהול שלו מובילה לצריכת חשמל נמוכה יותר. בנוסף, פרופיל זיכרון קטן יותר מאפשר לתהליכים לפעול בצורה יעילה יותר, וכך לדחות את שדרוגי המשאבים.
- שימוש במבנים ייעודיים: השתמשו במבני נתונים שנועדו לפתור בעיה מסוימת. לדוגמה, השתמשו במבנה נתונים מסוג trie לחיפוש מהיר של תחילת מחרוזת, והשתמשו בתור עדיפות כשאתם צריכים לגשת רק לערך הגבוה או הנמוך ביותר ביעילות.
אופטימיזציה של פעולות המחשוב והנתונים
כשמפתחים תוכנה, חשוב להתמקד בשימוש יעיל ופרופורציונלי במשאבים בכל סטאק התוכנות. התייחסו למעבד (CPU), לזיכרון, לדיסק ולרשת כאל משאבים מוגבלים ומשותפים. להבין ששימוש יעיל במשאבים מוביל להפחתה משמעותית בעלויות ובצריכת האנרגיה.
אופטימיזציה של ניצול המעבד וזמן חוסר הפעילות
כדי לצמצם את הזמן שבו המעבד (CPU) נמצא במצב פעיל וצורך אנרגיה בלי לבצע עבודה משמעותית, אפשר להשתמש בגישות הבאות:
- העדיפו לוגיקה מבוססת-אירועים על פני דגימה: החליפו לולאות עמוסות שצורכות הרבה משאבים או בדיקה קבועה (דגימה) בלוגיקה מבוססת-אירועים. ארכיטקטורה מבוססת-אירועים מבטיחה שרכיבי האפליקציה יפעלו רק כשהם מופעלים על ידי אירועים רלוונטיים. הגישה הזו מאפשרת עיבוד על פי דרישה, וכך אין צורך בסקרים שצורכים הרבה משאבים.
- מניעת תדירות גבוהה קבועה: כותבים קוד שלא מאלץ את המעבד לפעול כל הזמן בתדירות הגבוהה ביותר. כדי לצמצם את צריכת האנרגיה, מערכות שלא נמצאות בשימוש צריכות להיות מסוגלות להיכנס למצבי צריכת חשמל נמוכה או למצבי שינה.
- שימוש בעיבוד אסינכרוני: כדי למנוע נעילה של שרשורים בזמני המתנה, כדאי להשתמש בעיבוד אסינכרוני. הגישה הזו מפנה משאבים ומובילה לניצול גבוה יותר של המשאבים באופן כללי.
ניהול יעיל של הזיכרון ושל הקלט/פלט (I/O) בדיסק
שימוש לא יעיל בזיכרון ובדיסק מוביל לעיבוד מיותר ולצריכת חשמל מוגברת. כדי לנהל את הזיכרון ואת הקלט/פלט ביעילות, השתמשו בשיטות הבאות:
- ניהול זיכרון קפדני: פעולה יזומה לשחרור משאבי זיכרון שלא בשימוש. אל תשמרו אובייקטים גדולים בזיכרון לפרקי זמן ארוכים מהנדרש. הגישה הזו מונעת צווארי בקבוק בביצועים ומפחיתה את צריכת החשמל שנדרשת לגישה לזיכרון.
- אופטימיזציה של קלט/פלט בדיסק: מפחיתים את התדירות של אינטראקציות הקריאה והכתיבה של האפליקציה עם משאבי אחסון מתמידים. לדוגמה, אפשר להשתמש במאגר נתונים זמני (buffer) כדי לאחסן נתונים. כותבים את הנתונים באחסון מתמיד במרווחי זמן קבועים או כשהמאגר מגיע לגודל מסוים.
- פעולות באצווה: מאחדים פעולות קטנות ותכופות בדיסק לפעולות גדולות יותר באצווה. פעולה באצווה צורכת פחות אנרגיה מאשר הרבה עסקאות קטנות ונפרדות.
- שימוש בדחיסה: כדי לצמצם את כמות הנתונים שנכתבים בדיסקים או נקראים מהם, אפשר להשתמש בשיטות מתאימות לדחיסת נתונים. לדוגמה, כדי לדחוס נתונים שמאוחסנים ב-Cloud Storage, אתם יכולים להשתמש בהמרת קידוד שמבטלת דחיסה.
צמצום התנועה ברשת
משאבי הרשת צורכים הרבה אנרגיה במהלך פעולות של העברת נתונים. כדי לשפר את התקשורת ברשת, אפשר להשתמש בשיטות הבאות:
- צמצום גודל המטען הייעודי (payload): תכננו את ממשקי ה-API והאפליקציות כך שיעבירו רק את הנתונים שנדרשים לבקשה. הימנעו מאחזור או החזרה של מבני JSON או XML גדולים במקרים שבהם נדרשים רק כמה שדות. חשוב לוודא שמבני הנתונים שמוחזרים הם תמציתיים.
- צמצום מספר הנסיעות הלוך ושוב: כדי לצמצם את מספר הנסיעות הלוך ושוב ברשת שנדרשות להשלמת פעולת משתמש, השתמשו בפרוטוקולים חכמים יותר. לדוגמה, עדיף להשתמש ב-HTTP/3 על פני HTTP/1.1, לבחור ב-GraphQL על פני REST, להשתמש בפרוטוקולים בינאריים ולאחד קריאות ל-API. כשמפחיתים את נפח הקריאות ברשת, מפחיתים את צריכת האנרגיה גם בשרתים וגם במכשירי משתמשי הקצה.
הטמעת אופטימיזציה של ממשק המשתמש
אופטימיזציה של ממשק המשתמש מצמצמת את הנתונים שמשתמשי הקצה צריכים להוריד ולעבד, וכך עוזרת להפחית את העומס על המשאבים של מכשירי משתמשי הקצה.
צמצום הקוד והנכסים
כשמשתמשי קצה צריכים להוריד ולעבד משאבים קטנים יותר עם מבנה יעיל יותר, המכשירים שלהם צורכים פחות חשמל. כדי לצמצם את נפח ההורדה ואת עומס העיבוד במכשירי משתמשי הקצה, כדאי להשתמש בשיטות הבאות:
- צמצום ודחיסה: בקובצי JavaScript, CSS ו-HTML, הסירו תווים מיותרים כמו רווחים לבנים והערות באמצעות כלי צמצום מתאימים. חשוב לוודא שקבצים כמו תמונות דחוסים ועברו אופטימיזציה. אתם יכולים להפוך את המזעור והדחיסה של נכסי האינטרנט לאוטומטיים באמצעות צינור עיבוד נתונים של CI/CD.
- טעינה מדורגת: טוענים תמונות, סרטונים ונכסים לא קריטיים רק כשהם נחוצים בפועל, למשל כשהרכיבים האלה נגללים אל אזור התצוגה של דף אינטרנט. הגישה הזו מצמצמת את נפח העברת הנתונים הראשונית ואת עומס העיבוד במכשירי משתמשי הקצה.
- חבילות JavaScript קטנות יותר: הסירו קוד שלא בשימוש מחבילות ה-JavaScript באמצעות כלים מודרניים לאיסוף מודולים וטכניקות כמו tree shaking. הגישה הזו מאפשרת ליצור קבצים קטנים יותר שנטענים מהר יותר וצורכים פחות משאבי שרת.
- שמירה במטמון של הדפדפן: משתמשים בכותרות HTTP לשמירה במטמון כדי להורות לדפדפן של המשתמש לאחסן נכסים סטטיים באופן מקומי. שמירה במטמון של הדפדפן עוזרת למנוע הורדות חוזרות ותנועה מיותרת ברשת בביקורים הבאים.
תעדוף של חוויית משתמש (UX) קלילה
לעיצוב של ממשק המשתמש יכולה להיות השפעה משמעותית על המורכבות החישובית של עיבוד תוכן בקצה הקדמי. כדי ליצור ממשקי קצה קדמי המספקים חוויית שימוש קלה, השתמשו בשיטות הבאות:
- עיבוד יעיל: הימנעו משינויים תכופים ב-Document Object Model (DOM) שדורשים משאבים רבים. כתבו קוד שמצמצם את מורכבות העיבוד ומבטל עיבוד מחדש מיותר.
- תבניות עיצוב קלות: במקרים המתאימים, עדיף להשתמש באתרים סטטיים או ב-Progressive Web Apps (PWA). אתרים ואפליקציות כאלה נטענים מהר יותר ודורשים פחות משאבי שרת.
- נגישות וביצועים: אתרים רספונסיביים שנטענים מהר הם בדרך כלל נגישים יותר ופחות מזיקים לסביבה. עיצוב אופטימלי ונקי מצמצם את המשאבים שנדרשים לעיבוד התוכן. אתרים שעברו אופטימיזציה לביצועים ולמהירות יכולים לעזור להגדיל את ההכנסות. לפי מחקר של Deloitte ו-Google, Milliseconds Make Millions, שיפור של 0.1 שניות (100 אלפיות השנייה) במהירות האתר מוביל לעלייה של 8.4% בהמרות באתרים קמעונאיים ולעלייה של 9.2% בערך ההזמנה הממוצע.