שרשורי WebAssembly מוכנים לניסיון ב-Chrome 70

תמיכה בשרשור של WebAssembly נוספה ל-Chrome 70 במסגרת תקופת ניסיון למקורות.

Alex Danilo

WebAssembly‏ (Wasm) מאפשרת ליצור קובצי הידור של קוד שנכתב ב-C++ ובשפות אחרות, כדי להריץ אותו באינטרנט. אחת מהתכונות השימושיות מאוד של אפליקציות מקוריות היא היכולת להשתמש בשרשור (thread) – רכיב פשוט לחישוב מקבילי. רוב המפתחים ב-C וב-C++‎ מכירים את pthreads, שהוא ממשק API סטנדרטי לניהול חוטים באפליקציה.

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

במהדורה 70 של Chrome יש תמיכה בשרשור ל-WebAssembly, ואנחנו ממליצים למפתחים שמעוניינים להתחיל להשתמש בהם ולשלוח לנו משוב.

שרשורים? מה לגבי Workers?

דפדפנים תומכים במקביליות באמצעות Web Workers מאז 2012 ב-Chrome 4. למעשה, נהוג להשתמש במונחים כמו 'בשרשור הראשי' וכו'. עם זאת, משימות Web Workers לא משתפות בינן נתונים שניתנים לשינוי, אלא מסתמכות על העברת הודעות לצורך תקשורת. למעשה, Chrome מקצה מנוע V8 חדש לכל אחד מהם (שנקראים 'בידוד'). ב-isolates לא משותפים קוד מקודד או אובייקטים של JavaScript, ולכן אי אפשר לשתף בהם נתונים שניתנים לשינוי, כמו pthreads.

לעומת זאת, שרשורים של WebAssembly הם שרשורים שיכולים לחלוק את אותו זיכרון Wasm. האחסון הבסיסי של הזיכרון המשותף מתבצע באמצעות SharedArrayBuffer, רכיב פרימיטיבי של JavaScript שמאפשר לשתף בו-זמנית את התוכן של ArrayBuffer יחיד בין עובדים. כל חוט WebAssembly פועל ב-Web Worker, אבל הזיכרון המשותף של Wasm מאפשר להם לפעול באופן דומה לפלטפורמות מקוריות. כלומר, האפליקציות שמשתמשות בשרשורי Wasm אחראיות לניהול הגישה לזיכרון המשותף, כמו בכל אפליקציה רגילה עם שרשורים. יש הרבה ספריות קוד קיימות שנכתבו ב-C או ב-C++‎ שמשתמשות ב-pthreads, ואפשר לקמפל אותן ל-Wasm ולהריץ אותן במצב תהליכי אמיתי, שמאפשר ליותר ליבות לעבוד על אותם נתונים בו-זמנית.

דוגמה פשוטה

הנה דוגמה לתוכנית פשוטה ב-C‏‎ שמשתמשת בשרשור.

#include <pthread.h>
#include <stdio.h>

// Calculate Fibonacci numbers shared function
int fibonacci(int iterations) {
    int     val = 1;
    int     last = 0;

    if (iterations == 0) {
        return 0;
    }
    for (int i = 1; i < iterations; i++) {
        int     seq;

        seq = val + last;
        last = val;
        val = seq;
    }
    return val;
}
// Start function for the background thread
void *bg_func(void *arg) {
    int     *iter = (void *)arg;

    *iter = fibonacci(*iter);
    return arg;
}
// Foreground thread and main entry point
int main(int argc, char *argv[]) {
    int         fg_val = 54;
    int         bg_val = 42;
    pthread_t   bg_thread;

    // Create the background thread
    if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) {
        perror("Thread create failed");
        return 1;
    }
    // Calculate on the foreground thread
    fg_val = fibonacci(fg_val);
    // Wait for background thread to finish
    if (pthread_join(bg_thread, NULL)) {
        perror("Thread join failed");
        return 2;
    }
    // Show the result from background and foreground threads
    printf("Fib(42) is %d, Fib(6 * 9) is %d\n", bg_val, fg_val);

    return 0;
}

הקוד מתחיל בפונקציה main() שמצהירה על שני משתנים fg_val ו-bg_val. יש גם פונקציה בשם fibonacci(), שתי השרשורים בדוגמה הזו יפעילו אותה. הפונקציה main() יוצרת שרשור רקע באמצעות pthread_create(), שתפקידו לחשב את הערך של רצף המספרים של פיבונאצ'י שתואם לערך של המשתנה bg_val. בינתיים, הפונקציה main() שפועלת בשרשור בחזית מחשבת את הערך עבור המשתנה fg_val. כשתהליך ה-thread ברקע מסתיים, התוצאות מודפסות.

הידור לתמיכה בשרשור

קודם כול, צריך להתקין את emscripten SDK, רצוי בגרסה 1.38.11 ואילך. כדי לבנות את הקוד לדוגמה שלנו עם הפעלת שרשורים להרצה בדפדפן, צריך להעביר כמה דגלים נוספים למהדר emscripten emcc. שורת הפקודה שלנו נראית כך:

emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c

הארגומנט -s USE_PTHREADS=1 בשורת הפקודה מפעיל תמיכה בשרשור למודול WebAssembly המהדר, והארגומנט -s PTHREAD_POOL_SIZE=2 מורה למהדר ליצור מאגר של שני (2) חוטים.

כשהתוכנית מופעלת, מתבצע טעינה של מודול WebAssembly, יצירת Web Worker לכל אחד מהשרשראות בבריכת השרשורים, שיתוף המודול עם כל אחד מהעובדים (במקרה הזה יש 2 עובדים), והם ישמשו בכל פעם שתתבצע קריאה ל-pthread_create(). כל עובד מייצר את מודול ה-Wasm עם אותו זיכרון, מה שמאפשר לו לשתף פעולה. השינויים החדשים ביותר ב-V8 בגרסה 7.0 משתפים את הקוד המקורי המהדר של מודולי Wasm שמועברים בין עובדים, וכך מאפשרים להתאים אפליקציות גדולות מאוד לעבודה עם הרבה עובדים. חשוב לוודא שגודל מאגר השרשור שווה למספר המקסימלי של השרשור שהאפליקציה צריכה, אחרת יצירת השרשור עשויה להיכשל. במקביל, אם מאגר השרשורים גדול מדי, אתם עלולים ליצור עובדי אינטרנט מיותרים, שלא יעשו דבר מלבד שימוש בזיכרון.

איך לנסות את זה

הדרך המהירה ביותר לבדוק את מודול WebAssembly היא להפעיל את התמיכה בשרשורי WebAssembly הניסיוניים ב-Chrome 70 ואילך. עוברים לכתובת ה-URL about://flags בדפדפן, כמו שמוצג בהמשך:

הדף של התכונות הניסיוניות של Chrome

בשלב הבא, מאתרים את ההגדרה הניסיונית של WebAssembly בשרשורים שנראית כך:

הגדרת שרשורי WebAssembly

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

ההגדרה של שרשורי WebAssembly מופעלת

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

<!DOCTYPE html>
<html>
  <title>Threads test</title>
  <body>
    <script src="test.js"></script>
  </body>
</html>

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

פלט המסוף מתוכנית fibonacci

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

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

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

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

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

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

נשמח לקבל ממך משוב

שרשראות של WebAssembly הן רכיב פרימיטיבי חדש ושימושי מאוד להעברת אפליקציות לאינטרנט. עכשיו אפשר להריץ בסביבת WebAssembly אפליקציות וספריות ב-C וב-C++‎ שדורשות תמיכה ב-pthreads.

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