هناك نوعان من لغات البرمجة: لغات البرمجة التي تجمع المهملات ولغات البرمجة التي تتطلّب إدارة الذاكرة يدويًا. ومن الأمثلة على هذه الفئة، من بين غيرها الكثير، Kotlin أو PHP أو Java. ومن أمثلة الأخير هي C أو C++ أو Rust. كقاعدة عامة، من المرجّح أن تتضمّن لغات البرمجة ذات المستوى الأعلى ميزة جمع المهملات كميزة قياسية. في هذه المشاركة على المدوّنة، يتم التركيز على لغات البرمجة التي تتضمّن ميزة جمع المهملات وكيفية تجميعها إلى WebAssembly (Wasm). ولكن ما هو جمع المهملات (المعروف غالبًا باسم GC)؟
توافق المتصفّح
جمع البيانات المهملة
بعبارات مبسطة، فكرة جمع البيانات المهملة هي محاولة استرداد الذاكرة التي خصصها البرنامج، ولكن لم تعد تتم الإشارة إليها. تُسمّى هذه الذاكرة "المهملات". هناك العديد من الاستراتيجيات لتنفيذ عملية جمع البيانات غير المرغوب فيها. ومن هذه الطرق احتساب عدد الإشارات حيث يكون الهدف هو احتساب عدد الإشارات إلى العناصر في الذاكرة. عندما لا تتوفّر أيّ إشارات إلى عنصر، يمكن وضع علامة عليه بأنّه لم يعُد مُستخدَمًا، وبالتالي يكون جاهزًا لجمع المهملات. يستخدِم برنامج جمع المهملات في 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. Zend Engine هو برنامج ترميز وبيئة تشغيل للغة البرمجة PHP. وتتكوّن من Zend Virtual Machine (الآلة الافتراضية)، التي تتكوّن من Zend Compiler وZend Executor. غالبًا ما يكون للغات مثل PHP التي يتم تنفيذها بلغات أخرى عالية المستوى مثل C تحسينات تستهدف بُنى محددة، مثل Intel أو ARM، وتتطلب خلفية مختلفة لكل بنية. في هذا السياق، يمثّل Wasm بنية جديدة. إذا كان الجهاز الافتراضي يتضمّن رمزًا برمجيًا خاصًا بالبنية، مثل التجميع في الوقت المناسب (JIT) أو تجميع البيانات في وقت مبكر (AOT)، سينفّذ مطوّر البرامج أيضًا خلفية لتقنية JIT/AOT للبنية الجديدة. ويُعدّ هذا النهج منطقيًا جدًا لأنّه في أغلب الأحيان يمكن إعادة تجميع الجزء الرئيسي من قاعدة البيانات لكل بنية جديدة.
نظرًا لمستوى Wasm المنخفض، من الطبيعي تجربة النهج نفسه هنا: إعادة تجميع رمز وحدة المحاكاة الافتراضية الرئيسية مع المُحلِّل ودعم المكتبة وجمع المهملات والمحسِّن إلى 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. لا يمكن لتنفيذ Wasm MVP الحالي التعامل إلا مع الأرقام، أي الأعداد الصحيحة والكسور العشرية، في الذاكرة الخطية، ومع اقتراح أنواع المراجع الذي يتم إرساله، يمكن لـ Wasm الاحتفاظ أيضًا بالمراجع الخارجية. يضيف WasmGC الآن أنواعًا من كومة الذاكرة إلى النظام والصفيف، ما يعني إتاحة تخصيص الذاكرة غير الخطية. يحتوي كل عنصر WasmGC على نوع وبنية ثابتَين، ما يسهّل على الأجهزة الافتراضية إنشاء رمز برمجي فعّال للوصول إلى حقولها بدون المخاطرة بإلغاء التحسين الذي توفّره اللغات الديناميكية، مثل JavaScript. وبالتالي، يضيف هذا الاقتراح دعمًا فعّالاً للغات المُدارة عالية المستوى إلى WebAssembly، وذلك من خلال أنواع هياكل البيانات وأنواع أكوام الصفائف التي تتيح لمُجمِّعي اللغات الذين يستهدفون Wasm الدمج مع أداة جمع المهملات في الآلة الافتراضية المضيف. بعبارة مبسطة، يعني ذلك أنّ استخدام WasmGC لنقل لغة برمجة إلى Wasm يعني أنّه لم يعد من الضروري أن يكون أداة جمع المهملات في لغة البرمجة جزءًا من عملية النقل، بل يمكن استخدام أداة جمع المهملات الحالية بدلاً من ذلك.
للتأكّد من التأثير الفعلي لهذا التحسين، جمع فريق Wasm في Chrome إصدارات من مقياس أداء Fannkuch (الذي يخصّص بنى البيانات أثناء عمله) من C وRust وJava. يمكن أن تتراوح أحجام الملفات الثنائية لـ C وRust بين 6.1 كيلوبايت و9.6 كيلوبايت، وذلك استنادًا إلى علامات المُجمِّع المختلفة، في حين أنّ حجم إصدار Java أصغر بكثير، إذ يبلغ 2.3 كيلوبايت فقط. لا يشتمل C وRust على أداة تجميع البيانات المهملة، ولكن لا يزالان يجمعان 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. لمزيد من المعلومات عن هذه الميزة، راجع الروابط التالية:
- طريقة جديدة لاستخدام لغات البرمجة التي تتضمّن ميزة جمع المهملات بكفاءة في WebAssembly
- نظرة عامة على WasmGC
- WasmGC MVP
- WasmGC بعد إطلاق المنتج النموذجي
شكر وتقدير
تمت مراجعة هذه المقالة من قِبل ماتياس ليدتك وآدم كلاين وجوشوا بيل وألون زاكي وجاكوب كوميروف وكليمنتس باكيس وإيمانويل زيغلر وراشيل أندرو.