אובייקטים ניתנים להעברה – במהירות הבזק

ב-Chrome 13 הושקה האפשרות לשלוח ArrayBuffer לעובד אינטרנט או ממנו באמצעות אלגוריתם שנקרא שכפול מובנה. כך ה-API של postMessage() יכול לקבל הודעות שלא היו רק מחרוזות, אלא סוגים מורכבים כמו File, Blob, ArrayBuffer ואובייקטים של JSON. השכפול המובנה נתמך גם בגרסאות מאוחרות יותר של Firefox.

מהר יותר הוא טוב יותר

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

באובייקטים שניתנים להעברה, הנתונים מועברים מהקשר אחד לאחר. מדובר בעותק אפס, שמשפר משמעותית את הביצועים של שליחת נתונים לעובד. אם אתם מגיעים מעולם C/C++ , אפשר להתייחס לזה כאל קובץ עזר. עם זאת, בניגוד להעברה לאחר הפניה, ה 'גרסה' מהקשר הקריאה לא תהיה זמינה יותר אחרי ההעברה להקשר החדש. לדוגמה, כשמעבירים ArrayBuffer מהאפליקציה הראשית ל-Worker, האפליקציה ArrayBuffer המקורית נמחקת ואי אפשר יותר להשתמש בה. התוכן שלו מועבר (פשוטו כמשמעו) להקשר של העובד.

יש גרסה חדשה של postMessage() שמאפשרת לשחק עם פריטים שניתנים להעברה:

worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);

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

הדגמה של השוואה לשוק

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

ההדגמה שולחת 32MB ArrayBuffer לעובד ובחזרה באמצעות postMessage(). אם הדפדפן שלך לא תומך בפעולות ניתנות להעברה, הדוגמה תחזור לשכפול מובנה. ממוצע 5 הפעלות בדפדפנים שונים, שקיבלתי:

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

ב-MacBook Pro/10.6.8/2.53GHz/Intel Core 2 Duo, FF היה המהיר ביותר באמצעות שכפול מובנה. בממוצע, שליחת 32MB ArrayBuffer לעובד נמשכת 302 אלפיות השנייה ושליחה בחזרה לשרשור הראשי (RRT – זמן הלוך ושוב). אם משווים את זה עם פריטים שניתנים להעברה, אותה בדיקה נמשכה 6.6 אלפיות השנייה. זה שיפור משמעותי בביצועים!

המהירויות האלה מאפשרות להעביר בקלות מרקמים/הודעות רשת מסיביים של WebGL בין Worker לאפליקציה הראשית.

זיהוי תכונות

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

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
if (ab.byteLength) {
    alert('Transferables are not supported in your browser!');
} else {
    // Transferables are supported.
}

תמיכה: נכון לעכשיו, Chrome בגרסה 17 ומעלה, Firefox, Opera, Safari ו-IE10 ומעלה

עודכן (13-12-2011): קטע הקוד שמציג חתימת webkitPostMessage() שונה עבור חלון ועובד. תאריך עדכון (3 בנובמבר 2016): הוסרו קידומות ספקים וקטעי קוד מעודכנים