כה ציטט Donald Knuth:
... Premature optimization is the root of all evil...
אמר, וכולם האזינו. ובצדק. יש לאמירה הזאת הרבה פירושים, אחד מהם (שאני אוהב) אומר שיש לבצע אופטימיזציה רק לקוד שמהווה צוואר בקבוק ובפירוש אין לנסות ליעל קוד שאינו כזה. האמירה והפירושים מגובים בד"כ בטענה שיעול של קוד הופך אותו ללא קריא, לא ניתן לתחזוקה ורגיש לשינויים אחרים בתוכנה. בד"כ מתקשרים לאופטימיצזיה כזאת וויתורים על בדיקות של חוקיות קלט, טיפול במקרי קצה וכד'.
הגיוני, לא? אני חושב שכן, אבל מכיוון שונה. לדעתי פשוט אין לנו מושג.
ראשית יש להפריד בין כמה סוגי יעולים - יעול אלגוריתמי (כמו שימוש ב-quicksort מול bubble sort) ויעול "טקטי". יעול אלגוריתמי תמיד היה ויהיה חשוב, ובעולם שבו כמויות המידע המעובד רק גדלות, שיפור אלגוריתמי אף הופך למשמעותי יותר.
הבעיה שלי היא עם יעול טקטי. הנה למשל דוגמא: כאשר אני צריך להפוך מספר לספרה שש עשרונית, מה רץ מהר יותר:
Option1:
switch (digit) {
case 0: return '0'
case 1: return '1'
....
case 10: return 'A'
....
}
Option 2:
return digitToHex[digit];
התשובה שגיליתי, היא שתלוי. מאוד תלוי. תלוי בשפת התכנות, באופטימיזציות של הקומפיילר, ו/או של ה-runtime (בשפות כמו java/c#). במקרה שלי, גיליתי למשל שדווקא האפשרות השניה, שנראית על פניו מהירה יותר, היא דווקא האיטית (בכ-50%), כי ב-java בודקים את גבולות המערך בכל גישה (היום כבר יש אופטימיזציות של ה-runtime שמבטלות אותן) ואילו ה-switch מתורגם על ידי ה-runtime לגישה יחידה למערך, בלי שום בדיקות.
אבל לא צריך להרחיק עד לשפות שהן interpreted. כבר ב-c++ אין להרבה אנשים מושג איך הקוד באמת מתנהג. כמות ה-features שמציע המעבד, וסוגי האופטימיזציות שמציע ה-compiler (למשל סידור מחדש של הפקודות כדי לנצל את מלא כוח החישוב של המעבד). נסיון לבצע אופטימיזציה לקוד שטופל היטב על ידי ה-compiler דורש הכרות טובה עם ה-assembly ויכולות מעקב טובה אחרי הקוד הנוצר. או האם, למשל, כדאי לשלב ב-c++ קטעי קוד ב-assembly? הכנסה של קוד כזה יכולה לשבור את האופטימיזציות שה-compiler היה עושה בקוד ה-c++ ובסופו של דבר לגרום לאפקט הפוך. איך אפשר לדעת? אי אפשר, צריך להבין היטב מה עושים ו/או לנסות.
דוגמא אחרת היא ההתייחסות ל-cache של המעבד והמחשב. כמה אנשים יודעים כמה cache מסוג L1 או L2 יש להם במחשב? ואת הפרמטרים הפנימיים שלו? עבודה נכונה של ה-cache יכולה לתת שיפורים מדהימים (במקרה אחד ראיתי שיפור של 90% בביצועים של קוד שהיה צוואר בקבוק באפליקציה) ועבודה שגויה יכולה לגרום להאטה משמעותית ביותר.
אז מי בכלל יכול להתחיל ולעשות אופטימיזציה ל"סתם קטע קוד שנראה איטי" אך אינו צוואר הבקבוק האמיתי של האפליקציה?
ומה קורה כאשר אנחנו מגיעים לנקדה שאין ברירה וצריך לייעל? מה ה-skills set שדרוש כדי ליעל קוד? האם מתכנת java יכול/צריך להכיר את c/c++/שפת aseembly/את מבנה המחשב ומערכת ההפעלה/תורת הקומפילציה? בעולם שבו אנחנו הולכים וכותבים יותר ויותר קוד בשפות כמו python/ruby/groove וכד' האם אפשר למצוא בכלל אנשים שמכירים את המחשב ב-low level? והאם לימוד java כשפת לימוד ראשונה לא פוגע בהבנה כזו? והאם הידע שלומדים באוניברסיטה לא הופך ל-obsolete לאחר כמה שנים? כמי שלמד את ה-assembly של pdp11 (אני חושב שבטכניון כבר עברו ל-80x86) ואת המבנה של הפנטיום, ראיתי שאני צריך לקרוא לא מעט חומר בעצמי כדי לעמוד בקצב הטכנולוגי.
אז זהו גורלה של האופטימיזציה היום, חיה כמעט נכחדת...
הוספת תגובה על "אופטימיזציה - שורש כל רע או סתם נושא מיותר"
נא להתחבר כדי להגיב.
התחברות או הרשמה