Въведение в споделената памет в JavaScript
Споделена памет е усъвършенствана функция на JavaScript, че нишките (едновременно изпълнени части от процеса) могат да се използват. Споделяне на паметта означава няма да има проблеми с предаването на актуализирани данни между нишките и всички нишки могат да имат достъп и да актуализират същите данни в споделената памет.
Не звучи ли прекрасно? Е, почти. В тази публикация ще видим как да използвате споделена памет в JavaScript и как да решите дали това е, което наистина искате да направите.
Предимства и недостатъци на споделената памет
Ние използваме уеб работници да се създайте нишки в JavaScript. APIът Web Workers ни позволява да създаваме работни потоци, с които да се използва изпълнява код във фонов режим така, че основната нишка е свободна да продължи изпълнението си, евентуално да обработва събития на потребителския интерфейс, като гарантира, че не се блокира UI.
Работни конци тече едновременно с главната нишка и една с друга. Такова едновременно изпълнение на различни части от дадена задача спестява време. Завършваш по-бързо, но има и свой собствен набор от проблеми.
Уверете се, че всяка нишка получава необходимите ресурси и своевременно комуникира помежду си е задача сама по себе си, когато злополука може да доведе до изненадващ резултат. Или ако една нишка променя данните, а друга я чете по същото време, какво мислите, че другата нишка ще види? Актуализираните или старите данни?
Въпреки това, уеб работниците не са толкова лесни за завинтване. По време на комуникацията им чрез използване на съобщения, данните, които изпращат един на друг, са не оригинал, а копие, което означава, че не го правят дял същите данни. Те предават копия на данни един на друг когато е необходимо.
Но споделянето е грижовно, а многобройните нишки също може да се наложи да гледат едни и същи данни едновременно и да ги променят. Така, споделянето на забрани е голямо не-не. Това е мястото, където SharedArrayBuffer
обектът влиза в картината. Ще ни позволи споделяте двоични данни между няколко нишки.
Най- SharedArrayBuffer
обект
Вместо да предаваме копията на данните между нишките, ние предава копия на SharedArrayBuffer
обект. А SharedArrayBuffer
обект точки към паметта, където се съхраняват данните.
Така че, дори когато копията на SharedArrayBuffer
преминават между нишките, те всички ще продължават да сочат към една и съща памет където се съхраняват оригиналните данни. Така нишките могат преглед и актуализиране на данните в същата памет.
Уеб работници без споделена памет
За да видим как уеб работникът работи без споделена памет, ние създайте нишка на работника и предайте някои данни към него.
Най- index.html
файлът съдържа основен сценарий вътре , както можете да видите по-долу:
const w = нов работник ('worker.js'); var n = 9; w.postMessage (п);
Най- worker.js
файлът носи работен сценарий:
onmessage = (e) => console.group ('[worker]'); console.log ("Данните, получени от основната нишка:% i ', e.data); console.groupEnd ();
Използвайки горния код, получаваме следното изход в конзолата:
[работник] Данни, получени от основната нишка: 9
Можете да прочетете гореспоменатата ми публикация в уеб работници за пълното обяснение на кода на горепосочените фрагменти.
Засега имайте предвид, че данните са изпратени напред и назад между нишките използвайки postMessage ()
метод. Данните са получени от другата страна на. \ t съобщение
събитие, като стойността на събитието данни
Имот.
Сега, ако ние промените данните ще се показва ли актуализиран в края на получаването? Да видим:
const w = нов работник ('worker.js'); var n = 9; w.postMessage (п); п = 1;
Както се очакваше, данни не са актуализирани:
[работник] Данни, получени от основната нишка: 9
Защо би било така? е просто клонинг, изпратен на работника от основния скрипт.
Уеб работници с споделена памет
Сега ще го направим използвай SharedArrayBuffer
обект в същия пример. Можем да създадем ново SharedArrayBuffer
например използвайки нов
ключова дума. Конструкторът приема един параметър; а стойност на дължината в байтове, задаване на размера на буфера.
const w = нов работник ('worker.js'); buff = new SharedArrayBuffer (1); var arr = нов Int8Array (buff); / * настройка на данни * / arr [0] = 9; / * изпращане на буфер (копие) на работник * / w.postMessage (buff);
Обърнете внимание, че a SharedArrayBuffer
обект представлява само общата памет. Да се вижте и променете двоичните данни, трябва да използваме подходяща структура от данни (a TypedArray
или a DataView
обект).
В index.html
файл по-горе, нов SharedArrayBuffer
е създаден само с една байт дължина. След това ново Int8Array
, което е един вид TypedArray
предмети задайте данните “9” в предоставеното байтово пространство.
onmessage = (e) => var arr = нов Int8Array (e.data); console.group ( "[работник]); console.log ("Данните, получени от основната нишка:% i ', arr [0]); console.groupEnd ();
Int8Array
също се използва в работника, за да прегледайте данните в буфера.
Най- очакваната стойност се появява в конзолата от нишката на работника, което е точно това, което искахме:
[работник] Данни, получени от основната нишка: 9
Сега, нека актуализирайте данните в основната нишка да се види дали промяната е отразена в работника.
const w = нов работник ('worker.js'), buff = new SharedArrayBuffer (1); var arr = нов Int8Array (buff); / * настройка на данни * / arr [0] = 9; / * изпращане на буфер (копие) на работник * / w.postMessage (buff); / * промяна на данните * / arr [0] = 1;
И, както можете да видите по-долу, актуализацията отразява вътре в работника!
[работник] Данни, получени от основната нишка: 1
Но кодът също трябва да работи обратното: когато стойността в работника се променя първоначално също трябва да се актуализира когато е отпечатан от основната нишка.
В този случай нашият код изглежда така:
onmessage = (e) => var arr = нов Int8Array (e.data); console.group ( "[работник]); console.log ("Данните, получени от основната нишка:% i ', arr [0]); console.groupEnd (); / * промяна на данните * / arr [0] = 7; / * публикуване в основната нишка * / postMessage (");
Най- данните се променят в работника и празна съобщение се публикува в основната нишка сигнализиране, че данните в буфера са променени и е готов за извеждане на основната нишка.
const w = нов работник ('worker.js'), buff = new SharedArrayBuffer (1); var arr = нов Int8Array (buff); / * настройка на данни * / arr [0] = 9; / * изпращане на буфер (копие) на работник * / w.postMessage (buff); / * промяна на данните * / arr [0] = 1; / * отпечатване на данните след като работникът го е променил * / w.onmessage = (e) => console.group ('[main]'); console.log ("Актуализирани данни, получени от работната нишка:% i ', arr [0]); console.groupEnd ();
И това също работи! Данните в буфера са същите като данните в работника.
[работник] Данни, получени от основната нишка: 1 [main] Актуализирани данни, получени от работната нишка: 7
Стойността се показва актуализиран и в двата случая; Основните и работните нишки разглеждат и променят едни и същи данни.
Заключителни думи
Както споменах по-рано, използвайки споделена памет в JavaScript не е без недостатъци. Разработчиците трябва да се уверят, че последователност на изпълнение се случва, както е предвидено и нито две нишки се състезават, за да получат същите данни, защото никой не знае кой ще вземе трофея.
Ако се интересувате от споделена памет повече, погледнете документацията на Atomics
обект. Най- Атомният обект може да ви помогне с някои от трудностите, чрез намаляване на непредсказуемостта на четене / писане от споделената памет.