تخطَّ إلى المحتوى

الأداء

قيس في 2026-10-11 على 0.5.2. الجهاز ليس خالياً (حِمل 1.2 إلى 1.9 على أربعة خيوط)؛ السكربت يطبع الحمل قبل كل برنامج، والانحراف المذكور يبيّن أثره. الفروق الأصغر من 5% لا يُعتدّ بها.

المعالج Intel Core i3-8130U (نواتان، 4 خيوط، حتى 3.4 غ.هـ؛ L2 512 ك.ب، L3 4 م.ب)
الذاكرة والنظام 7.6 غ.ب؛ لينكس 7.1 x86_64، glibc 2.41
المجمّعات gcc 14.2 (-O2)؛ rustc 1.99 (-O)؛ ميم 0.5.2 (llvmlite 0.49، LLVM 22.1 كما يبلّغ عنه)

لإعادة القياس: python bench/run.py --rounds 3 (من المجلد الأب: .env/bin/python my_compiler/bench/run.py). البرامج في bench/: لكل برنامج نسخة ميم ونسخة C ونسخة Rust بالخوارزمية نفسها، والسكربت يتحقق أن مخرجاتها متطابقة (وكانت متطابقة في السبعة).

قيس في 2026-10-16 على 0.6.0، والحمل قبل الجولات بين 1.37 و1.72 (يطبعه السكربت). وسيط ثلاث جولات. «مبني» صار محسَّناً افتراضياً (O2)، و«-O0» بلا O2، و«native» بـ--cpu=native. المعالج كان أبطأ في هذا القياس منه في قياس 0.5.2 (C نفسه 1.09 ث للحلقة مقابل 0.76)، فالمقارنة بين الإصدارين بالنسبة إلى C لا بالثواني.

البرنامج مبني مبني -O0 مبني native حركي مباشر C Rust النسبة إلى C: 0.5.2 مبني ← 0.6.0 مبني
1. حلقة 1.00 ±0.06 1.35 0.64 1.25 1.27 1.09 0.76 0.9 ← 0.9
2. فيبوناتشي 1.03 ±0.01 1.06 1.04 0.98 1.13 0.38 0.53 4.0 ← 2.7
3. n-body 0.50 ±0.05 1.05 0.48 0.50 1.43 0.28 0.29 3.7 ← 1.8
3. n-body بأسلوب C 0.31 ±0.02 0.64 — — — 0.28 2.5 ← 1.1
4. غربال 0.34 ±0.02 0.42 0.27 0.26 0.64 0.23 0.24 1.6 ← 1.5
5. نصوص 0.46 ±0.02 0.50 0.46 0.23 0.60 0.20 0.07 2.8 ← 2.3
6. قاموس 0.37 ±0.02 0.63 0.46 0.40 0.96 0.22 0.47 2.4 ← 1.7
7. قيم مُدارة 0.105 ±0.007 0.124 0.103 0.052 0.49 — — —
  • ما صنع الفرق: حارس المكدس بدل عدّاد العودية (فيبوناتشي)، والبناء بـO2 افتراضياً (n-body والقاموس والغربال).
  • فحوص الحدود والتجاوز بعد 0.6.0 («بلا فحوص» في سكربت القياس، مبنياً بـO2): الحلقة 1.00 ← 0.77 (23%)، فيبوناتشي 1.03 ← 0.94 (9%)، n-body 0.50 ← 0.37 (26%)، الغربال 0.34 ← 0.26 (24%)، القاموس 0.37 ← 0.43 (تشويش)، النصوص والقيم المُدارة ضمن التشويش.
  • التشغيل المباشر لم يتغير (سريع الترجمة بالقرار 11)، فصار الفرق بينه وبين المبني كبيراً في البرامج الحسابية (n-body 1.43 مقابل 0.50).
  • --cpu=native يفيد الحلقة العددية وحدها بوضوح (1.00 ← 0.64)، ويبطئ القاموس هنا (0.37 ← 0.46؛ لم يُحلَّل).
  • لإعادة القياس: python bench/run.py --rounds 3.

