העיקרון הזה, שנכלל בעמודה 'קיימות' בGoogle Cloud מסגרת Well-Architected Framework, מספק המלצות לכתיבת תוכנה שממזערת את צריכת האנרגיה ואת העומס על השרת.
סקירה כללית של העקרונות
כשפועלים לפי שיטות מומלצות לפיתוח אפליקציות בענן, מייעלים את האנרגיה שמשאבי התשתית בענן צורכים: AI, מחשוב, אחסון ורשת. בנוסף, עוזרים לצמצם את כמות המים שנדרשת למרכזי הנתונים ואת האנרגיה שמכשירי משתמשי הקצה צורכים כשהם ניגשים לאפליקציות שלכם.
כדי ליצור תוכנה חסכונית באנרגיה, צריך לשלב שיקולים של קיימות לאורך מחזור החיים של התוכנה, החל משלב התכנון והפיתוח ועד לשלב הפריסה, התחזוקה והארכוב. לקבלת הנחיות מפורטות לגבי שימוש ב-AI כדי ליצור תוכנה שממזערת את ההשפעה הסביבתית של עומסי עבודה בענן, אפשר לעיין ב Google Cloud ספר הדיגיטלי, Build Software Sustainably (פיתוח תוכנה באופן בר-קיימא).
המלצות
ההמלצות בקטע הזה מחולקות לתחומי ההתמקדות הבאים:
- מצמצמים את העבודה החישובית: מומלץ להשתמש בקוד יעיל וממוקד שמבטל לוגיקה מיותרת ומונע חישובים מיותרים או נפח מיותר של תכונות.
- שימוש באלגוריתמים ובמבני נתונים יעילים: בחירה באלגוריתמים יעילים מבחינת זמן וזיכרון, שמפחיתים את עומס המעבד וממזערים את השימוש בזיכרון.
- אופטימיזציה של פעולות חישוב ונתונים: פיתוח במטרה להשתמש ביעילות בכל המשאבים הזמינים, כולל CPU, זיכרון, קלט/פלט של דיסק ורשת. לדוגמה, כשמחליפים לולאות עסוקות בלוגיקה מבוססת-אירועים, נמנעים מסקרים מיותרים.
- הטמעת אופטימיזציה של חזית האתר (frontend): כדי לצמצם את צריכת החשמל של מכשירי משתמשי הקצה, כדאי להשתמש באסטרטגיות כמו מזעור, דחיסה וטעינה עצלה של תמונות ונכסים.
מזעור העבודה החישובית
כדי לכתוב תוכנה חסכונית באנרגיה, צריך לצמצם את כמות העבודה החישובית הכוללת שהאפליקציה מבצעת. כל הוראה מיותרת, כל לולאה כפולה וכל תכונה נוספת צורכות אנרגיה, זמן ומשאבים. כדי ליצור תוכנה שמבצעת חישובים מינימליים, אפשר להיעזר בהמלצות הבאות.
כתיבת קוד יעיל וממוקד
כדי לכתוב קוד מינימלי שנדרש להשגת התוצאות הרצויות, אפשר להשתמש בגישות הבאות:
- מבטלים לוגיקה מיותרת וריבוי תכונות: כותבים קוד שמבצע רק את הפונקציות החיוניות. נמנעים מתכונות שמגדילות את התקורה החישובית והמורכבות, אבל לא מספקות ערך מדיד למשתמשים.
- ארגון מחדש של הקוד: כדי לשפר את היעילות האנרגטית לאורך זמן, מומלץ לבצע ביקורת על האפליקציות באופן קבוע כדי לזהות תכונות שלא נעשה בהן שימוש. עליך לפעול להסרה או לשינוי של התכונות האלה בהתאם לצורך.
- הימנעות מפעולות מיותרות: אל תחשבו ערך או תפעילו פעולה עד שתזדקקו לתוצאה. שימוש בטכניקות כמו הערכה עצלה, שדוחה חישובים עד שרכיב תלוי באפליקציה צריך את הפלט.
- מתעדפים את הקריאות והשימוש החוזר בקוד: כותבים קוד שקל לקרוא ושאפשר להשתמש בו שוב. הגישה הזו מצמצמת את הכפילות ופועלת לפי העיקרון של'אל תחזור על עצמך' (DRY), שיכול לעזור להפחית את פליטת הפחמן מפיתוח ותחזוקה של תוכנה.
שימוש במטמון של השרת
שמירה במטמון של ה-Backend מוודאת שהאפליקציה לא מבצעת את אותה פעולה שוב ושוב. יחס גבוה של פגיעות במטמון מוביל לצמצום כמעט לינארי בצריכת האנרגיה לכל בקשה. כדי להטמיע שמירה במטמון של ה-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% בערך ההזמנה הממוצע.