تم تفعيل WebAssembly Garbage Group (WasmGC) الآن بشكل تلقائي في Chrome.

هناك نوعان من لغات البرمجة: لغات البرمجة التي يتم جمعها من البيانات المهملة ولغات البرمجة التي تتطلب إدارة يدوية للذاكرة. ومن الأمثلة على التعليقات السابقة، من بين أمثلة أخرى، Kotlin أو PHP أو Java. ومن الأمثلة على هذه المستندات C أو C++ أو Rust. كقاعدة عامة، من المرجح أن يكون لدى لغات البرمجة ذات المستوى الأعلى مجموعة بيانات غير صحيحة كميزة قياسية. في منشور المدونة هذا، ينصب التركيز على لغات البرمجة التي تم جمعها من البيانات غير المرغوب فيها وكيفية تجميعها إلى WebAssembly (Wasm). ولكن ما الذي نبدأ به لجمع البيانات المهملة (غالبًا ما يشار إليها باسم تجميع البيانات المهملة)؟

التوافق مع المتصفح

  • 119
  • 119
  • 120
  • x

جمع القمامة

وبمصطلحات مبسطة، فإن فكرة جمع البيانات المهملة هي محاولة استعادة الذاكرة التي تم تخصيصها بواسطة البرنامج، ولكن لم تعد تتم الإشارة إليها. تُسمى هذه الذاكرة القمامة. هناك العديد من الاستراتيجيات لتنفيذ عملية جمع البيانات غير المرغوب فيها. أحدها هو احتساب المراجع، حيث يكون الهدف هو احتساب عدد المراجع إلى العناصر في الذاكرة. عندما لا يكون هناك المزيد من المراجع إلى كائن، يمكن وضع علامة عليه بأنه لم يعد مستخدمًا وبالتالي جاهز لجمعه غير المهم. تستخدم أداة تجميع البيانات غير المرغوب فيها في PHP حساب المراجع، واستخدام وظيفة xdebug_debug_zval() في إضافة Xdebug تتيح لك إلقاء نظرة سريعة على التفاصيل. ضع في الاعتبار برنامج PHP التالي.

<?php
  $a= (string) rand();
  $c = $b = $a;
  $b = 42;
  unset($c);
  $a = null;
?>

يعيّن البرنامج رقمًا عشوائيًا يتم تحويله إلى سلسلة إلى متغيّر جديد يُسمى a. ثم تنشئ متغيّرَين جديدَين، هما b وc، وتحدّد لهما القيمة a. بعد ذلك، يعيد تعيين b إلى الرقم 42، ثم يُبطل ضبط c. وأخيرًا، يتم ضبط قيمة a على null. من خلال إضافة تعليقات توضيحية إلى كل خطوة من خطوات البرنامج باستخدام xdebug_debug_zval()، يمكنك الاطّلاع على العدّاد المرجعي لجمع البيانات غير المرغوب فيها في العمل.

<?php
  $a= (string) rand();
  $c = $b = $a;
  xdebug_debug_zval('a');
  $b = 42;
  xdebug_debug_zval('a');
  unset($c);
  xdebug_debug_zval('a');
  $a = null;
  xdebug_debug_zval('a');
?>

سينتج عن المثال السابق السجلّات التالية، حيث ترى كيف ينخفض عدد المراجع إلى قيمة المتغير a بعد كل خطوة، وهو أمر منطقي وفقًا لتسلسل الرمز. (سيكون الرقم العشوائي مختلفًا بالطبع.)

a:
(refcount=3, is_ref=0)string '419796578' (length=9)
a:
(refcount=2, is_ref=0)string '419796578' (length=9)
a:
(refcount=1, is_ref=0)string '419796578' (length=9)
a:
(refcount=0, is_ref=0)null

هناك تحديات أخرى متعلّقة بجمع البيانات غير المرغوب فيها، مثل رصد الدورات التدريبية، ولكن في هذه المقالة، يكفي الحصول على مستوى أساسي من فهم طريقة احتساب المراجع.

يتم تنفيذ لغات البرمجة بلغات برمجة أخرى

قد يبدو الأمر وكأنها بداية، لكن لغات البرمجة يتم تنفيذها بلغات برمجة أخرى. على سبيل المثال، يتم تطبيق وقت تشغيل PHP بشكل أساسي بلغة C. يمكنك الاطلاع على رمز مصدر PHP على GitHub. يوجد رمز مجموعة البيانات المهملة للغة PHP بشكل أساسي في الملف zend_gc.c. سيقوم معظم المطورين بتثبيت لغة PHP عبر مدير الحزم في نظام التشغيل الذي يستخدمونه. ولكن يستطيع المطوّرون أيضًا إنشاء لغة PHP من رمز المصدر. على سبيل المثال، في بيئة Linux، تنشئ الخطوات ./buildconf && ./configure && make لغة PHP في وقت تشغيل Linux. غير أن هذا يعني أيضًا أنه يمكن تجميع وقت تشغيل PHP مع أوقات تشغيل أخرى، مثل Wasm كما خمنت.

