برنامه نویسی

JS’s Atomics یک مقدمه، چند رشته ای و حافظه را ایراد می کند!

جاوا اسکریپت مورد علاقه ما تک رشته ای است و به این ترتیب، تنها می تواند یک چیز را در یک زمان اجرا کند. این را ذخیره کنید، این مهم است!

بنابراین اگر یک کار طولانی مدت، رشته اصلی مرورگر را مسدود کند، مرورگر برای رندر کردن مشکل خواهد داشت.

به عنوان مثال، اگر بخواهیم حلقه‌ای را در یک ساختار داده بزرگ انجام دهیم،
یا یک حلقه ساده بسیار بزرگ ایجاد کنید.
این می تواند باعث یخ زدن رندر شود. در حالی که حلقه تمام نشد، یا زمانی که الگوریتم در حال عبور از ساختار کلان داده بود، کاری نمی توانید انجام دهید، فقط تماشا کنید و منتظر بمانید.

این یک مشکل تک رشته ای است.
شما در هر زمان فقط می توانید یک کار را انجام دهید و اگر خیلی طول بکشد، هیچ کار دیگری نمی توانید انجام دهید!

در این متن از تماس ها و وعده ها صحبت نمی کنیم.

یکی از راه حل های این مشکل استفاده از Web Workers است.

Web Workers مکانیسم هایی هستند که به یک عملیات از یک اسکریپت داده شده اجازه می دهند در رشته ای غیر از رشته اصلی برنامه وب اجرا شود. امکان پردازش محاسبات پرزحمت بدون مسدود کردن رشته اصلی (که معمولاً با رابط مرتبط است).
منبع > mdn.

می دانیم که js تک رشته ای است.
با گذشت زمان، برنامه های کاربردی در مرورگر بیشتر و بیشتر خواستار شدند.
بنابراین آنها تصمیم گرفتند که کارگران وب را برای کمک به ما بیاورند!

حالا آن حلقه غول پیکر می تواند به یک موضوع دیگر برود و صفحه اصلی ما را زیبا و سبک کند بدون اینکه کسی مانع شود!

Web Workers امکان اجرای موازی در زمینه مرورگر را می دهد.

با این حال، مانند همه چیز در فن آوری، وب کارگران نقاط ضعف خود را دارند. برای مثال، هزینه ای برای انتقال داده به و از موضوع Worker وجود دارد. هر انتقال از طریق postMessage انجام می شود.

مرورگر از الگوریتم کلون ساخت یافته استفاده می کند

JSs Atomics یک مقدمه، چند رشته ای و حافظه را

الگوریتم کلون ساخت یافته اشیاء پیچیده جاوا اسکریپت را کپی می کند. هنگام فراخوانی ()structurdClone، برای انتقال داده ها بین Workers از طریق postMessage()، ذخیره اشیاء با IndexedDB یا کپی کردن اشیاء برای سایر APIها به صورت داخلی استفاده می شود.

فاویکون
developer.mozilla.org

برای کپی کردن یک شی، یعنی کپی کردن همان داده در حافظه. این هزینه، بسته به شرایط، می تواند بیشتر از سود تخلیه به نخ Worker باشد.

چه می شود اگر بتوانیم از کپی کردن داده ها خودداری کنیم؟
یکی از راه های حل این مشکل استفاده از آن است SharedArrayBuffer.

برای توسعه دهندگان جاوا اسکریپت، این ساختار به ما اجازه می دهد تا تکه هایی از حافظه مشترک ایجاد کنیم. به جای کپی کردن داده ها از رشته اصلی به Worker و بالعکس، می توانیم همان حافظه مشترک را از هر دو طرف به روز کنیم.

// 
const length = 10;
 // Criando o tamanho do nosso buffer
const size = Int32Array.BYTES_PER_ELEMENT * length;
 // Criando o buffer com 10 inteiros 
const sharedBuffer = new SharedArrayBuffer(size);
const sharedArray = new Int32Array(sharedBuffer);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Int32Array چیست:

JSs Atomics یک مقدمه، چند رشته ای و حافظه را

