Droid Hub✨
رفتن به کانال در Telegram
213
مشترکین
اطلاعاتی وجود ندارد24 ساعت
+37 روز
+330 روز
آرشیو پست ها
213
Structured concurrency:
یک رویکرد برنامه نویسی است که به ساده سازی و افزایش قابلیت اطمینان در اجرای فرایند های concurrent کمک میکند. این رویکرد اطمینان حاصل میکند تا تمام فرایندهای concurrent به صورت ساختار یافته و مدیریت شده اجرا شوند تا با یکدیگر به تداخل بر نخورند و side effect ای بر جای نگذارند.
این هدف به کمک محدود کردن اجرای فرایند ها در یک سلسله مراتب خاص (هر فرایند درون یک parent context انجام میشود و تضمین میشود تا قبل از آن که parent اش خاتمه یابد فعالیتش را تمام کند) محقق میشود.
ا Structured concurrency در کاتلین بر اساس یک رابطهی سلسله مراتبی بین کروتین هاست، هر کروتین یک parent دارد. موقعی که یک کروتین جدید start زده میشود این کروتین به child یک کروتین دیگر تبدیل میشود.
این رابطهی سلسله مراتبی باقی است تا زمانی که طول عمر تمام کروتین ها به پایان برسد. لازم به ذکر است هنگامی که یک کروتین parent کنسل میشود تمام child های آن نیز به صورت سلسله مراتبی از پایین ترین قسمت کنسل میشوند این کمک میکند تا مطمئن شویم هیچ leak و یا کروتین معلقی وجود ندارد.
یکی از مزایای مهم Structured concurrency آن است که به کمک محدود کردن اجرای کروتین ها به یک context سلسله مراتبی خاص ، مطمئن میشود تا همهی فرایندها مدیریت شده و ریسورس ها در یک زمان قابل پیشبینی آزاد شوند. به کمک این مورد میتوان بر بسیاری از مشکلات فرایندهای concurrent مانند race condition و deadlock و resource leak غلبه کرد.
#coroutines
213
بنابراین من در در توسعه ی این پلاگین در همین جا متوقف شدم و فعلا روشی برای اون پیدا نکردم
اگر دوستان راه حل یا ایده ی جدیدی داشتند ممنون میشم که به من پیام بدن
#compose_plugin
213
پاسخ گوگل
Status: Won't Fix (Infeasible)
Triage notes: It's unlikely that we'd provide an API in the front-end to do exactly what's being requested. Your current approach is the best we're going to be able to do. The information is generated during IR transforms, which aren't going to run in Android Studio.
#compose_plugin
213
تو این issue ازشون خواستم که یک api برای تحلیل stability در فاز front end کامپایلر فراهم کنند.
Is there a solution or API in the Compose compiler to determine whether the arguments are marked as stable or not by the compiler? While there is a solution in Gradle to generate reports appropriately, I am looking for a way to interact with the compiler in real-time to understand the stability model it considers for the arguments. This is intended for developing a plugin. Is such a solution publicly available in the compiler?
اما به دلیلی که متوجه نمیشوم به شدت از این دیتا محافظت میکنند و گفتند که احتمالا آن را پابلیک نمیکنند.
من حتی حدس میزنم که IR فاز بکند را هم به نحوی درهم ریزی میکنند تا تفسیر آن سخت باشد
#compose_plugin
213
اما این جا یه مشکل اساسی به وجود اومد
کامپایلر کامپوز در IR تولید شده در فاز front end استیبلیتی را مشخص نمیکرد
و این کار را در IR backend انجام میداد
بنابراین من نمیتوانستم در هنگام تایپ کد ها stability را مشخص کنم.
اگر چه این کار توسط تغییر آرگومان های compose plugin قابل انجام بود اما پلاگین هم از تمام پروژه اسکن میگرفت و به صورت ران تایم نبود.
بنابراین یک issue برای گوگل ثبت کردم
#compose_plugin
213
حالا برای اینکه متوجه بشم که کامپوز کامپایلر چه نوع stability ای رو به آرگومان ها اطلاق کرده باید به IR میرسیدم و اون رو تحلیل میکردم
ا IR (Intermediate Representation) چیه؟
کامپایلر در فاز های مختلف front end و back end خودش یک کد میانی به نام IR را از کد های ما تولید میکند که یک کد بهینه تر است و شامل موارد اضافه ای است که فرایند های بعدی را آسان تر میکند.
بنابراین من به کمک Psi2IrTranslator کد های psi را به IR تبدیل کردم تا بتوانم با تحلیل IR به stability آرگومان ها برسم
#compose_plugin
213
ا psi چیه ؟
کد زیر رو در نظر بگیرید
fun greet(name: String): String {
return "Hello, $name!"
}
وقتی این کد در ide های intelij based نوشته میشه یک ساختار درختی مثل تصویر بالا ایجاد میشه که بیانگر اجزای مختلف کد هست که از تحلیل آن میتوان به ساختار قسمت های مختلف یک کد پی برد.
#compose_plugin213
من قصد داشتم تا یک پلاگین برای اندروید استادیو توسعه بدم تا مثل تصویر بالا stability ای که کامپایلر کامپوز به آرگومان ها اطلاق میکنه رو در زمان نوشتن کد ها پیدا کنم و مطابق تصویر اون هارو هینت کنم.
برای این کار ابتدا درخت psi را پیمایش کردم تا به آرگومان های هر فانکشن کامپوزی برسم
#compose_plugin
213
3. برقراری انطباق با CoroutineContext: این کلاس ادامه اجرای کروتین را با توجه به
CoroutineContext فعلی تنظیم میکند. به عبارت دیگر، ادامه اجرای کروتین با در نظر گرفتن خصوصیات موجود در CoroutineContext مانند Job، Dispatcher و سایر عناصر مرتبط انجام میشود.
4. مدیریت استثناها (Exceptions): DispatchedContinuation به مدیریت و انتقال استثناها در کروتینها کمک میکند. اگر در حین اجرای continuation استثنایی رخ دهد، DispatchedContinuation تضمین میکند که استثنا به صورت صحیح به CoroutineExceptionHandler مناسب منتقل شود.
5. بهینهسازی عملکرد: با بررسی و تغییر dispatcher تنها در صورت نیاز، DispatchedContinuation به بهینهسازی عملکرد کمک میکند. این امر باعث میشود که تغییر ترد و dispatcher تنها زمانی انجام شود که واقعا لازم باشد، و از تغییرات غیرضروری جلوگیری شود.
در نتیجه، DispatchedContinuation نقشی کلیدی در مدیریت صحیح و کارای اجرای کروتینها در زمینههای مختلف دارد و به بهبود کارایی و ایمنی اجرای کروتینها کمک میکند.
#coroutines213
ا DispatchedContinuation:
این کلاس یک پیادهسازی از
Continuation interface است که هنگام resume شدن بلاک کروتین، پارامتر isDispatchNeeded را بررسی میکند و در صورت نیاز به تغییر dispatcher، آن را تغییر میدهد. این امر باعث میشود تا حین اجرای یک کروتین بتوان dispatcher را تغییر داد و ادامهی یک فرایند را به ترد دیگر منتقل کرد. این ویژگی به ویژه در سناریوهایی مفید است که نیاز به تغییر زمینه اجرای یک کروتین داریم، به عنوان مثال از IO dispatcher به Main dispatcher برای بهروزرسانی UI.
وظایف اصلی کلاس DispatchedContinuation در Kotlin Coroutines عبارتند از:
1. مدیریت تغییرات Dispatcher: بررسی و تغییر dispatcher برای ادامه اجرای کروتین در ترد یا زمینه مناسب. این کار به کمک متد isDispatchNeeded انجام میشود که تعیین میکند آیا نیاز به تغییر dispatcher هست یا خیر.
2. اجرای امن continuation: DispatchedContinuation تضمین میکند که continuation در زمینهای ایمن اجرا میشود، به خصوص زمانی که نیاز به تغییر ترد یا dispatcher داریم. این امر برای جلوگیری از مشکلاتی مانند race condition و بهبود کارایی حائز اهمیت است.213
از آنجا که دادههای Inline Class مستقیما به عنوان primitive type در حافظه ذخیره میشوند، دسترسی به آنها سریعتر است و نیازی به بررسیهای اضافی یا تبدیل نوع داده در زمان اجرا نیست. این امر به خصوص در حلقهها و فراخوانیهای تابعی که بارها اجرا میشوند، میتواند تفاوت چشمگیری در عملکرد ایجاد کند.
کامپایلر کاتلین به گونهای طراحی شده است که کد نهایی تولید شده برای Inline Classes به گونهای باشد که کمترین فراخوانی به توابع اضافی و کد اضافی را داشته باشد. این کاهش در تعداد فراخوانیها و دستورات اضافی، به کاهش زمان اجرا و افزایش کارآیی کمک میکند.
213
بعضی وقت ها احتیاج هست تا به جهت خوانایی یک بخش از کد یا مدل کردن یک قسمت از بیزینس یک primitive type را در یک کلاس wrap کنیم.
این کار باعث میشود تا overhead ها و memory allocation هایی در زمان ران تایم اتفاق بیفتد.
تایپ های اولیه برای runtime کاتلین بسیار optimize شده اند و wrap کردن آن ها در یک کلاس دیگر سبب از بین رفتن تمام این بهبود ها میشود.
کاتلین به جهت برطرف ساختن این مشکل امکان inline value class هارا فراهم ساخته است .
این نوع از کلاس ها با value keyword تعریف میشوند و با انوتیشن JvmInline اعلان میشوند و میتوانند تنها یک پارامتر از نوع primitive را در constructor خودشان داشته باشند. کلاس های inline از خودشان هیچ identity ای ندارند و تنها یک value را hold میکنند.
213
ا CancellableContinuation interface:
یک اینترفیس است که از اینترفیس continuation ارث بری میکند و قابلیت کنسل شدن کروتین را به همراه یک cancellation token به آن اضافه میکند. cancellation token پارامتری است که وضعیت کنسل شدن یک کروتین را مشخص میکند.
ا Cancel: این فانکشن یک Throwable را به عنوان cancelCause به صورت آپشنال دریافت کرده و سپس کروتین را با این cause کنسل میکند. اگر continuation با موفقیت کنسل شد خروجی این فانکشن مقدار بولی true است. اگر کروتین قبل از اجرای این متد کنسل شده بود و یا با موفقیت اجرا شده بود، خروجی مقدار بولی false است.
ا IsActive این پارامتر وضعیت فعلی continuation را به لحاظ فعال بودن یا نبودن بررسی میکند. اگر continuation همچنان در وضعیت completed یا cancelled نباشد به عنوان active در نظر گرفته میشود.
هنگامی که یک کورتین کنسل میشود متد cancel در CancellableContinuation کال میشود، این امر باعث میشود تا کروتین با یک exception مجددا resume شود (این باعث میشود تا کروتین فرصت کافی برای clean up کردن خودش را داشته باشد) سپس کروتین خاتمه مییابد.
#coroutines
213
به طور کلی اینترفیس Continuation بخش مهمی از سیستم کوروتین است، زیرا راهی برای تعلیق و از سرگیری اجرای برنامهها فراهم میکند و برنامهنویسی ناهمزمان در Kotlin ممکن میسازد
#coroutines
213
ا Continuation interface:
هنگامی که یک فانکشن را با کلمهی کلیدی suspend مارک میکنید کامپایلر آن فانکشن را به فرم زیر تبدیل میکند
fun backgroundTask(param: Int, callback: Continuation<Int>): Int {
// long running operation
}
در واقع کامپایلر یک callback از نوع Continuation را به عنوان ورودی تابع در نظر میگیرد. این callback اساس عملیات های suspend و resume در کروتین است.
ا <Continuation<T> یک interface است که شامل دوفانکشن است، این فانکشنها هنگامی که یک کروتین resume میشود، اجرا میشوند (برای بازگردانی کروتین به وضعیتی که بتواند ادامهی کارش را از سر بگیرد). یکی از فانکشنها شامل value است و دیگری شامل exception است (برای زمانهایی که کروتین در حین suspend شدن با خطا مواجه شده است)
همچنین پارامتر context نیز همان coroutine context ای هست که continuation با آن مرتبط است . در واقع به کمک پارامتر context مطمئن میشویم که continuation در coroutine context صحیح با dispatcher صحیحی resume شده است یا خیر.
در آینده به معرفی انواع coroutine context خواهیم پرداخت
#coroutines213
عبارتی مثل val x = 5 وقتی به kotlin bytecode تبدیل میشه تقریبا یه همچین چیزی میشه
public final class ValExample {
private final int x;
public ValExample() {
this.x = 5;
}
}
در واقع جادوی کار همون عبارت final هست که تضمین میکنه این متغیر re-assign نشه.213
Under-hood conversion of Suspend by the compiler
قبل از آنکه وارد جزییات کامپایلر شویم اجازه دهید تا با اساس کار کروتین آشنا شویم. یک کروتین در واقع یک lightweight thread است که میتواند در یک نقطهی خاص، بدون بلاک کردن ترد، suspend و resume شود. در واقع ایدهی اصلی کروتین آن است که کدهای asynchronous را به همان روشی بنویسیم که کدهای synchronous را مینویسیم. این باعث میشود تا از بسیاری از خطاها در امان باشیم و کدهای async خوانا و قابل درک باشند.
هنگامی یک کروتین suspend میشود به این معناست که کروتین اجرای خودش را متوقف کرده و کنترل را به caller خودش بازمیگرداند(تردی که روی آن در حال اجرا است را رها میکند). کروتین به دلایل مختلفی میتواند suspend شود:
• انتظار برای آنکه فرایندهای i/o تکمیل شوند
• انتظار برای آنکه یک تایمر به پایان برسد
• انتظار برای آنکه یک کروتین دیگر اجرایش را کامل کند
#coroutines
