העיקרון הזה, שנכלל בעמודה 'קיימות' בGoogle Cloud מסגרת Well-Architected Framework, כולל המלצות לכתיבת תוכנה שממזערת את צריכת האנרגיה ואת העומס על השרת.
סקירה כללית של העקרונות
כשפועלים לפי השיטות המומלצות לפיתוח אפליקציות בענן, מייעלים את האנרגיה שמשמשת את משאבי התשתית בענן: AI, מחשוב, אחסון ורשת. אתם גם עוזרים להפחית את כמות המים שנדרשת למרכזי הנתונים ואת האנרגיה שמכשירים של משתמשי קצה צורכים כשהם ניגשים לאפליקציות שלכם.
כדי ליצור תוכנה חסכונית באנרגיה, צריך לשלב שיקולים של קיימות לאורך כל מחזור החיים של התוכנה, החל משלבי התכנון והפיתוח ועד לשלבי הפריסה, התחזוקה והארכיון. בספר הדיגיטלי Build Software Sustainably (פיתוח תוכנה באופן בר-קיימא) מוסבר בפירוט איך להשתמש ב-AI כדי לפתח תוכנה שמצמצמת את ההשפעה הסביבתית של עומסי עבודה בענן. Google Cloud
המלצות
ההמלצות בקטע הזה מחולקות לתחומי ההתמקדות הבאים:
- מצמצמים את העבודה החישובית: מומלץ להשתמש בקוד יעיל וממוקד שמבטל לוגיקה מיותרת ומונע חישובים מיותרים או תכונות מנופחות.
- שימוש באלגוריתמים ובמבני נתונים יעילים: בחירה באלגוריתמים יעילים מבחינת זמן וזיכרון, שמפחיתים את עומס המעבד וממזערים את השימוש בזיכרון.
- אופטימיזציה של פעולות חישוב ונתונים: פיתוח במטרה להשתמש ביעילות בכל המשאבים הזמינים, כולל CPU, זיכרון, קלט/פלט של דיסק ורשת. לדוגמה, כשמחליפים לולאות עסוקות בלוגיקה מבוססת-אירועים, נמנעים מסקרים מיותרים.
- הטמעת אופטימיזציה של חזית האתר (frontend): כדי לצמצם את צריכת החשמל של מכשירי משתמשי הקצה, כדאי להשתמש באסטרטגיות כמו מזעור, דחיסה וטעינה עצלה של תמונות ונכסים.
צמצום העבודה החישובית
כדי לכתוב תוכנה חסכונית באנרגיה, צריך לצמצם את כמות העבודה החישובית הכוללת שהאפליקציה מבצעת. כל הוראה מיותרת, כל לולאה עודפת וכל תכונה נוספת צורכות אנרגיה, זמן ומשאבים. כדי ליצור תוכנה שמבצעת חישובים מינימליים, אפשר להיעזר בהמלצות הבאות.
כתיבת קוד יעיל וממוקד
כדי לכתוב קוד מינימלי שנדרש להשגת התוצאות הרצויות, אפשר להשתמש בגישות הבאות:
- הסרת לוגיקה מיותרת וניפוח של תכונות: כותבים קוד שמבצע רק את הפונקציות החיוניות. מומלץ להימנע מתכונות שמגדילות את התקורה החישובית והמורכבות, אבל לא מספקות ערך מדיד למשתמשים.
- ארגון מחדש של הקוד (Refactoring): כדי לשפר את היעילות האנרגטית לאורך זמן, מומלץ לבצע ביקורת על האפליקציות באופן קבוע כדי לזהות תכונות שלא נמצאות בשימוש. עליך לפעול להסרה או לשינוי של התכונות האלה בהתאם לצורך.
- הימנעות מפעולות מיותרות: אל תחשבו ערך או תפעילו פעולה עד שתזדקקו לתוצאה. שימוש בטכניקות כמו הערכה עצלה, שדוחות חישובים עד שרכיב תלוי באפליקציה צריך את הפלט.
- מתעדפים את הקריאות והשימוש החוזר בקוד: כותבים קוד שקל לקרוא ולהשתמש בו שוב. הגישה הזו מצמצמת כפילויות ופועלת לפי העיקרון של 'אל תחזור על עצמך' (DRY), שיכול לעזור להפחית את פליטת הפחמן מפיתוח ותחזוקה של תוכנה.
שימוש במטמון של ה-Backend
השימוש במטמון בשרת העורפי מבטיח שאפליקציה לא תבצע את אותה פעולה שוב ושוב. יחס גבוה של פגיעות במטמון מוביל לצמצום כמעט לינארי בצריכת האנרגיה לכל בקשה. כדי להטמיע שמירת נתונים במטמון בשרת, אפשר להשתמש בטכניקות הבאות:
- שמירת נתונים שמשתמשים בהם לעיתים קרובות במטמון: אחסון נתונים שמשתמשים בהם לעיתים קרובות במיקום אחסון זמני עם ביצועים גבוהים. לדוגמה, אפשר להשתמש בשירות שמירה במטמון בזיכרון כמו Memorystore. כשיישום מאחזר נתונים ממטמון, נפח השאילתות במסד הנתונים ופעולות הקלט/פלט בדיסק מצטמצם. כתוצאה מכך, העומס על מסדי הנתונים והשרתים בקצה העורפי פוחת.
- שמירת תשובות API במטמון: כדי להימנע מקריאות מיותרות ויקרות לרשת, כדאי לשמור במטמון את התוצאות של בקשות API תכופות.
- תעדוף של שמירת נתונים במטמון בזיכרון: כדי למנוע פעולות קלט/פלט איטיות בדיסק ושליחת שאילתות מורכבות למסד הנתונים, כדאי לאחסן נתונים בזיכרון מהיר (RAM).
- בוחרים אסטרטגיות מתאימות לכתיבה במטמון:
- האסטרטגיה של כתיבה דרך המטמון מבטיחה שהנתונים ייכתבו באופן סינכרוני למטמון וגם למאגר הקבוע. האסטרטגיה הזו מגדילה את הסיכוי למציאת נתונים במטמון, ולכן מאגר הנתונים הקבוע מקבל פחות בקשות קריאה שדורשות הרבה אנרגיה.
- אסטרטגיית הכתיבה חזרה (write-behind) משפרת את הביצועים של אפליקציות עם פעולות כתיבה רבות. הנתונים נכתבים קודם למטמון, ומסד הנתונים מתעדכן באופן אסינכרוני מאוחר יותר. השיטה הזו מפחיתה את עומס הכתיבה המיידי במסדי נתונים איטיים יותר.
- שימוש במדיניות חכמה של פינוי נתונים מהמטמון: כדי לשמור על מטמון רזה ויעיל. כדי להסיר נתונים לא עדכניים או נתונים עם שימוש מועט ולמקסם את הנפח שזמין לנתונים שמתבצעות לגביהם בקשות בתדירות גבוהה, אפשר להשתמש במדיניות כמו זמן חיים (TTL), שימוש אחרון (LRU) ושימוש בתדירות נמוכה (LFU).
שימוש באלגוריתמים ובמבני נתונים יעילים
האלגוריתמים ומבני הנתונים שתבחרו יקבעו את מורכבות החישוב הגולמית של התוכנה. כשבוחרים אלגוריתמים ומבני נתונים מתאימים, מצמצמים את מספר מחזורי המעבד ואת פעולות הזיכרון שנדרשות להשלמת משימה. פחות מחזורי CPU ופעולות זיכרון מובילים לצריכת אנרגיה נמוכה יותר.
בחירת אלגוריתמים למורכבות זמן אופטימלית
כדאי לתת עדיפות לאלגוריתמים שמשיגים את התוצאה הנדרשת בזמן הקצר ביותר. הגישה הזו עוזרת לצמצם את משך השימוש במשאבים. כדי לבחור אלגוריתמים שמבצעים אופטימיזציה של השימוש במשאבים, אפשר להיעזר בשיטות הבאות:
- התמקדות בהפחתת המורכבות: כדי להעריך את המורכבות, צריך להסתכל מעבר למדדי זמן הריצה ולשקול את המורכבות התיאורטית של האלגוריתם. לדוגמה, בהשוואה למיון בועות, מיון מיזוג מפחית באופן משמעותי את עומס החישוב ואת צריכת האנרגיה עבור מערכי נתונים גדולים.
- הימנעות מעבודה מיותרת: מומלץ להשתמש בפונקציות מובנות ומותאמות בשפת התכנות או במסגרת שבחרתם. הפונקציות האלה מיושמות בדרך כלל בשפה ברמה נמוכה יותר וחסכונית יותר באנרגיה, כמו C או C++, ולכן הן עוברות אופטימיזציה טובה יותר לחומרה הבסיסית בהשוואה לפונקציות עם קוד מותאם אישית.
בחירת מבני נתונים ליעילות
מבני הנתונים שבוחרים קובעים את המהירות שבה אפשר לאחזר, להוסיף או לעבד נתונים. המהירות הזו משפיעה על השימוש ב-CPU ובזיכרון. כדי לבחור מבני נתונים יעילים, אפשר להשתמש בגישות הבאות:
- אופטימיזציה לחיפוש ולאחזור: לפעולות נפוצות כמו בדיקה אם פריט קיים או אחזור ערך ספציפי, מומלץ להשתמש במבני נתונים שעברו אופטימיזציה למהירות. לדוגמה, מפות גיבוב או קבוצות גיבוב מאפשרות חיפושים בזמן כמעט קבוע, וזו גישה חסכונית יותר באנרגיה מאשר חיפוש לינארי במערך.
- מזעור הזיכרון שבשימוש: מבני נתונים יעילים עוזרים לצמצם את הזיכרון הכולל שבשימוש של אפליקציה. צריכת החשמל נמוכה יותר כי יש פחות גישה לזיכרון ופחות ניהול של הזיכרון. בנוסף, פרופיל זיכרון רזה יותר מאפשר לתהליכים לפעול בצורה יעילה יותר, וכך לדחות את השדרוגים של המשאבים.
- שימוש במבנים ייעודיים: שימוש במבני נתונים שנוצרו במיוחד לפתרון בעיה מסוימת. לדוגמה, אפשר להשתמש במבנה נתונים מסוג trie לחיפוש מהיר של תחילת מחרוזת, ולהשתמש בתור עדיפויות כשצריך לגשת רק לערך הכי גבוה או הכי נמוך בצורה יעילה.
אופטימיזציה של פעולות חישוב ונתונים
כשמפתחים תוכנה, חשוב להתמקד בשימוש יעיל ופרופורציונלי במשאבים בכל סטאק התוכנות. התייחסו למעבד (CPU), לזיכרון, לדיסק ולרשת כאל משאבים מוגבלים ומשותפים. הבנה שלפיה שימוש יעיל במשאבים מוביל להפחתה משמעותית בעלויות ובצריכת האנרגיה.
אופטימיזציה של ניצול המעבד וזמן ההמתנה
כדי לצמצם את הזמן שבו המעבד נמצא במצב פעיל שבו הוא צורך אנרגיה בלי לבצע עבודה משמעותית, אפשר להיעזר בשיטות הבאות:
- עדיף להשתמש בלוגיקה מבוססת-אירועים במקום בסקרים: כדאי להחליף לולאות עמוסות או בדיקות קבועות (סקרים) בלוגיקה מבוססת-אירועים. ארכיטקטורה מבוססת-אירועים מבטיחה שהרכיבים של האפליקציה יפעלו רק כשהם מופעלים על ידי אירועים רלוונטיים. הגישה הזו מאפשרת עיבוד על פי דרישה, וכך לא צריך לבצע סקרים שדורשים הרבה משאבים.
- מניעת תדירות גבוהה קבועה: כותבים קוד שלא מכריח את המעבד לפעול כל הזמן בתדירות הגבוהה ביותר שלו. כדי לצמצם את צריכת האנרגיה, מערכות במצב לא פעיל צריכות להיות מסוגלות לעבור למצבי צריכת חשמל נמוכה או למצבי שינה.
- שימוש בעיבוד אסינכרוני: כדי למנוע נעילה של שרשורים בזמן ההמתנה במצב סרק, צריך להשתמש בעיבוד אסינכרוני. הגישה הזו מפנה משאבים ומובילה לניצול גבוה יותר של המשאבים באופן כללי.
ניהול יעיל של הזיכרון והקלט/פלט בדיסק
שימוש לא יעיל בזיכרון ובדיסק מוביל לעיבוד מיותר ולצריכת חשמל מוגברת. כדי לנהל את הזיכרון ואת קלט/פלט בצורה יעילה, אפשר להשתמש בטכניקות הבאות:
- ניהול זיכרון מחמיר: פעולה לשחרור יזום של משאבי זיכרון שלא נמצאים בשימוש. מומלץ להימנע מהחזקת אובייקטים גדולים בזיכרון לתקופות ארוכות מהנדרש. הגישה הזו מונעת צווארי בקבוק בביצועים ומפחיתה את צריכת החשמל לגישה לזיכרון.
- אופטימיזציה של קלט/פלט בדיסק: צמצום התדירות של אינטראקציות הקריאה והכתיבה של האפליקציה עם משאבי אחסון מתמיד. לדוגמה, אפשר להשתמש במאגר זיכרון ביניים כדי לאחסן נתונים. לכתוב את הנתונים לאחסון מתמיד במרווחים קבועים או כשהמאגר מגיע לגודל מסוים.
- פעולות באצווה: כדאי לאחד פעולות קטנות בדיסק שמתבצעות לעיתים קרובות לכמה פעולות גדולות באצווה. פעולה בקבוצה צורכת פחות אנרגיה מאשר הרבה עסקאות קטנות ונפרדות.
- שימוש בדחיסה: כדי להקטין את כמות הנתונים שנכתבים לדיסקים או נקראים מהם, אפשר להשתמש בטכניקות מתאימות לדחיסת נתונים. לדוגמה, כדי לדחוס נתונים שמאוחסנים ב-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 App (PWA). האתרים והאפליקציות האלה נטענים מהר יותר ודורשים פחות משאבי שרת.
- נגישות וביצועים: אתרים רספונסיביים שנטענים במהירות הם לרוב יותר בני קיימא ונגישים. עיצוב אופטימלי ונקי מאפשר לצמצם את המשאבים שנצרכים בזמן רינדור התוכן. אתרים שעברו אופטימיזציה לשיפור הביצועים והמהירות יכולים לעזור להגדיל את ההכנסות. על פי מחקר של Deloitte ו-Google, Milliseconds Make Millions, שיפור של 0.1 שניות (100 אלפיות השנייה) במהירות האתר מוביל לעלייה של 8.4% במספר ההמרות באתרים קמעונאיים ולעלייה של 9.2% בערך ההזמנה הממוצע.