الطرق التقليدية لنقل اللغات إلى وقت تشغيل Wasm

وبشكلٍ مستقل عن النظام الأساسي الذي يعمل عليه لغة PHP، يتم تجميع النصوص البرمجية للغة PHP في رمز البايت نفسه ويتم تشغيلها بواسطة Zend Engine. Zend Engine عبارة عن بيئة برنامج تجميع ووقت تشغيل للغة البرمجة النصية PHP. وهو يتألّف من جهاز Zend الافتراضي (VM) الذي يتكوّن من برنامج التجميع من Zend وأداة Zend التنفيذية. عادةً ما تشتمل اللغات مثل PHP التي يتم تنفيذها بلغات أخرى عالية المستوى مثل C على تحسينات تستهدف بنية معيَّنة، مثل Intel أو ARM، وتتطلب خلفية مختلفة لكل بنية. في هذا السياق، يمثل Wasm بنية جديدة. إذا كان الجهاز الافتراضي يحتوي على رمز برمجي خاص بالبنية، مثل التجميع في الوقت الفعلي (JIT) أو التجميع المسبق (AOT)، سينفّذ مطوّر البرامج أيضًا خلفيةً لنظام JIT/AOT للبنية الجديدة. هذا النهج له معنى كبير لأنه في كثير من الأحيان يمكن إعادة تجميع الجزء الرئيسي من قاعدة التعليمات البرمجية لكل بنية جديدة.

نظرًا إلى انخفاض مستوى Wasm، من الطبيعي أن تجرِّب الطريقة نفسها هناك: إعادة تجميع رمز الجهاز الافتراضي (VM) الرئيسي باستخدام محلّل الجهاز الافتراضي، ودعم المكتبة، وجمع البيانات غير المرغوب فيها، وأداة التحسين إلى Wasm، وتنفيذ خلفية JIT أو AOT لـ Wasm إذا لزم الأمر. وقد أصبح ذلك ممكنًا منذ أن أصبح Wasm MVP، وهو يعمل بشكل جيد في العديد من الحالات. في الواقع، إنّ لغة PHP مجمّعة في Wasm هي التي تعزّز WordPress Playground. تعرّف على المزيد من المعلومات عن المشروع في المقالة إنشاء تجارب على WordPress في المتصفّح باستخدام WordPress Playground وWebAssembly.

ومع ذلك، يتم تشغيل لغة PHP Wasm في المتصفح في سياق JavaScript للغة المضيف. في Chrome، يتم تشغيل JavaScript وWasm في V8، وهو محرّك JavaScript مفتوح المصدر من Google ينفِّذ ECMAScript على النحو المحدّد في ECMA-262. ويتضمن V8 أداة تجميع البيانات غير المرغوب فيها. وهذا يعني أنّ المطوّرين الذين يستخدمون، على سبيل المثال، لغة PHP المجمَّعة في Wasm، ينتهي بها الأمر بشحن أداة تجميع البيانات المهملة في اللغة المنقولة (PHP) إلى المتصفّح الذي يحتوي على أداة تجميع البيانات المهملة، والتي تبدو هدرًا كما يبدو. وهنا يأتي دور WasmGC.

المشكلة الأخرى المتمثلة في النهج القديم المتمثل في السماح لوحدات Wasm بإنشاء تجميع البيانات المهملة الخاصة بها فوق ذاكرة Wasm الخطية هي أنّه لا يوجد تفاعل بعد ذلك بين أداة تجميع البيانات المهملة في Wasm ووحدة تجميع البيانات المهملة المدمجة في لغة Wasm المجمّعة، ما ينتج عنه مشاكل مثل تسرُّب الذاكرة ومحاولات التجميع غير الفعّالة. يؤدي السماح لوحدات Wasm بإعادة استخدام وحدة تجميع المعلومات (GC) المضمّنة الحالية إلى تجنُّب هذه المشاكل.

نقل لغات البرمجة إلى أوقات تشغيل جديدة من خلال WasmGC