آرایه تایپ شده Int32Array آرایه ای از اعداد صحیح امضا شده 32 بیتی مکمل twos را به ترتیب بایت پلتفرم نشان می دهد. اگر کنترل بر ترتیب بایت نیاز است، به جای آن از DataView استفاده کنید. محتویات به 0 مقداردهی اولیه می شوند. پس از ایجاد، می توانید عناصر موجود در آرایه را با استفاده از روش های شی یا با استفاده از نحو شاخص آرایه استاندارد (یعنی با استفاده از علامت گذاری براکت) ارجاع دهید.

فاویکون
developer.mozilla.org

sharedarraybuffer چیست:

1689455080 489 JSs Atomics یک مقدمه، چند رشته ای و حافظه را

فاویکون
developers.google.com

اکنون یک حافظه داریم که می توان آن را به اشتراک گذاشت. یعنی موضوع اصلی و کارمندان وب می توانند با هم به همان مکان دسترسی داشته باشند!

این واقعا خوب است، حافظه را ذخیره می کند!
اما مثل همه چیز در تکنولوژی، معایبی هم دارد!

موارد زیر را تصور کنید: ما 3 یا بیشتر Web Worker داریم که علاوه بر رشته اصلی به یک مکان حافظه دسترسی دارند. این اشتباه خواهد شد.
بسیار اشتباه. ممکن است شرایط مسابقه ای داشته باشیم. همه برای یک مکان رقابت می کنند یا مشکل به روز رسانی یک مکان دو بار با اطلاعات یکسان دارند.
به عبارت دیگر، 2 کارگر می توانند یک کار را همزمان انجام دهند و این اتلاف است.

شرط مسابقه چیست:

بنابراین آنها شی Atomics را ایجاد کردند.

عملیات اتمی تضمین می کند که ما روشی استاندارد برای خواندن و نوشتن داده ها به ترتیب قابل پیش بینی داریم.

Atomics دسترسی همه افراد به حافظه را مدیریت می کند، بنابراین از شرایط مسابقه، هدر رفتن کار و غیره جلوگیری می کند.

اتمی چیست؟

JSs Atomics یک مقدمه، چند رشته ای و حافظه را

شی فضای نام Atomics شامل متدهای ثابت برای انجام عملیات اتمی است. آنها با اشیاء SharedArrayBuffer و ArrayBuffer استفاده می شوند.

فاویکون
developer.mozilla.org

// main.js
const worker = new Worker('worker.js');
const length = 10;
const size = Int32Array.BYTES_PER_ELEMENT * length;

const sharedBuffer = new SharedArrayBuffer(size);
const sharedArray = new Int32Array(sharedBuffer);
for (let i = 0; i < 10; i++) {
    Atomics.store(sharedArray, i, 0);
}
worker.postMessage(sharedBuffer);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دسترسی به داده ها در کارگر

// worker.js
self.addEventListener('message', (event) => {
    const sharedArray = new Int32Array(event.data);
    for (let i = 0; i < 10; i++) {
        const arrayValue = Atomics.load(sharedArray, i);
        console.log(`The item at array index ${i} is ${arrayValue}`);
    }
}, false);


وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر بخواهیم ماتریس کارگر را به روز کنیم چه می شود؟ ما دو گزینه برای این به روز رسانی ها با استفاده از Atomics داریم. می توانیم از store که قبلاً دیدیم استفاده کنیم یا می توانیم از Exchange استفاده کنیم. تفاوت اینجاست که store مقدار ذخیره شده را برمی گرداند و Exchange مقدار جایگزین شده را برمی گرداند. بیایید ببینیم این در عمل چگونه کار می کند:

// worker.js
self.addEventListener('message', (event) => {
    const sharedArray = new Int32Array(event.data);
    for (let i = 0; i < 10; i++) {
        if (i%2 === 0) {
            const storedValue = Atomics.store(sharedArray, i, 1);
            console.log(`The item at array index ${i} is now ${storedValue}`);
        } else {
            const exchangedValue = Atomics.exchange(sharedArray, i, 2);
            console.log(`The item at array index ${i} was ${exchangedValue}, now 2`);
        }
    }
}, false);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون می‌توانیم آرایه نخ اصلی و کارگر را بخوانیم و به‌روزرسانی کنیم. Atomics چند روش دیگر دارد که می‌توانیم از آنها برای مدیریت آرایه‌های مشترک جدیدمان استفاده کنیم. دو تا از مفیدترین روش ها صبر و بیدار شدن هستند. Waitnos به شما این امکان را می دهد که منتظر تغییر در شاخص آرایه باشید و سپس عملیات را ادامه دهید. در عمل، این ممکن است در سمت کارگر چیزی شبیه به این باشد:

self.addEventListener('message', (event) => {
    const sharedArray = new Int32Array(event.data);
    const arrayIndex = 0;
    const expectedStoredValue = 50;
    // An optional 4th argument can be passed which is a timeout
    Atomics.wait(sharedArray, arrayIndex, expectedStoredValue);
    // Log the new value
    console.log(Atomics.load(sharedArray, arrayIndex));
}, false);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا ما انتظار تغییر در arrayIndex0 را داریم که در آن مقدار ذخیره شده مورد انتظار 50 است. بنابراین می توانیم به آن بگوییم که وقتی مقدار ایندکس را تغییر می دهیم از رشته اصلی بیدار شود:

const newArrayValue = 100;
Atomics.store(sharedArray, 0, newArrayValue);
// The index that is being waited on
const arrayIndex = 0;
// The first agent waiting on the value
const queuePos = 1;
Atomics.wake(sharedArray, arrayIndex, queuePos);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توابع دیگری برای راحتی ارائه شده است، مانند add و sub که به ترتیب از شاخص آرایه اضافه یا کم می کنند. اگر به عملیات بیتی علاقه دارید، برخی از آنها از جمله یا، و و xor ارائه شده است.

می‌توانیم ببینیم که اتمی‌ها می‌توانند از شرایط مسابقه اجتناب کنند و با استفاده از روش‌های Atomics، به‌روزرسانی‌های قابل پیش‌بینی را برای یک آرایه ایجاد کنند.

برای استفاده از رشته ها، باید آنها را به یک نمایش عددی تبدیل کنیم، به عنوان مثال، یک استاندارد شناخته شده برای رمزگذاری به عنوان UTF-16.

function sharedArrayBufferToUtf16String(buf) {
    const array = new Uint16Array(buf);
    return String.fromCharCode.apply(null, array);
}

function utf16StringToSharedArrayBuffer(str) {
    // 2 bytes for each char
    const bytes = str.length *2;
    const buffer = new SharedArrayBuffer(bytes);
    const arrayBuffer = new Uint16Array(buffer);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        arrayBuffer[i] = str.charCodeAt(i);
    }
    return { array: arrayBuffer, buffer: buffer };
}

const exampleString = "Hello world, this is an example string!";
const sharedArrayBuffer = utf16StringToSharedArrayBuffer(exampleString).buffer;
const backToString = sharedArrayBufferToUtf16String(sharedArrayBuffer);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همه کدها از این متن گرفته شده اند:

JSs Atomics یک مقدمه، چند رشته ای و حافظه را

ببینید چگونه از SharedArrayBuffers برای به اشتراک گذاشتن حافظه بین زمینه‌های رشته‌های مختلف و در عین حال اجتناب از شرایط مسابقه با استفاده از روش‌های Atomics استفاده می‌کنیم.

فاویکون
sitepen.com

من یک مقدمه کوچک بر شی Atomics کردم
به یاد داشته باشید که همه اینها *روی Node هم کار میکنه! *
اگر می خواهید بیشتر بدانید فقط منابع را بخوانید:

https://www.sitepen.com/blog/the-return-of-sharedarraybuffers-and-atomics

https://dev.to/feezyhendrix/worker-threads-in-node-js-2ikh

https://exploringjs.com/es2016-es2017/ch_shared-array-buffer.html

https://blogtitle.github.io/using-javascript-sharedarraybuffers-and-atomics/

Understanding SharedArrayBuffer and cross-origin isolation

https://www.tutorialspoint.com/what-is-the-use-of-atomics-in-javascript

https://webreflection.medium.com/about-sharedarraybuffer-atomics-87f97ddfc098

https://www.geeksforgeeks.org/atomics-in-javascript/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا