- Explicit
- Implicit
کامپایلر JIT
همانطور که در تصویر فوق مشاهده میکنید، سورس کد توسط کامپایلر دات نت به exe و یا dll کامپایل میشود. کامپایلر JIT تنها متدهایی را که در زمان اجرا(runtime) فراخوانی میشوند را کامپایل میکند. در دات نت فریم ورک سه نوع JIT Compilation داریم:
Normal JIT Compilation
در این نوع کامپایل، متدها در زمان فراخوانی در زمان اجرا کامپایل میشوند. بعد از اجرا، متد داخل حافظه ذخیره میشود. به متدهای ذخیره شده در حافظه jitted گفته میشود. دیگر نیازی به کامپایل متد jit شده نیست. در فراخوانی بعدی، متد مستقیماً از حافظه کش در دسترس خواهد بود.
Econo JIT Compilation
این نوع کامپایل شبیه به حالت Normal JIT است با این تفاوت که متدها بلافاصله بعد از اجرا از حافظه حذف میشوند.
Pre-JIT Compilation
یکی دیگر از حالتهای کامپایل برنامههای دات نتی Pre-JIT Compilation می باشد. در این حالت به جای متدهای مورد استفاده، کل اسمبلی کامپایل میشود. در دات نت میتوان اینکار را توسط Ngen.exe یا (Native Image Generator) انجام داد. تمام دستورالعملهای CIL قبل از اجرا به کد محلی(Native Code) کامپایل میشوند. در این حالت runtime میتواند از native images به جای کامپایلر JIT استفاده کند. این نوع کامپایل عملیات تولید کد را در زمان اجرای برنامه به زمان Installation منتقل میکند، در اینصورت برنامه نیاز به یک Installer برای اینکار دارد.
Multicore JIT
در دات نت فریم ورک 4.5 یک راه حل جایگزین دیگر برای بهینه سازی و بهبود سرعت اجرای برنامههای دات نت وجود دارد. همانطور که عنوان شد Ngen.exe برای در دسترس بودن نیاز به Installer برای برنامه دارد. توسط Multicore JIT متدها بر روی دو هسته به صورت موازی کامپایل میشوند، در اینصورت میتوانید تا 50 درصد از JIT Time صرفه جویی کنید.
Multicore JIT همچنین میتواند باعث بهبود سرعت در برنامههای WPF شود. در نمودار زیر میتوانید حالتهای استفاده و عدم استفاده از Multicore JIT را در سه برنامه WPF نوشته شده مشاهده کنید.
Multicore JIT در عمل
Multicore JIT از دو مد عملیاتی استفاده میکند: مد ثبت(Recording mode)، مد بازپخش(Playback mode)
در حالت ثبت کامپایلر JIT هر متدی که نیاز به کامپایل داشته باشد را رکورد میکند. بعد از اینکه CLR تعیین کند که اجرای برنامه به اتمام رسیده است، تمام متدهایی که اجرا شده اند را به صورت یک پروفایل بر روی دیسک ذخیره میکند.
هنگامیکه Multicore JIT فعال میشود، با اولین اجرای برنامه، حالت ثبت مورد استفاده قرار میگیرد. در اجراهای بعدی، از حالت بازپخش استفاده میشود. حالت بازپخش پروفایل را از طریق دیسک بارگیری کرده، و قبل از اینکه این اطلاعات توسط ترد اصلی مورد استفاده قرار گیرد، از آنها برای تفسیر (کامپایل) متدها در پیشزمینه استفاده میکند.
در نتیجه، ترد اصلی به کامپایل دیگری نیاز ندارد، در این حالت سرعت اجرای برنامه بیشتر میشود. حالتهای ثبت و بازپخش تنها برای کامپیوترهایی با چندین هسته فعال میباشند.
استفاده از Multicore JIT
در برنامههای 4.5 ASP.NET و 5 Silverlight به صورت پیش فرض این ویژگی فعال میباشد. ازآنجائیکه این برنامهها hosted application هستند؛ در نتیجه فضای مناسبی برای ذخیره سازی پروفایل در این نوع برنامهها موجود میباشد. اما برای برنامههای Desktop این ویژگی باید فعال شود. برای اینکار کافی است دو خط زیر را به نقطه شروع برنامه تان اضافه کنید:
public App() { ProfileOptimization.SetProfileRoot(@"C:\MyAppFolder"); ProfileOptimization.StartProfile("Startup.Profile"); }
توسط متد SetProfileRoot میتوانیم مسیر ذخیره سازی پروفایل JIT را مشخص کنیم. در خط بعدی نیز توسط متد StartProfile نام پروفایل را برای فعال سازی Multicore JIT تعیین میکنیم. در این حالت در اولین اجرای برنامه پروفایلی وجود ندارد، Multicore JIT در حالت ثبت عمل میکند و پروفایل را در مسیر تعیین شده ایجاد میکند. در دومین بار اجرای برنامه CRL پروفایل را از اجرای قبلی برنامه بارگذاری میکند؛ در این حالت Multicore JIT به صورت بازپخش عمل میکند.
همانطور که عنوان شد در برنامههای ASP.NET 4.5 و Silverlight 5 قابلیت Multicore JIT به صورت پیش فرض فعال میباشد. برای غیر فعال سازی آن میتوانید با تغییر فلگ profileGuidedOptimizations به None اینکار را انجام دهید:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!-- ... --> <system.web> <compilation profileGuidedOptimizations="None" /> <!-- ... --> </system.web> </configuration>
زمانیکه اولین نگارش ASP.NET حدود 10 سال قبل منتشر شد، تنها سیستم عاملی که از آن پشتیبانی میکرد، ویندوز سرور 2000 بود، تنها پروسهی اجرایی آن aspnet_wp نام داشت و تنها معماری پشتیبانی شده هم X86 بود. به پروسهی aspnet_wp محدودیت مصرف حافظهای اعمال شده بود که در حین آغاز آن بر اساس مقدار قابل تغییر processModel memoryLimit محاسبه و اعمال میشد (تعریف شده در فایل ماشین کانفیگ). این عدد به صورت درصدی از ظرفیت RAM فیزیکی سیستم، قابل تعریف و به صورت پیش فرض به 60 درصد تنظیم شده بود. به این ترتیب این پروسه مجاز نبود تا تمام حافظهی فیزیکی مهیا را مصرف کند و در صورت وجود نشتی حافظهای در برنامهای خاص، این پروسه امکان بازیابی مجدد حافظه را پیدا میکرد (recycling). همچنین یک مورد دیگر را هم باید در نظر داشت و آن هم وجود قابلیتی است به نام ASP.NET Cache است که امکان ذخیره سازی مقادیر اشیاء را در حافظهی مصرفی این پروسه مهیا میسازد. هر زمان که میزان این حافظهی مصرفی به حد نزدیکی از محدودیت تعریف شده برسد، این پروسه به صورت خودکار شروع به حذف آنها خواهد کرد.
محدودیت 60 درصدی تعریف شده، برای سیستمهایی با میزان RAM کم بسیار مفید بود اما در سیستمهایی با میزان RAM بیشتر، مثلا 4 گیگ به 2.4GB حافظه مهیا (60 درصد حافظه فیزیکی سیستم) محدود میشد و همچنین باید در نظر داشت که میزان user mode virtual address space مهیا نیز تنها 2 گیگابایت بود. بنابراین هیچگاه استفاده مؤثری از تمام ظرفیت RAM مهیا صورت نمیگرفت و گاها مشاهده میشد که یک برنامه تنها با مصرف 1.5GB RAM میتوانست پیغام OutOfMemoryException را صادر کند. در این حالت مطابق بررسیهای صورت گرفته مشخص شد که اگر مقدار processModel memoryLimit به حدود 800 مگابایت تنظیم شود، بهترین عملکرد را برای سیستمهای مختلف میتوان مشاهده کرد.
با ارائهی ویندوز سرور 2003 و همچنین ارائهی نسخهی 1.1 دات نت فریم ورک و ASP.NET ، این وضعیت تغییر کرد. پروسهی جدید در اینجا w3wp نام دارد و این پروسه تعاریف مرتبط با محدودیت حافظهی خود را از تنظیمات IIS دریافت میکند (قسمت Maximum Used Memory در برگهی Recycling مربوط به خواص Application Pool مرتبط). متاسفانه این عدد به صورت پیش فرض محدودیتی ندارد و به ظاهر برنامه مجاز است تا حد امکان از حافظهی مهیا استفاده کند. به همین جهت یکی از مواردی را که باید در نظر داشت، مقدار دهی Maximum Used Memory ذکر شده است. خصوصا اینکه در نگارش 1.1 ، تنظیمات میزان مصرف RAM مرتبط با ASP.NET Cache نیز با برنامه یکی است.
در نگارش 2.0 دات نت فریم ورک، تنظیمات مرتبط با ASP.NET cache از تنظیمات میزان RAM مصرفی یک برنامهی ASP.NET جدا شد و این مورد توسط قسمت cache privateBytesLimit قابل تنظیم و مدیریت است (در فایل IIS Metabase و همچنین فایل web.config برنامه).
نکته!
اگر process memory limit و همچنین cache memory limit را تنظیم نکنید، باز به همان عدد 60 درصد سابق بازخواهیم گشت و این مورد به صورت خودکار توسط IIS محاسبه و اعمال میشود. البته محدودیت ذکر شده برای پروسههای 64 بیتی در این حالت بسیار بهتر خواهد بود. اگر هر دوی اینها را تنظیم کنید، عدد حداقل بکارگرفته شده، مبنای کار خواهد بود و اگر تنها یکی را تنظیم کنید ، این عدد به هر دو حالت اعمال میگردد. برای بررسی بهتر میتوان به مقدار Cache.EffectivePrivateBytesLimit و Cache.EffectivePercentagePhysicalMemoryLimit مراجعه کرد.
و ... اکنون بهتر میتوانید به این سؤال پاسخ دهید که «سرور ما بیشتر از 4 گیگ رم دارد و برنامهی ASP.NET من الان فقط 850 مگ رم مصرف کرده (که البته این هم نشانی از عدم dispose صحیح منابع است یا عدم تعیین تقدم و تاخر و زمان منقضی شدن، حین تعریف اشیاء کش)، اما پیغام out of memory exception را دریافت میکنم. چرا؟!»
بنابراین ایجاد یک Application pool جدید به ازای هر برنامهی ASP.NET امری است بسیار مهم زیرا:
- به این ترتیب هر برنامهی ASP.NET در پروسهای ایزوله از پروسهی دیگر اجرا خواهد شد (این مساله از لحاظ امنیتی هم بسیار مهم است). در اینجا هر برنامه، از پروسهی w3wp.exe مجزای خاص خود استفاده خواهد کرد (شبیه به مرورگرهایی که هر tab را در یک پروسه جدید اجرا میکنند).
- اگر پروسهای به حد بالای مصرف حافظهی خود رسید با تنظیمات انجام شده در قسمت recycling مرتبط با Application pool اختصاصی آن، به صورت خودکار کار بازیابی حافظه صورت میگیرد و این امر بر روی سایر برنامهها تاثیر نخواهد داشت (کاربران سایر برنامهها مدام شکایت نمیکنند که سشنها پرید. کش خالی شد. زیرا در حالت وجود application pool اختصاصی به ازای هر برنامه، مدیریت حافظه برنامهها از هم ایزوله خواهند بود)
- کرش صورت گرفته در یک برنامه به دلیل عدم مدیریت خطاها، بر روی سایر برنامهها تاثیر منفی نخواهد گذاشت. (زمانیکه ASP.NET worker process به دلیل استثنایی مدیریت نشده خاتمه یابد بلافاصله و به صورت خودکار مجددا «وهلهی دیگری» از آن شروع به کار خواهد کرد؛ یعنی تمام سشنهای قبلی از بین خواهند رفت؛ که در صورت ایزوله سازی ذکر شده، سایر برنامهها در امان خواهند ماند؛ چون در پروسه ایزولهی خود مشغول به کار هستند)
- با وجود application pool اختصاصی به ازای هر برنامه، میتوان برای سایتهای کم ترافیک و پرترافیک، زمانهای recycling متفاوتی را اعمال کرد. به این ترتیب مدیریت حافظهی بهتری قابل پیاده سازی میباشد. همچنین در این حالت میتوان مشخص کرد کدام سایت از تعداد worker process بیشتر یا کمتری استفاده کند.
- کاربری که پروسهی ASP.NET تحت آن اجرا میشود نیز همینجا تعریف میگردد. بنابراین به این ترتیب میتوان به برنامهای دسترسی بیشتر و یا کمتر داد، بدون تاثیر گذاری بر روی سایر برنامههای موجود.
نتیجه گیری:
- از IIS استفاده میکنید؟ آیا میدانید Application pool چیست؟
- آیا میدانید در صورت عدم مقدار دهی پارامترهای حافظهی یک Application pool ، به صورت پیش فرض چند درصد از حافظهی فیزیکی مهیا در اختیار شما است؟
برای مطالعه بیشتر:
رایگان شدن بیش از ۷۰۰۰ دوره سایت Pluralsight
قرار دادن سامانه دانشگاه بروی یک Private IP Address
iTextSharp تا نگارش 4.6.1 آن با مجوز LGPL ارائه شد و پس از آن بود که مجوز آن به AGPL تجاری تغییر کرد. به همین جهت کسانیکه نمیخواهند از مجوز AGPL آن استفاده کنند، هنوز با نگارش 4.6.1 آن کار میکنند. کتابخانهی iTextSharp.LGPLv2.Core حاصل انتقال کدهای این نگارش ویژه به NET Core. است.
یافتن «مطالب مرتبط» توسط لوسین
iTextSharp تا نگارش 4.6.1 آن با مجوز LGPL ارائه شد و پس از آن بود که مجوز آن به AGPL تجاری تغییر کرد. به همین جهت کسانیکه نمیخواهند از مجوز AGPL آن استفاده کنند، هنوز با نگارش 4.6.1 آن کار میکنند. کتابخانهی iTextSharp.LGPLv2.Core حاصل انتقال کدهای این نگارش ویژه به NET Core. است.
لینکهای هفته دوم دی
وبلاگها ، سایتها و مقالات ایرانی (داخل و خارج از ایران)
- شیوهنامه فارسیپسند گوگلخوان، نسخه ۰.۱.۱ (کار جالبی است. آشنایی با افزونه استایلیش)
ASP. Net
طراحی و توسعه وب
PHP
اسکیوال سرور
سی شارپ
SharePoint
عمومی دات نت
ویندوز
مسایل اجتماعی و انسانی برنامه نویسی
متفرقه
- آشنایی با لولههای یاهو و همچنین نمونهای دیگر