WasmGC هو اقتراح من WebAssembly Community Group. إنّ طريقة Wasm الحالية قادرة على التعامل مع الأرقام، أي الأعداد الصحيحة والأعداد العشرية، في الذاكرة الخطية. وبفضل اقتراح أنواع المراجع الذي يجري شحنه، تستطيع Wasm أيضًا الاحتفاظ بالمراجع الخارجية. يضيف WasmGC الآن أنواع حزم البنية والصفيف، ما يعني إتاحة تخصيص الذاكرة غير الخطي. لكل كائن WasmGC نوع وبنية ثابتة، ما يسهِّل على الأجهزة الافتراضية إنشاء رمز فعال للوصول إلى حقولها بدون المخاطرة بإلغاء التحسين الذي توفّره اللغات الديناميكية، مثل JavaScript. بناءً على ذلك، يوفّر هذا الاقتراح دعمًا فعّالاً للّغات المُدارة ذات المستوى العالي في WebAssembly، من خلال أنواع من البنية والصفيفة التي تتيح لبرامج التجميع اللغوي التي تستهدف Wasm الدمج مع أداة تجميع البيانات المهملة في الجهاز الافتراضي المضيف. ويعني ذلك أنه من خلال WasmGC، يعني نقل لغة البرمجة إلى Wasm أنّه لم يعد من الضروري أن تكون وحدة تجميع البيانات المهملة في لغة البرمجة جزءًا من المنفذ، ولكن يمكن استخدام أداة تجميع البيانات المهملة الحالية.

للتحقق من التأثير الفعلي لهذا التحسين، جمّع فريق Wasm في Chrome إصدارات من مقياس Fannkuch (الذي يخصّص هياكل البيانات أثناء عمله) من C وRust وJava. وتتراوح قيم البرامج الثنائية C وRst على أي قيمة من 6.1 ألف إلى 9.6 ألف اعتمادًا على مختلف علامات برنامج التجميع، في حين أن إصدار جافا أصغر بكثير من 2.3 ألف. لا يشتمل C وRst على أداة تجميع البيانات المهملة، ومع ذلك لا يزالان يدمجان malloc/free لإدارة الذاكرة، والسبب في صغر حجم Java هو عدم الحاجة إلى تجميع أي رمز لإدارة الذاكرة على الإطلاق. هذا مجرد مثال واحد محدد، لكنه يوضح أن ثنائيات WasmGC لديها إمكانية أن تكون صغيرة جدًا، وهذا حتى قبل أي عمل مهم على تحسين الحجم.

رؤية استخدام لغة برمجة مستندة إلى WasmGC

لغة Kotlin Wasm

من أوائل لغات البرمجة التي تم نقلها إلى Wasm بفضل WasmGC هي لغة Kotlin في شكل Kotlin/Wasm. يظهر العرض التوضيحي في البيانات التالية، مع رمز المصدر الذي قدّمه فريق Kotlin.

import kotlinx.browser.document
import kotlinx.dom.appendText
import org.w3c.dom.HTMLDivElement

fun main() {
    (document.getElementById("warning") as HTMLDivElement).style.display = "none"
    document.body?.appendText("Hello, ${greet()}!")
}

fun greet() = "world"

قد تتساءل الآن عن المقصود بالمهمة، لأنّ رمز Kotlin أعلاه يتكوّن بشكل أساسي من واجهات برمجة تطبيقات JavaScript OM التي تم تحويلها إلى Kotlin. بدأ الأمر يبدو أكثر منطقية بالاقتران مع Compose Multiplatform، التي تتيح للمطوّرين الاعتماد على واجهة المستخدم التي ربما سبق لهم إنشاؤها لتطبيقات Android Kotlin. يمكنك الاطّلاع على استكشاف مبكر لهذا الأمر من خلال العرض التوضيحي لعارض صور Kotlin/Wasm واستكشاف رمز المصدر الخاص به، وكذلك شرحه من قِبل فريق Kotlin.

لعبة Dart وFlutter

يعمل فريقا Dart وFlutter في Google أيضًا على إعداد الدعم لأداة WasmGC. أوشكت عملية تجميع Dart-to-Wasm على الانتهاء، ويعمل الفريق على توفير الأدوات اللازمة لتقديم تطبيقات الويب من Flutter التي تم جمعها باستخدام WebAssembly. يمكنك الاطّلاع على الحالة الحالية للعمل في مستندات Flutter. العرض التوضيحي التالي هو معاينة Flutter WasmGC.

مزيد من المعلومات حول WasmGC

بالكاد ساعدت مشاركة المدونة هذه في تقديم نظرة عامة عالية المستوى على WasmGC. لمعرفة المزيد حول الميزة، راجع الروابط التالية:

شكر وتقدير

صورة رئيسية من تصوير غاري تشان على UnLaunch. راجع هذه المقالة ماتياس ليدتك وآدم كلاين وجوشوا بيل وألون زاكاي وجاكوب كومرو وكليمنس باكس وإيمانويل زيغلر وراشيل أندرو.