زمن الحائط بالثواني، وسيط ثلاث جولات ± الانحراف المعياري؛ «×» نسبةً إلى C. حمل الجهاز قبل الجولات 1.3 إلى 1.9 (يطبعه السكربت قبل كل برنامج).

البرنامج مبني مبني -O حركي حركي -O مباشر C Rust
1. حلقة عددية، 300 مليون 0.71 ±0.01 (×0.9) 0.67 ±0.01 0.97 ±0.02 0.65 ±0.01 0.84 ±0.02 0.76 ±0.02 0.51 ±0.01
2. فيبوناتشي، ن=40 1.01 ±0.01 (×4.0) 0.97 ±0.02 (×3.9) 1.01 ±0.04 0.99 ±0.04 1.04 ±0.02 0.25 ±0.01 0.30 ±0.01
3. n-body 0.69 ±0.01 (×3.7) 0.35 ±0.00 (×1.9) 0.72 ±0.01 0.36 ±0.02 0.97 ±0.01 0.18 ±0.00 0.21 ±0.00
3. n-body بأسلوب C 0.45 ±0.02 (×2.5) 0.20 ±0.02 (×1.1) — — —
4. غربال 20 مليوناً 0.32 ±0.00 (×1.6) 0.29 ±0.01 (×1.5) 0.30 ±0.01 0.27 ±0.01 0.51 ±0.03 0.19 ±0.01 0.20 ±0.00
5. نصوص 0.36 ±0.01 (×2.8) 0.33 ±0.01 0.19 ±0.01 (×1.5) 0.16 ±0.01 (×1.2) 0.39 ±0.01 0.13 ±0.03 0.05 ±0.00
6. قاموس، مليون مفتاح 0.43 ±0.03 (×2.4) 0.29 ±0.02 (×1.6) 0.43 ±0.01 0.26 ±0.00 0.62 ±0.01 0.18 ±0.00 0.36 ±0.02
7. قيم مُدارة كثيرة الحركة 0.088 ±0.006 0.073 ±0.006 0.050 ±0.007 0.043 ±0.004 0.38 ±0.03 — —
  • «مبني» meem build (ساكن، musl)؛ «حركي» --dynamic (glibc)؛ «مباشر» meem برنامج.م وفيه نحو 0.25 إلى 0.30 ث ترجمةً وبدءاً.
  • «بأسلوب C» كُتبت للبرنامج 3 وحده (مصفوفات ثابتة بدل قوائم). للغربال وللقاموس اليدوي لم تُكتب: اللغة لا تعطي مصفوفة ثابتة كبيرة ولا حجز كتلة.
  • القاموس: نسخة C جدول يدوي بحجم ثابت بلا توسعة، وفي Rust HashMap القياسي؛ فليست تنفيذاً بتنفيذ.
  • الحلقة العددية حركياً بلا -O أبطأ من الساكن (0.97 مقابل 0.71) والسبب غير مقيس (الشيفرة نفسها، بنموذج عنونة آخر).

قبل وبعد (0.5.1 ثم 0.5.2)، بالأسلوب نفسه وعلى الجهاز في الحال نفسها

رابط إلى قسم «قبل وبعد (0.5.1 ثم 0.5.2)، بالأسلوب نفسه وعلى الجهاز في الحال نفسها»

«قبل» قيس ثانيةً على إيداع 0.5.1 (5d2c1f0) بالسكربت نفسه، في الساعة نفسها (حمل 1.2 إلى 1.3). الأرقام في القسم 9 قيست تحت حِمل أعلى، فلا تُقارن بهذه.

البرنامج 0.5.1 مبني 0.5.2 مبني 0.5.2 مبني -O 0.5.1 حركي 0.5.2 حركي C
1. حلقة 1.39 0.71 0.67 1.40 0.97 0.74 إلى 0.76
2. فيبوناتشي 1.40 1.01 0.97 1.39 1.01 0.25 إلى 0.26
3. n-body 0.75 0.69 0.35 0.78 0.72 0.18
3. n-body بأسلوب C 0.52 0.45 0.20 — —
4. غربال 0.34 0.32 0.29 0.36 0.30 0.18 إلى 0.19
5. نصوص 0.87 0.36 0.33 0.29 0.19 0.09 إلى 0.13
6. قاموس 0.47 0.43 0.29 0.43 0.43 0.18 إلى 0.19
7. قيم مُدارة 0.33 0.088 0.073 0.125 0.050 —

