תכנות יעיל וביצועים, בJS (בפרט)


  • ניהול

    הערה: לדיונים אנא פנו לאשכול בקטגוריית התכנות

    החלטתי לפתוח פה שרשור שבכל הודעה אתן דוגמא על שיפור ביצועים ויעילות.

    אני עושה זאת בעיקר בשביל עצמי, אז יכול להיות שאדלג על נושאים פשוטים יותר ושלא תהיה פרופורציה בין יעילות רעיון למשנהו.

    ישנם עקרונות יעילות שנכונים עבור כל שפת תכנות - כולם לעניין זה זהות ממש,
    אבל יש הרבה שתלויים בשפות וגם במהדרים, בדרך כלל באלו אין כללי ברזל כי הם עלולים להשתנות ויש מידי פעם לבצע השוואות ובדיקות ביצועים בכלים מתאימים.

    בגלל שJS היא שפה ללא מפרש רשמי אלא רק מסמך תקינה לא מחייב כל כך (ואף הוא עיקרו בא להתנהגות ופחות למימוש), היא בהרבה דברים שונה מדפדפן לדפדפן לפי סוגי המימושים השונים.
    (ישנם כמה מנועי פירוש לJS, המפורסמים הם V8 של כרום ונוד, Rhino של פיירפוקס, וChakra של IE.
    החברות הגדולות מאחורי אלו, יותר ויותר משתפים פעולה בהרבה נושאים ומתקרבים זה לזה, ולכן אני מאמין שהפערים במימוש מצטמצמים).


  • ניהול

    המשך להקדמה:
    כל נושא הביצועים בJS ברמות העדינות שנדבר פה הם לא רלוונטיים לדפדפן אלא לסביבת שרת (בה כל עיכוב CPU הוא יקר). מכיון שסביבות צד שרת כמעט ואין חוץ מnode אז הדגש שלנו יהיה על V8 שזה המנוע של כרום ונוד.
    המקורות שלי מגוונים: מאמרים, פורומים, וגם טסטים אישיים. קצת קשה למצוא כלי בדיקה קל ומדוייק. אני משתמש בעיקר בו http://jsbench.github.io/.

    טוב נתחיל עם מערכים ואובייקטים.

    א. מערך באופן כללי מהיר מאובייקט, למשל:

    1. אתחול זול (זיכרון) ומהיר יותר ([] VS {}).
    2. גישה לפי אינדקס מהירה יותר במערך, מאשר גישה לאיבר של אובייקט (arr[1] VS obj.key או obj[key]).
    3. בחיפוש לפי ערך, במערך יש indexOf שמהר בהרבה מלולאה.
    4. דחיפת איברים חדשים מהירה יותר במערך (טסט).

    ב. פרקטיקות לשימוש נכון במערכים:

    • אם אפשר לאתחל מייד עם ערכים, מהר יותר מאשר הכנסה בהמשך.
    • כשידוע האורך מראש, יש לאתחל את המערך עם Array(length) (טסט).
    • push איטי מגישה ישירות לאינדקס הבא (טסט, דיון בסטאק).
    • להימנע מקריאת תאים ריקים (empty). לכן גם לא כדאי למחוק תאים עם delete אם זה לא הכרחי, null יותר טוב (טסט).
    • חיפוש:
      • לבדוק אם קיים, arr.includes. באם לא נתמך (ES5) אז arr.indexOf(x) > -1.
      • למצוא לפי קריטריון, find. אם הקיריטריון הוא ערך כל שהוא, כדאי לבנות מילון מאובייקט שמפתחותיו הם הערכים.
      • מיקום בהינתן הערך עצמו (במקרה של אובייקט אז המופע), indexOf. בשביל ספירת הופעות במערך, לולאה של indexOf מהירה מfilter ואז length.
    • לולאת for עובדת כמו טיל במערך (אבל יותר לאט מindexOf!), יש גם לשים את המאפיין length במשתנה (קשינג) ולא לפנות אליו בכל איטרציה. forEach נח יותר ובריא לקריאות - אבל במקומות קריטיים השתמשו תמיד בfor.
    • מנועי JS מבצעים אופטימיזציה למערכים בעלי אותו סוג (ניחוש הסוג מבוצע ע"י האתחול או ההשמה הראשונה). כלומר אם יש לכם מערך שכולו מספרים, עדיף לא לשים שם אובייקט. אם מדובר במספרים שלמים ישנה אופטימיזציה גדולה אף יותר, ועדיך לא "לשבור" את זה עם איבר עם מספר בעל שבר.

  • ניהול

    פוסט זה נמחק!

 

בא תתחבר לדף היומי!