اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
سه دقیقه
تولید برنامههای اجرایی تک فایلی در زمان NET Core 3x. ارائه شد؛ اما به همراه این مسائل نیز بود:
- فایل اجرایی تک فایلی تولید شده در اصل یک فایل zip خود باز شونده بود که در یک مکان موقتی به صورت خودکار باز و اجرا میشد. این حالت با آنتیویروسها و یا سیستمهایی که قسمتهای اصلی آنها جهت کاربران عادی قفل شدهاند، مشکلاتی را ایجاد میکرد.
- حجم فایل نهایی تولید شده قابل توجه بود. برای نمونه یک برنامهی کنسول Hello world آن حدود 70 مگابایت میشد. البته باید درنظر داشت که یک چنین خروجی به همراه یک NET Core runtime. کامل نیز میشد.
از آن زمان تغییرات تدریجی مفیدی در این زمینه رخ دادهاند که خلاصهای از آنها را تا دات نت 6 در ادامه مرور میکنیم.
اصول تولید برنامههای اجرایی تک فایلی دات نت
فرض کنید برنامهی کنسول ما از این سه سطر تشکیل شدهاست:
برای تولید یک برنامهی اجرایی تک فایلی بر اساس آن، میتوان دستور زیر را در خط فرمان اجرا کرد:
در این حالت ذکر سیستم عامل هدف، اجباری است؛ از این جهت که خروجی نهایی تنها برای یک سیستم عامل تهیه میشود.
پس از اجرای دستور فوق، اگر به مکان C:\MyProject\bin\Release\net6.0\win-x64\publish مراجعه کنیم، به یک فایل exe حدود 62 مگابایتی خواهیم رسید که کمی کم حجمتر از نمونهی NET Core 3x. آن است! البته همانطور که عنوان شد این خروجی به همراه runtime متناظری نیز هست. اگر بخواهیم این runtime را از آن حذف کنیم میتوان به صورت زیر عمل کرد:
با استفاده از سوئیچ self-contained false دیگر خروجی نهایی به همراه runtime دات نت تشکیل نخواهد شد و حجم حاصل تنها 150 کیلوبایت خواهد بود. در این حالت استفاده کنندهی نهایی باید runtime را خودش به صورت مجزایی نصب کند.
یک نکته: میتوان سوئیچهای فوق را به فایل csproj نیز به صورت زیر اضافه کرد:
تک فایلهای اجرایی دات نت 6 دیگر فایلهای zip خود باز شونده نیستند
همانطور که عنوان شد، تک فایلهای اجرایی تولید شدهی در نگارشهای پیشین دات نت، چیزی بجز یک فایل zip خود بازشونده که همه چیز داخل آن قرار گرفته بودند، نبودند. این حالت دیگر در دات نت 6 صادق نیست و اینبار خروجی نهایی در حافظه بارگذاری میشود و نیاز به باز شدن آن در مکانهای temp برطرف شدهاست. تا زمان دات نت 5، این قابلیت فقط برای خروجیهای لینوکس تدارک دیده شده بود، اما با ارائهی دات نت 6، خروجیهای ویندوز و مک هم فایلهای اجرایی واقعی هستند.
فعالسازی IL Trimming
به صورت پیشفرض با اجرای دستورات تولید تک فایلهای اجرایی برنامههای دات نت، تمام وابستگیهای استفاده شده بدون هیچگونه بهینه سازی در کنار هم قرار میگیرند. با فعالسازی قابلیت IL Trimming میتوان وابستگیهایی را که برنامه از آنها استفاده نمیکند، از خروجی نهایی حذف کرد که در نتیجهی آن، شاهد کاهش حجم قابل ملاحظهی فایل تولیدی نهایی خواهیم بود. برای اینکار میتوان سوئیچ PublishTrimmed را فعالسازی کرد:
پس از آن برنامهی 60 مگابایتی تولیدی در ابتدای بحث، تبدیل به یک برنامهی اجرایی تک فایلی 11 مگابایتی میشود که کاهش حجم قابل توجهی است.
باید دقت داشت که این حجم نهایی، یک فایل اجرایی واقعی بدون نیاز به نصب هیچ نوع runtime ای است و کاملا متکی به خود است.
فعالسازی فشرده سازی
به همراه دات نت 6، امکان فشرده سازی خودکار این خروجی نهایی تک فایلی، جهت کاهش هرچه بیشتر حجم آن نیز میسر شدهاست. برای اینکار میتوان سوئیچ EnableCompressionInSingleFile را فعالسازی کرد:
خروجی آن یک فایل 30 مگابایتی بدون IL Trimming است که نسبت به خروجی 60 مگابایتی ابتدای بحث، باز هم کاهش قابل ملاحظهای داشتهاست.
- فایل اجرایی تک فایلی تولید شده در اصل یک فایل zip خود باز شونده بود که در یک مکان موقتی به صورت خودکار باز و اجرا میشد. این حالت با آنتیویروسها و یا سیستمهایی که قسمتهای اصلی آنها جهت کاربران عادی قفل شدهاند، مشکلاتی را ایجاد میکرد.
- حجم فایل نهایی تولید شده قابل توجه بود. برای نمونه یک برنامهی کنسول Hello world آن حدود 70 مگابایت میشد. البته باید درنظر داشت که یک چنین خروجی به همراه یک NET Core runtime. کامل نیز میشد.
از آن زمان تغییرات تدریجی مفیدی در این زمینه رخ دادهاند که خلاصهای از آنها را تا دات نت 6 در ادامه مرور میکنیم.
اصول تولید برنامههای اجرایی تک فایلی دات نت
فرض کنید برنامهی کنسول ما از این سه سطر تشکیل شدهاست:
using System; Console.WriteLine("Hello, World!"); Console.ReadLine();
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained true
پس از اجرای دستور فوق، اگر به مکان C:\MyProject\bin\Release\net6.0\win-x64\publish مراجعه کنیم، به یک فایل exe حدود 62 مگابایتی خواهیم رسید که کمی کم حجمتر از نمونهی NET Core 3x. آن است! البته همانطور که عنوان شد این خروجی به همراه runtime متناظری نیز هست. اگر بخواهیم این runtime را از آن حذف کنیم میتوان به صورت زیر عمل کرد:
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained false
یک نکته: میتوان سوئیچهای فوق را به فایل csproj نیز به صورت زیر اضافه کرد:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <PublishSingleFile>true</PublishSingleFile> <SelfContained>true</SelfContained> <RuntimeIdentifier>win-x64</RuntimeIdentifier> <PublishReadyToRun>true</PublishReadyToRun> </PropertyGroup> </Project>
تک فایلهای اجرایی دات نت 6 دیگر فایلهای zip خود باز شونده نیستند
همانطور که عنوان شد، تک فایلهای اجرایی تولید شدهی در نگارشهای پیشین دات نت، چیزی بجز یک فایل zip خود بازشونده که همه چیز داخل آن قرار گرفته بودند، نبودند. این حالت دیگر در دات نت 6 صادق نیست و اینبار خروجی نهایی در حافظه بارگذاری میشود و نیاز به باز شدن آن در مکانهای temp برطرف شدهاست. تا زمان دات نت 5، این قابلیت فقط برای خروجیهای لینوکس تدارک دیده شده بود، اما با ارائهی دات نت 6، خروجیهای ویندوز و مک هم فایلهای اجرایی واقعی هستند.
فعالسازی IL Trimming
به صورت پیشفرض با اجرای دستورات تولید تک فایلهای اجرایی برنامههای دات نت، تمام وابستگیهای استفاده شده بدون هیچگونه بهینه سازی در کنار هم قرار میگیرند. با فعالسازی قابلیت IL Trimming میتوان وابستگیهایی را که برنامه از آنها استفاده نمیکند، از خروجی نهایی حذف کرد که در نتیجهی آن، شاهد کاهش حجم قابل ملاحظهی فایل تولیدی نهایی خواهیم بود. برای اینکار میتوان سوئیچ PublishTrimmed را فعالسازی کرد:
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained true -p:PublishTrimmed=true
باید دقت داشت که این حجم نهایی، یک فایل اجرایی واقعی بدون نیاز به نصب هیچ نوع runtime ای است و کاملا متکی به خود است.
فعالسازی فشرده سازی
به همراه دات نت 6، امکان فشرده سازی خودکار این خروجی نهایی تک فایلی، جهت کاهش هرچه بیشتر حجم آن نیز میسر شدهاست. برای اینکار میتوان سوئیچ EnableCompressionInSingleFile را فعالسازی کرد:
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained true -p:EnableCompressionInSingleFile=true