ما صنع الفرق، خطوةً خطوة:

الخطوة ما قيس بعدها
(أ) SROA وتبسيط خفيف في كل تشغيل حلقة 1.39 إلى 0.70؛ فيبوناتشي 1.40 إلى 0.99؛ n-body 0.75 إلى 0.69؛ غربال 0.34 إلى 0.31؛ قاموس 0.47 إلى 0.44؛ النصوص بلا تغيير. زمن الترجمة لم يتغير: كل_اللغة 0.429 إلى 0.443 ث (+3%)، قواميس +1%، قاموس_تجزئة -3% (أفضل 9، ضمن التشويش)
(ب) meem build -O (مسار O1) n-body 0.69 إلى 0.35؛ قاموس 0.43 إلى 0.29؛ غربال 0.32 إلى 0.29؛ فيبوناتشي 1.01 إلى 0.97 فقط. زمن البناء: كل_اللغة 0.50 إلى 0.74 ث (+47%)، قواميس 0.30 إلى 0.45 (+50%)
(ج) دمج النصوص بنسخ القطع بلا snprintf نصوص: ساكن 0.86 إلى 0.36، حركي 0.30 إلى 0.19. قيم مُدارة: ساكن 0.33 إلى 0.088، حركي 0.12 إلى 0.050

المخرجات: كل اختبارات المجمّع (556) تمرّ بلا تغيير في أي ناتج مرجعي بعد (أ) وبعد (ج)، ومنها برامج الأخطاء وبرامج الكاشف ووضع البناء.

السؤال الجواب (0.6.0)
مستوى التحسين توليد الكود بالمستوى 2. وعلى مستوى IR: التشغيل المباشر SROA ثم تبسيط التعليمات ثم تبسيط مخطط التحكم؛ وmeem build مسار O2 الكامل افتراضياً منذ 0.6.0 (و-O0 يعيده إلى التحسين الخفيف). برنامج فوق 5000 كتلة يُولَّد بالمستوى 0 بلا تحسين IR
إعدادات المعالج عامة (x86_64 الأساسي) افتراضياً؛ وmeem build --cpu=native لمعالج الجهاز (منذ 0.6.0)
الدمج (inlining) التشغيل المباشر و-O0: النداءات المعلَّمة لدوال التشغيل الصغيرة داخل الحلقات فقط. meem build (افتراضياً): دمج LLVM العام بمستوى O2. ونداءات دوال المستخدم notail: العودية الذيلية لا تصير حلقة، كي يبقى تجاوز المكدس خطأ تشغيل
إعادة معالجة الوحدة مرة واحدة بالمسار المذكور، قبل توليد الكود

(في 0.5.1 وما قبله: لا تحسين على مستوى IR إطلاقاً.)

3. لماذا يتقدم C: القياس (على 0.5.1)

رابط إلى قسم «3. لماذا يتقدم C: القياس (على 0.5.1)»

الطريقتان: عدّ التعليمات المنفَّذة (valgrind/callgrind، على بناء حركي غير مجرَّد) ومقارنة الشيفرة المولَّدة (objdump)، ثم تجارب تعدّل المجمّع للقياس فقط (bench/meem_variant.py؛ لا شيء منها في المجمّع).

البرنامج تعليمات ميم تعليمات C النسبة
2. فيبوناتشي 11.09 مليار 2.96 مليار 3.7
3. n-body 6.21 مليار 1.30 مليار 4.8
5. النصوص 2.29 مليار 0.88 مليار 2.6
6. القاموس 394 مليوناً 94 مليوناً 4.2

والتجارب (ثوانٍ، مبني ساكن):

