Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon ما هي الآثار المترتبة على الأداء لاستخدام Push vs Concat في المصفوفات الكبيرة


ما هي الآثار المترتبة على الأداء لاستخدام Push vs Concat في المصفوفات الكبيرة


تنشأ الآثار المترتبة على الأداء المترتبة على استخدام Push مقابل Concat في المصفوفات الكبيرة في المقام الأول من الطرق المختلفة التي تتعامل بها هذه الطرق في دمج Array أو إضافة العنصر ، بالإضافة إلى إدارة الذاكرة الأساسية والنفقات العامة الحسابية.

عند استخدام Array.push ، يتم إلحاق عناصر من صفيف واحد مباشرة إلى الصفيف الحالي. بالنسبة لدمج المصفوفات ، يتضمن ذلك غالبًا نمطًا مثل استخدام تطبيق أو مشغل الانتشار لدفع عناصر متعددة في وقت واحد على سبيل المثال ، Array.Prototype.push.apply (ARR1 ، ARR2). يعدل هذا النهج الصفيف الأصلي في مكانه ويؤدي عمومًا في الوقت الخطي ، O (n) ، حيث N هو عدد العناصر التي يتم دفعها. والسبب هو أن الدفع عادة ما يلحق العناصر إلى نهاية الصفيف الحالي دون إنشاء صفيف جديد أو نسخ المحتويات بأكملها بشكل متكرر. نظرًا لهذه الطفرة في مكانها ، يتم تقليل النفقات العامة للذاكرة ، وغالبًا ما تستغل الطريقة كتل الذاكرة المتجاورة المحسنة وموقع ذاكرة التخزين المؤقت ، مما يقلل من تكلفة الوصول إلى الذاكرة.

في المقابل ، لا يقوم Array.Concat بتعديل المصفوفات الأصلية. بدلاً من ذلك ، فإنه ينشئ صفيفًا جديدًا يحتوي على عناصر المصفوفات الأصلية المتسلسلة معًا. يتضمن إنشاء هذه المجموعة الجديدة تخصيص الذاكرة للحجم المشترك للصفائف وعناصر النسخ من كلا المصفوفات المصدر إلى هذه المساحة المخصصة حديثًا. يقدم هذا النسخ النفقات العامة التي تتناسب عمومًا مع حجم كلا الصيفين ، مما يجعل تعقيد وقت العملية O (M + N) ، حيث يتم تسلسل M و N من أحجام المصفوفات. يؤدي إنشاء مجموعة جديدة ونسخ إلى زيادة استخدام الذاكرة واحتمال أعلى لإحداث جمع القمامة ، وخاصةً مع المصفوفات الكبيرة جدًا.

تُظهر الاختبارات القياسية باستمرار أن الدفع يمكن أن يكون أسرع بكثير من التسلسل للعمليات التي تنطوي على دمج أو إضافة أعداد كبيرة من العناصر. على سبيل المثال ، أظهر أحد المعايير أنه بالنسبة لدمج المصفوفات مع الآلاف من العناصر مرارًا وتكرارًا ، كان الدفع أسرع حوالي 945 مرة من التسلس في الكروم وحتى أسرع في Firefox. ينشأ هذا الاختلاف الهائل من سلوك Concat المتمثل في إنشاء صفيف جديد ونسخ البيانات بشكل متكرر ، في حين أن الدفع يزرع الصفيف الموجود بشكل أكثر تدريجية وفي مكانه ، وتجنب عمليات إعادة تكرار الذاكرة المتكررة.

ومع ذلك ، قد تختلف خصائص الأداء هذه حسب سيناريوهات الاستخدام. إذا كان الهدف هو تسلسل واحد لصفعة كبيرة جدًا تم تخصيصها مسبقًا ، فقد يؤدي Concat بشكل جيد نسبيًا لأنه يخصص مرة واحدة ويقوم بالنسخ مرة واحدة. في مثل هذه الحالات ، يمكن أن يتسبب نهج إلحاق Push One-By-One أو Batch في إجراءات متعددة أو نسخ داخليًا ، مما قد يقلل من ميزته النظرية. ومع ذلك ، بالنسبة للدمج المتكرر أو إضافة العديد من العناصر عبر العديد من المصفوفات ، فإن الدفع يميل إلى إطفاء O (1) لكل إضافة لأن المصفوفات غالبًا ما تخصص الذاكرة الهندسية (مضاعفة السعة عند تجاوزها) ، مما يجعلها فعالة بشكل عام.

