פרויקט Java Valhalla

1. סקירה כללית

במאמר זה נבחן את Project Valhalla - הסיבות ההיסטוריות לכך, מצב הפיתוח הנוכחי ומה הוא מביא לשולחן עבור מפתח Java היומיומי לאחר שחרורו.

2. מוטיבציה וסיבות לפרויקט ואללה

באחת משיחותיו אמר בריאן גץ, אדריכל שפות ג'אווה באורקל, כי אחד המניעים העיקריים לפרויקט ואלהאלה הוא הרצון להתאים את שפת Java וזמן הריצה לחומרה מודרנית. כאשר נוצרה שפת ג'אווה (לפני כ- 25 שנה בעת כתיבת שורות אלה), העלות של אחזור זיכרון וניתוח חשבוני הייתה זהה בערך.

כיום זה השתנה, כאשר פעולות אחזור הזיכרון היו יקרות פי 200 ל -1,000 מפעולות חשבון. מבחינת עיצוב השפה, פירוש הדבר כי התכווצויות המובילות לאחזור מצביעים משפיעות לרעה על הביצועים הכוללים.

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

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

3. סוגי ערכים

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

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

הקוד ומתווה הזיכרון המתאים של רגיל נְקוּדָה הכיתה תהיה:

נקודת הכיתה הסופית {final int x; סופי int y; }

מצד שני, הקוד ופריסת הזיכרון המתאימה מסוג ערך נְקוּדָה יהיה:

מחלקת ערך נקודה {int x; int y}

זה מאפשר ל- JVM לשטוח סוגי ערכים למערכים ואובייקטים, כמו גם לסוגי ערך אחרים. בתרשים הבא אנו מציגים את ההשפעה השלילית של התכווצויות כאשר אנו משתמשים ב- נְקוּדָה מחלקה במערך:

מצד שני, כאן אנו רואים את מבנה הזיכרון המתאים מסוג הערך נְקוּדָה[]:

זה גם מאפשר ל- JVM להעביר סוגי ערכים בערימה במקום שיהיה עליהם להקצות אותם בערימה. בסופו של דבר, המשמעות היא שאנו מקבלים אגרגטים של נתונים שיש להם התנהגות זמן ריצה הדומה לפרימיטיבים של Java, כגון int אוֹ לָצוּף.

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

  • חפצים מהירים יותר
  • פרימיטיבים המוגדרים על ידי המשתמש

כדובדבן נוסף על העוגה, אנו יכולים להשתמש בסוגי ערך כסוגים גנריים ללא אגרוף. זה מוביל אותנו ישירות לתכונה הגדולה האחרת של פרויקט ואללה: גנריות מתמחות.

4. גנריות מתמחות

כשאנחנו רוצים לייצר פרימיטיביות לשפה, אנו משתמשים כיום בסוגי תיבות, כגון מספר שלם ל int אוֹ לָצוּף ל לָצוּף. אגרוף זה יוצר שכבה נוספת של כיוון, ובכך מביך מלכתחילה את מטרת השימוש בפרימיטיבים לשיפור ביצועים.

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

אז גנריות מתמחות הן מאמץ להסיר את הצרכים של אותם "פריצות". במקום זאת, שפת Java שואפת לאפשר טיפוסים גנריים לכל דבר: הפניות לאובייקטים, פרימיטיביים, סוגי ערכים ואולי אפילו בָּטֵל.

5. מסקנה

הצצנו על השינויים ש- Project Valhalla יביא לשפת Java. שתיים מהמטרות העיקריות הן ביצועים משופרים והפשטות פחות דולפות.

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

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

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

אנו יכולים למצוא מידע נוסף אודות פרויקט ואללה בדף הפרויקט המתאים וב- JEP:

  • פרויקט ואלהאלה
  • JEP 169: אובייקטים ערכיים
  • JEP 218: גנריות על פני סוגים פרימיטיביים