البرنامج اليوم SROA وتبسيط مسار O1 مسار O2 O2 + معالج الجهاز بلا فحوص بلا فحوص + O2
1. حلقة 2.60 — — 1.45 1.19 3.06 1.07
2. فيبوناتشي 2.80 1.40 0.97 1.67 1.56 1.89 1.50
3. n-body 1.11 0.71 0.36 0.54 0.49 0.86 0.35
4. غربال 0.40 — — 0.26 0.26 0.44 0.23
5. نصوص 1.26 — — 1.24 1.17 1.27 1.23
6. قاموس 0.52 0.42 0.29 0.35 0.27 0.56 0.30

(«SROA وتبسيط» و«O1» قيسا جولة واحدة لثلاثة برامج.)

السبب الأول، في كل البرامج العددية: المتغيرات في الذاكرة

رابط إلى قسم «السبب الأول، في كل البرامج العددية: المتغيرات في الذاكرة»

شيفرة الحلقة (البرنامج 1) كما ولّده ميم، مقابل gcc: متغير الحلقة على المكدس والمجموع في متغير عام، وكلاهما يُقرأ من الذاكرة ويُكتب فيها في كل دورة (mov (%rsp),%rcx … incq (%rsp)؛ add (%r8,%rsi,1),%r14 ثم mov %r14,(%r8,%rsi,1))، ومعها قفزة فحص تجاوز بعد كل عملية (jo)، وفحص «القسمة على صفر» على مقسوم عليه ثابت لم يُطوَ. gcc يبقي الاثنين في مسجِّلين بلا ذاكرة ولا فحوص. هذا ما تزيله SROA/mem2reg، وهي غير مشغَّلة.

33.5 تعليمة لكل استدعاء مقابل 8.9 في C (331 مليون استدعاء). في كل استدعاء: زيادة عدّاد عمق العودية وإنقاصه (متغير عام: قراءتان وكتابتان) وفحص الحد، وثلاثة فحوص تجاوز، ومعامل ونتائج وسيطة على المكدس. نسبة الزمن (7.3) أكبر من نسبة التعليمات (3.7) لأن الكتابة في العدّاد العام وقراءته تسلسلان الاستدعاءات. وgcc يحوّل أحد الاستدعاءين إلى حلقة. أثر عدّاد العمق وحده: غير مقيس منفرداً.

كل س[ا] على قائمة: قراءة رأس القائمة، قراءة العدد، فحص الحدود، قراءة مؤشر البيانات، ثم العنصر؛ والقوائم السبع متغيرات عامة تُعاد قراءتها. المصفوفة الثابتة تحذف القراءات غير المباشرة (1.11 إلى 0.75). ورياضيات.جذر نداء دالة غير مضمَّن فيه فحص السالب (6.4% من التعليمات). مع O1: 0.36 ث، أي ×1.4 من C.

الحلقة الداخلية: فحص الحدود وقراءة رأس القائمة في كل كتابة، والعدّادان في الذاكرة. مع O2: 0.26 (×1.1)؛ ومعه بلا فحوص: 0.23، وهو زمن C.

سببان مختلفان:

  • musl (ثلثا الفرق): البرنامج نفسه 1.26 ث ساكناً و0.43 حركياً. انظر القسم 6.
  • الباقي (×2.8): 2.29 مليار تعليمة مقابل 0.88. البحث نفسه (strstr) 590 مليوناً في الاثنين. الزائد: تحويل العدد إلى نص ودمج القطع يمرّان بـsnprintf (نحو 800 مليون تعليمة في آلة printf، مقابل نداء واحد في C)، ونصان مؤقتان يُحجزان ويُعادان في كل دورة، وطول يعدّ الأحرف بالمرور على النص كله في كل استدعاء. تحسينات IR لا تغيّر شيئاً هنا (1.24 مع O2): الزمن في مكتبة التشغيل ومكتبة C.

45% من التعليمات في دالة تحديد الموضع و12% في دالة التجزئة، وكلتاهما نداء غير مضمَّن (سمة التضمين عليهما لا تُنفَّذ إلا إن عمل مسار التضمين، وهو لا يعمل لهذا البرنامج). مع O1: 0.29 ث (×1.4)؛ مع O2 ومعالج الجهاز: 0.27. و5% في إعادة بناء الفهارس عند التوسعة، وهي كلفة جدول يكبر (نسخة C بحجم ثابت).

