پردازش موازی یا خطی در جاوا اسکریپت ، مسئله این است!(قسمت دوم)

در قسمت اول درباره مفهوم کلی نخ ها ، زمان بندی و دو نوع روش برای کنترل فرایند ها معرفی شد.

در این قسمت درباره جاوا اسکریپت مطالبی را بیان خواهم کرد.

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

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

موتور V8 گوگل  برای اجرای دستورات از روش non-blocking I/O استفاده می کند ، تمامی فعالیت ها در یک نخ کنترل می شوند .

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

اما درصورتی که از این زبان استفاده کرده باشید متوجه شدید که می توان به راحتی به عنوان مثال یک ساعت طراحی کرد و همزمان فرایند های دیگری را نیز کنترل کرد.

این امکان به دلیل آن است که موتور V8 خود در سطح زبان ، فرایند نخ را شبیه سازی کرده است. با این تفاوت که نام آن Event Loop  می باشد.

در این زبان صفی به نام Event Loop تعبیه شده است که دستوراتی که به I/O نیاز دارند و یا Event ها را در آن زمان بندی می نماید.

Event  ها یا رویداد ها به فرایند هایی مانند کلیک کردن ، حرک موس ، تایپ کردن و هر عملیاتی که توسط کاربر انجام شود اطلاق می شود. رویداد ها توسط پردازشگر I/O مدیریت می شوند.

دستور Ajax نیز مانند Event یک دستور I/O می باشد که در این صف قرار می گیرد. دستورات I/O همانطور که گفته شد برای اجرا به نخ دیگری ارسال می شوند که همراه خود دستور فراخوانی را حمل می کنند. هنگامی که فرایند I/O به اتمام برسد فراخوان اجرا می شود و پاسخ دستور I/O درون صف Event Loop وارد می شود تا در زمان مناسب اجرا شود.

event loop

نکته مهمی که در زمان بندی صف وجود دارد این است که ، هر دستوری که در صف قرار می گیرد می بایست تا انتها اجرا شود که دستور بعد بتواند از صف خارج شده و اجرا شود.

به عنوان مثال در قطعه کد زیر:

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

تابع setTimeout یک time event ایجاد می کند که به صورت مجزا درون صف Event loop وارد می شود. پس می بایست منتظر بماند تا Main Code اجرایش تمام شود که در این مورد حلقه زمانی طولانی سپری خواهد کرد.

با اینکه جاوا اسکریپت از یک نخ استفاده می کند با این حال سرعت بالای پردازش صف Event Loop باعث شده تا همان حس چند نخی را ایجاد نماید.

نوع دیگر Event  ها Timer ها هستند. توابعی مانند setTimeout  و setInterval .

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

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

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

این شبیه سازی ها به دلیل اینکه می بایست قطعه درون صف تا انتها اجرا شود کارایی لازم برای نتیجه دلخواه را ندارد. به همین دلیل روش دیگری برای مرتفع کردن این مشکل ارائه شده است.

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



دسته بندی: مقاله

4 دیدگاه

  • MJB_Khorasani

    سلام
    این بخش رو متوجه نشدم: «نکته مهمی که در زمان بندی صف وجود دارد این است که ، هر دستوری که در صف قرار می گیرد می بایست تا انتها اجرا شود که دستور بعد بتواند از صف خارج شده و اجرا شود.»

    اگر ممکن است بیشتر و دقیق تر توضیح بدهید.
    آیا منظورتان این است که در صف event loop هر رویدادی زودتر وارد صف شود زودتر هم انجام می شود و تا دستورات آن رویداد به صورت کامل اجرا نشده اند بقیه ی دستورات پردازش نمی شوند؟؟؟
    خب پس چگونه است که نود برای وب اپ های real time مثل اپلیکیشن های چت کارایی خوبی دارد؟؟

    لطفا بیشتر توضیح دهید

    • porya grand

      سلام خدمت شما دوست عزیز.
      هم نه و هم آره. اجازه بدین با یک مثال توضیح بدم.
      فرض کنید اپلیکیشنی با عنوان ضرب دو ماتریس طراحی کردید که قسمتی هم در این پلیکیشن وجود داره که به عنوان مثال راهنمای این اپلیکیشن هست ، یک دکمه که زمانی که روی اون کلیک کنید ، درخواستی به سرور ارسال می کنه و محتوای راهنما رو دریافت می کنه.
      خوب حالا فرض کنید دو ماتریس با ابعاد بزرگ وارد کردید ، اما قبل از اجرای پراسس ضرب دو ماتریس ، بر روی راهنما کلیک کردید.
      خوب قاعدتا سیستم درخواست کلیک شمارو اجرا می کنه ، یک درخواست به سرور میفرسته که فایل راهنمارو برام بفرست.
      از شانس بد ، دریافت پاسخ از سرور زمان زیادی میگیره، به طوری که شما وقت می کنید روی دکمه پراسس ضرب دو ماتریس کلیک کنید .
      همچنان از همون شانس بد ، هنوز هم جوابی از سرور دریافت نشده، پس Event Loop همچنان خالیه. پس تابع ضرب دو ماتریس شروع به اجرا می کنه.
      اما به محض شروع شدن ضرب ، درخواست از سرور برمیگرده ، اما همونجور که گفتم از همون شانس بد ، دیگه تابع ضرب اجرا شده و حداقل فرض کنید یک دقیقه طول می کشه تا فرایند تکمیل بشه. پس درخواست بازگشته از سرور صبر می کنه تا ضرب تموم بشه.
      زمانی که فرایند ضرب ، کارش تموم شد ، داده های راهنما نمایش داده میشه ، با اینکه دیدید ، درخواست نمایش راهنما خیلی زود تر از اجرای فرایند ضرب ارسال شده بود ، اما چون هنوز پاسخی به Event Loop از سمت سرور ارسال نشده بود ، تابع ضرب کارشو زود تر شروع کرد و همچنین به دلیل اینکه فرایند ضرب ، زمان زیادی گرفت و همونطور که گفتم ، "هر دستوری که در صف قرار می گیرد می بایست تا انتها اجرا شود که دستور بعد بتواند از صف خارج شده و اجرا شود" ،پس ضرب هم تا انتها باید اجرا بشه تا سیستم بتونه "راهنما" رو نشون بده.

      — ویرایش
      در مورد اپلیکیشن چت که فرمودید باید بگم که این فرایند به حدی سریع هست ، که متوجه این موضوع نمیشید. البته این سرعت همونطور که در مثال مشهوده ، بسته به فرایند اجرا شده ، می تونه کند باشه و محسوس بشه

      باز هم اگه خوب توضیح ندادم ، بفرمایید تا بیشتر توضیح بدم. 🙂
      موفق باشین

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

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