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

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

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

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

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

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

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

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

הדגמה של בנצ'מרק

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

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

תרשים השוואה בין יצירת עותקים מובְנים לבין העברת אובייקטים

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

מהירויות כאלה מאפשרות להעביר בצורה חלקה בין Worker לאפליקציה הראשית טקסטורות או רשתות ענקיות של WebGL.

זיהוי תכונות

זיהוי התכונה הזו קצת מסובך. ההמלצה שלי היא לשלוח 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 וב-IE מגרסה 10 ואילך.

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