4. أهم التحسينات الممكنة (كما قُدّرت على 0.5.1؛ الأول والثاني والخامس نُفّذت)

رابط إلى قسم «4. أهم التحسينات الممكنة (كما قُدّرت على 0.5.1؛ الأول والثاني والخامس نُفّذت)»
التحسين الأثر المقيس الكلفة
تشغيل SROA وتبسيط خفيف على IR قبل توليد الكود فيبوناتشي 2.80 إلى 1.40؛ n-body 1.11 إلى 0.71؛ قاموس 0.52 إلى 0.42. وزمن الترجمة ينقص: كل_اللغة 0.87 إلى 0.55 ث، قاموس_تجزئة 0.86 إلى 0.77 (مولّد الشيفرة يستلم تعليمات أقل) سطور قليلة في finish_module. يلزمه تشغيل المجموعة والبذور كلها (يغيّر الشيفرة المولَّدة لكل برنامج)، ومراجعة رسائل أخطاء التشغيل
مسار O1 كاملاً (فيه التضمين) فيبوناتشي 0.97 (×2.5 من C)؛ n-body 0.36 (×1.4)؛ قاموس 0.29 (×1.4) زمن الترجمة يزيد: كل_اللغة 0.87 إلى 1.11 ث (+27%)، قواميس 0.42 إلى 0.83 (+97%)، قاموس_تجزئة +64%. يتجاوز حدّ الـ15% المعتمد: يصلح لـmeem build (خيار -O) لا للتشغيل المباشر
معالج الجهاز في التشغيل المباشر فوق O2: حلقة 1.45 إلى 1.19؛ قاموس 0.35 إلى 0.27؛ الباقي ضمن التشويش سطر. لا يصلح للملف المبني الذي يُنقل إلى جهاز آخر إلا بخيار صريح
سعة النص في رأسه بدل الاعتماد على سعة كتلة malloc يُتوقع أن يزيل أغلب فرق musl في النصوص (1.26 مقابل 0.43): تقدير، غير مقيس متوسطة: حقل في رأس النص، ومراجعة كل من يقرأ الرأس
تحويل العدد إلى نص بلا snprintf يزيل نحو ثلث تعليمات برنامج النصوص: تقدير من عدّ التعليمات صغيرة: دالة تشغيل للأعداد الصحيحة
تخفيف حارس عمق العودية (عدّاد في مسجِّل أو فحص عنوان المكدس) غير مقيس منفرداً متوسطة؛ يمسّ رسالة «تجاوز عمق العودية»
حذف فحوص الحدود التي تُثبَت (فهرس حلقة مدى(0, طول)) حدّها الأعلى ما في القسم 5 يأتي جزء منه مع مسارات IR؛ الباقي تحليل في المجمّع

5. كلفة فحوص التشغيل (النسبة الحقيقية بعد 0.5.2)

رابط إلى قسم «5. كلفة فحوص التشغيل (النسبة الحقيقية بعد 0.5.2)»

التجربة: فحص حدود الفهرسة موقوف (تعديل تجريبي) وفحص التجاوز موقوف (--wrap-overflow). فحوص القسمة على صفر والمؤشر الفارغ وعمق العودية باقية.

البرنامج مبني بلا فحوص الكلفة مبني -O بلا فحوص -O الكلفة
1. حلقة 0.708 0.705 0% 0.665 0.671 0%
2. فيبوناتشي 1.006 1.041 0% 0.970 1.002 0%
3. n-body 0.686 0.515 25% 0.353 0.321 9%
4. غربال 0.315 0.378 0% (أبطأ بلا فحوص: تشويش أو ترتيب الشيفرة) 0.289 0.269 7%
5. نصوص 0.362 0.361 0% 0.328 0.320 2%
6. قاموس 0.433 0.440 0% 0.290 0.255 12%
7. قيم مُدارة 0.088 0.084 5% 0.073 0.069 5%

