معرفی ZLinq: کتابخانه LINQ با تخصیص حافظه صفر برای داتنت
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۳/۰۱ ۰۷:۵۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
Shuffle، RightJoin و LeftJoin. همچنین، ZLinq سازگاری رفتاری ۹۹ درصدی را با LINQ استاندارد تضمین میکند که این امر با پورت کردن و اجرای مداوم تستهای System.Linq.Tests از dotnet/runtime به دست آمده است. علاوه بر کاهش تخصیص حافظه، ZLinq شامل بهینهسازیهای پیشرفتهای از جمله پشتیبانی از SIMD است تا عملکرد بهتری را در اکثر سناریوهای عملی ارائه دهد. یکی از مزایای مهم ZLinq این است که این بهینهسازیها را برای تمام نسلهای .NET، از جمله .NET Framework، فراهم میکند، نه فقط برای نسخههای اخیر.ValueEnumerable و IValueEnumerator بنا شده است. ValueEnumerable یک readonly ref struct است که IValueEnumerator را کپسوله میکند. این طراحی امکان پردازش با وضعیت مستقل را برای هر Enumerator فراهم میآورد. این رویکرد به جای استفاده از IValueEnumerable انتخاب شده است تا از محدودیتهای استنتاج نوع (type inference) در C# جلوگیری شود.IValueEnumerator، متد TryGetNext(out T current) است که جایگزین جفت MoveNext() و Current در رابط IEnumerator شده است. این تغییر، تعداد فراخوانی متد را در هر تکرار به یک مورد کاهش داده و نیاز به نگهداری فیلد current را از بین میبرد. این امر به طور قابل توجهی اندازه ساختار (struct size) را کاهش میدهد که برای معماری مبتنی بر ساختار ZLinq حیاتی است، زیرا اندازه کوچکتر ساختارها منجر به هزینه کپی کمتر و عملکرد بهتر میشود. اگرچه این رویکرد از هموردایی (covariance) و پادهموردایی (contravariance) پشتیبانی نمیکند، اما توسعهدهنده ZLinq معتقد است که این ویژگیها با Span سازگار نیستند و در .NET مدرن منسوخ شدهاند.IValueEnumerator همچنین شامل متدهای کمکی برای بهینهسازی است:TryGetNonEnumeratedCount(out int count): این متد زمانی موفق میشود که منبع اصلی دارای تعداد متناهی باشد و متدهای فیلترینگ (مانند Where و Distinct) در زنجیره عملیات وجود نداشته باشند. این بهینهسازی برای متدهایی مانند ToArray و متدهایی که به بافرهای میانی نیاز دارند (مانند OrderBy و Shuffle) مفید است.TryGetSpan(out ReadOnlySpan: این متد امکان دسترسی به دادهها را به عنوان حافظه پیوسته فراهم میکند، که میتواند منجر به بهبود چشمگیر عملکرد از طریق عملیات SIMD یا پردازش حلقه مبتنی بر Span شود.TryCopyTo(scoped Span: این متد عملکرد را از طریق تکرارکنندههای داخلی (internal iterators) افزایش میدهد. برخلاف CopyTo استاندارد .NET، این متد شامل Index offset است و به destination اجازه میدهد که از منبع کوچکتر باشد، که امکان پوشش موارد بهینهسازی بیشتری را با یک متد واحد فراهم میکند، به عنوان مثال برای نمایش ElementAt، First و Last.Span و ReadOnlySpan فراهم میکند. این قابلیت با معرفی ویژگی allows ref struct در C# 13 و .NET 9 ممکن شده است، که به ZLinq اجازه میدهد Span و IEnumerable را به طور یکسان پردازش کند.Sum، Max، Min، Contains و SequenceEqual استفاده میکند. این بهینهسازی با بهرهگیری از IValueEnumerator.TryGetSpan به مجموعههایی که میتوانند به عنوان Span دسترسی پیدا کنند، اعمال میشود. ZLinq متد SumUnchecked را نیز معرفی کرده است که سریعتر از Sum استاندارد است زیرا بررسیهای سرریز (overflow checks) را انجام نمیدهد. برای عملیاتهایی که به صراحت از SIMD بهره میبرند، متد AsVectorizable() ارائه شده است که به توسعهدهندگان امکان میدهد عملیاتهای قابل اعمال SIMD را فراخوانی کنند. همچنین، VectorizedUpdate برای آرایهها و Spanها، پردازش موازی عناصر را با استفاده از SIMD فراهم میکند.LINQ to XML، ZLinq مفهوم LINQ to Tree را گسترش داده است. این ویژگی امکان عملیاتهای LINQ-مانند را بر روی ساختارهای درختی فراهم میکند. ZLinq یک رابط ITraverser تعریف کرده است که به صورت عمومی امکان دسترسی به Ancestors، Children، Descendants، BeforeSelf و AfterSelf را فراهم میآورد. ZLinq شامل پیادهسازیهای استاندارد برای FileSystem (درخت دایرکتوری)، JSON (برای JsonNode از System.Text.Json)، GameObject و Transform در Unity و Node در Godot است. این پیادهسازیها به دقت برای عملکرد و تخصیص حافظه بهینه شدهاند.