ترتيب إضافة الخصائص في الكائنات يغيّر الـ shape في الذاكرة وقد يضاعف الفرق في الأداء
نشر Max Bernstein في 21 أكتوبر 2026 مقالة تشرح آلية تعمل في لغات مثل Ruby وJavaScript دون أن يراها المبرمج، وتُعرف بالـ object shapes، وقد تؤثر بوضوح في سرعة الكود.
والطريقة الأبسط لتمثيل الكائن أن يحمل كل object جدول hash بأسماء خصائصه وقيمها. لكن كل وصول إلى خاصية مثل a.b يكلّف حينها سلسلة من التعليمات والقراءات من الذاكرة. ولذلك تفصل الـ runtimes الفعلية، مثل V8 وJavaScriptCore، بين وصف الكائن وقيمه. فالوصف، أي الـ shape، ويسمى أيضًا map أو hidden class، يربط اسم كل خاصية برقم موقعها، بينما تُخزّن القيم في مصفوفة مسطحة.
والـ shapes ثابتة لا تتغير ومشتركة بين الكائنات. فكل object جديد يبدأ بـ shape فارغ، وكلما أضيفت إليه خاصية ينتقل إلى shape آخر في شجرة من الأشكال. وفوق ذلك يعمل الـ inline cache: موضع الاستدعاء في الكود يتذكر آخر shape رآه ورقم الموقع، فإذا جاءه كائن بالـ shape نفسه قرأ القيمة من موقعها مباشرة. وهذه المقارنة سريعة لأن الـ shapes لا تتغير، فيكفي التحقق من أنهما الشيء نفسه.
ومن هنا يأتي الأثر العملي. فإضافة الخاصية a ثم b تنتج shape مختلفًا عن إضافة b ثم a. والأمر نفسه يحدث حين تُضاف خاصية داخل شرط، فتنتج الفروع المختلفة أشكالًا مختلفة. وبحسب المقالة، قد يصل الفرق بين إصابة الـ cache وإخفاقه في مسار ساخن من الكود إلى ضعف الأداء أو أكثر.
ولا يعني ذلك إعادة كتابة الكود. لكن في constructor يُستدعى ملايين المرات، يصبح تثبيت ترتيب تهيئة الخصائص تحسينًا بلا تكلفة. والمشكلة لا تظهر عند قراءة الكود، بل في الـ profiler فقط. وتستخدم المقالة Python للتوضيح، مع أنها لا تسمح بالتحكم في شكل الذاكرة، وتقدم النموذج الأقرب للواقع بلغة C++.