من منظور الذاكرة ، تعني طفرة Push في مكانها التخصيصات الأقل تكرارًا وربما أقل ضغطًا على النظام الفرعي للذاكرة. تؤكد طريقة Concat ، التي تتطلب تخصيصات جديدة ونسخ بيانات على من جديد ، الذاكرة وذاكرة التخزين المؤقت أكثر ، وخاصة بالنسبة للصفائف الكبيرة. ينتج عن هذا الموقف عمليات تسلسس من المحتمل أن تتجاوز حدود ذاكرة التخزين المؤقت للوحدة المعالجة المركزية ، مما يؤدي إلى أوقات الوصول إلى الذاكرة أبطأ بسبب جلب البيانات من ذاكرة التخزين المؤقت للوصول العالي أو الذاكرة الرئيسية بشكل متكرر. Push ، وتجنب الزراعة إلى البيانات الموجودة بالفعل في المصفوفة ، يمكن أن يستفيد من موقع ذاكرة التخزين المؤقت بشكل أفضل.

تجدر الإشارة إلى أن الدفع يغير الصفيف الأصلي بينما يحافظ Concat على الثبات عن طريق إعادة صفيف جديد. هذا الاختلاف مهم في تصميم التطبيق ولكنه يؤثر أيضًا على الأداء. لا تضمن التسلسلات غير القابلة للتسلية مع عدم وجود آثار جانبية ولكن دفع سعر الذاكرة الإضافية والنسخ ، في حين أن الدفع يتداول للتأثير للسرعة عن طريق تعديل صفيف المصدر مباشرة.

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

فيما يتعلق بجمع القمامة ، يمكن أن تزيد المخصصات المتكررة في Concat من عبء عمل جمع القمامة لأن المصفوفات القديمة يتم التخلص منها بعد النسخ. هذا يمكن أن يؤدي إلى توقف مؤقت أو انخفاض الأداء في سيناريوهات التخصيص العالية. Push's Grading A Tray Fray يقلل من تواتر التخصيصات وبالتالي جمع القمامة العلوي.

بشكل عام ، ينطوي الاختيار بين الدفع والتسلسل على مفاضلة بين السرعة (الدفع) والتأثري/الراحة (CONCAT). بالنسبة للعمليات على المصفوفات الكبيرة ذات الأداء كأولوية ، فإن PUSH هي الطريقة الأفضل بشكل عام بسبب معالجة الذاكرة الأكثر كفاءة وأقل النفقات العامة. يصبح المسلسل النفقات العامة من إنشاء المصفوفة والنسخ مكلفًا للغاية مع زيادة أحجام الصفيف. في السيناريوهات التي يكون فيها الثبات أمرًا بالغ الأهمية ، يتم استخدام Concat على الرغم من عقوبة الأداء.

باختصار ، يعرض Push عادةً أداءً أفضل وانخفاضًا في الذاكرة النفقات العامة مقارنةً بالتسلسل في سياق المصفوفات الكبيرة بسبب التعديل في مكانه ، وإلحاق الوقت المستمر ، وتقليل النسخ. يعاني Concat من تخصيصات الذاكرة الإضافية وتكاليف النسخ لأنها تنشئ صفيفًا جديدًا في كل مرة يطلق عليها ، مما يؤثر على كل من الوقت المستغرق واستخدام الذاكرة ، خاصة مع المصفوفات الكبيرة جدًا. يتم تضخيم هذه الاختلافات عند دمج العديد من المصفوفات أو التعامل مع مجموعات البيانات الضخمة ، حيث يمكن أن يكون الدفع مئات إلى آلاف المرات أسرع من التسلسل وفقًا للمعايير. ومع ذلك ، بناءً على سياق الاستخدام وتحسينات المحرك ، يمكن أن يكون لهذه الأنماط العامة استثناءات ويجب النظر فيها إلى جانب الحاجة إلى عدم قابلية التثبيت في الكود وقابليتها للصيانة.