الخلاصة: الفحوص تكلّف ما بين صفر و12% في ستة من سبعة، و25% في برنامج واحد كثير الفهرسة على قوائم قصيرة داخل حلقة (n-body)، تنزل إلى 9% مع -O (المسار يحذف المكرر منها). الانحراف في هذه القياسات 1% إلى 5%.

«بلا عدّ» نسخة تجريبية لا تزيد ولا تنقص، فلا تحرّر شيئاً (كل قيمة تتسرّب): هي «نسخة افتراضية بلا عدّ» من حيث التعليمات، وأسوأ من حيث الذاكرة.

البرنامج زيادات نقصانات اليوم بلا عدّ ذاكرة الذروة: اليوم / بلا عدّ
بلا قيم مُدارة (1، 2) 0 0 2.60 / 2.80 3.09 / 2.55 12 / 12 م.ب
نصوص كثيرة (5) 0 808,043 1.26 1.17 12 / 141 م.ب
قوائم وقواميس ونصوص متحركة (7) 1,500,200 2,096,302 0.51 0.57 12 / 25 م.ب
n-body، غربال، قاموس أعداد (3، 4، 6) 0 9، 1، 1 — مثل اليوم —
  • برنامج بلا قيم مُدارة لا يدفع شيئاً: صفر عملية (الفرق في الجدول تشويش).
  • الكلفة في البرنامجين المُدارَين أصغر من تشويش القياس؛ «بلا عدّ» ليس أسرع (والتسريب يكلّفه حجزاً من النظام). تقدير من العدد: 3.6 مليون عملية في البرنامج 7، كل منها قراءة وكتابة وقفزة، نحو 1 إلى 2 نانوثانية، أي 4 إلى 7 مللي ثانية من 510 (نحو 1%). الزمن في الحجز والتحرير، لا في العدّ.
  • ما يحذفه تحليل ثابت، تقديراً (غير منفَّذ):
    • البرنامج 7، لكل دورة داخلية 5 زيادات و7 نقصانات. ثلاثة متغيرات محلية (ن، م، صف) تأخذ قيمة مستعارة من حاوية لا تتغير ما دامت تُستعمل ثم تتركها: زيادة ونقصان لكلٍّ، أي 3 من 5 زيادات و3 من 7 نقصانات (نحو النصف) يحذفها تحليل «محلي مستعار لا يهرب». الباقي تحرير مؤقتات (نص المفتاح) وتخزين في حاوية: لازم.
    • البرنامج 5: النقصانات كلها تحرير نصين مؤقتين في كل دورة. لا يُحذف منها شيء بتحليل؛ يحذفها بناء النص بلا مؤقتات.
    • النقل (move) مطبَّق اليوم للقيمة المملوكة تُسند إلى موضع. تمرير الوسائط بلا عدّ مطبَّق (المعاملات مستعارة).

7. musl مقابل glibc: ما كان السبب، وما اختير

رابط إلى قسم «7. musl مقابل glibc: ما كان السبب، وما اختير»

في 0.5.1 كان الملف الساكن (musl) أبطأ ثلاثة أضعاف من الحركي في البرامج النصية والكثيرة الحجز. القياس، لا الظن:

1. عزل الأنماط (0.5.1، ثوانٍ):

النمط ساكن حركي ×
إلحاق بنص، 30 مليون مرة (بلا حجز جديد) 10.27 3.12 3.3
نصوص مؤقتة، 4 ملايين 4.09 1.11 3.7
تقسيم نص كبير 0.82 0.29 2.8
قوائم صغيرة تُنشأ وتُترك، مليونان 0.41 0.17 2.5
اضف لقائمة أعداد، 30 مليوناً 0.24 0.24 1.0

الإلحاق لا يحجز ومع ذلك أبطأ ثلاث مرات: فالمخصص ليس السبب الأول.

2. ربط mimalloc ساكناً بدل مخصص musl (تجربة يدوية بمكتبة ألباين 3.20): الإلحاق 10.23 إلى 9.89، المؤقتات 4.05 إلى 3.68، برنامج النصوص 0.84 إلى 0.67. تحسّن صغير، والفرق عن glibc باقٍ.

3. عدّ التعليمات في حلقة الإلحاق: 55% منها في آلة printf (‏snprintf تُستدعى مرتين لكل دمج أو إلحاق: مرة للطول ومرة للكتابة). وsnprintf في musl أبطأ منها في glibc بمراتب. هذا السبب.

ما نُفّذ: دمج النصوص والإلحاق ينسخان القطع بـmemcpy (طول النص من رأسه، والعدد الصحيح بدالة تحويل في مكتبة التشغيل)، بلا snprintf. لا اعتماد جديد، ويفيد المكتبتين، والنواتج المرجعية كلها لم تتغير.

النمط ساكن قبل ساكن بعد حركي قبل حركي بعد
إلحاق بنص 10.27 2.08 3.12 0.93
نصوص مؤقتة 4.09 0.95 1.11 0.33
تقسيم نص كبير 0.82 0.32 0.29 0.15
برنامج النصوص (5) 0.86 0.36 0.30 0.19
قيم مُدارة (7) 0.33 0.088 0.12 0.050
قوائم صغيرة 0.41 0.41 0.17 0.17

الحلول الأربعة المقترحة سابقاً، وما قاله القياس:

الحل الحكم السبب
سعة النص في رأسه مرفوض الإلحاق يضاعف السعة أصلاً، ومخصص سريع الاستعلام عن السعة (mimalloc) لم يسرّع الإلحاق: ليست السعة ما يكلّف
مخصص صغير مضمَّن في الشيفرة المولَّدة مؤجَّل أثره محدود بما أظهره mimalloc (القوائم الصغيرة والتقسيم)، ومخاطرته أعلى الأربعة (يمسّ كل حجز وتحرير والكاشف)
ربط mimalloc ساكناً لم يُنفَّذ؛ قرار عند مالك اللغة بعد الإصلاح يسدّ أغلب الباقي: قوائم صغيرة 0.45 إلى 0.06، تقسيم 0.32 إلى 0.15، نصوص 0.35 إلى 0.20، قيم مُدارة 0.087 إلى 0.062. لكنه يضاعف زمن اضف لقائمة كبيرة (0.23 إلى 0.47) ويبطئ القاموس قليلاً (0.43 إلى 0.46)، ويكبّر كل ملف مبني من نحو 40 إلى 175 ك.ب، ويضيف رخصة (MIT) وتنزيلاً مثبَّتاً آخر
تدوين أن --dynamic أسرع قائم الجدول أعلاه

الباقي بعد الإصلاح: الساكن ما زال أبطأ من الحركي 1.8 إلى 2.9 مرة في الأنماط النصية والكثيرة الحجز (برنامج النصوص 0.36 مقابل 0.19). جزء منه المخصص (ما يسدّه mimalloc)، وجزء في الإلحاق الخالص (2.08 مقابل 0.93، ولا يتغير مع mimalloc) سببه غير مقيس (المرشَّح: memcpy وmalloc_usable_size في musl). الافتراضي بقي الساكن.

  • على جهاز هادئ: لا. الأرقام وسيط ثلاث جولات تحت حِمل.
  • معالجات أخرى، وARM: لا.
  • أثر عدّاد عمق العودية منفرداً، ونسبة سببَي musl، وأطول توقف عند تحرير بنية كبيرة: لا.
  • --debug-mem: كلفته لم تُقس هنا.
  • برامج حقيقية (لا معيارية صغيرة): لا.
  • بعد 0.5.2: لم يُعَد عدّ التعليمات (callgrind)، ولم يُحلَّل لماذا بقي فيبوناتشي عند ×4 (المرشَّح: عدّاد عمق العودية في متغير عام)، ولا الباقي من فرق musl في الإلحاق الخالص.

للسجل: قياس 0.5.1 الأول جرى تحت حِمل 2.3 إلى 2.9 فجاءت أزمنته كلها أكبر (C نفسه 1.96 ث للحلقة مقابل 0.74 هنا). نِسَبه إلى C كانت: حلقة 1.3، فيبوناتشي 7.3، n-body 4.2، غربال 1.7، نصوص 8.4 (ساكن) و2.8 (حركي)، قاموس 2.6. جدولا القسمين 3 و4 من ذلك القياس.