الاستخدام العملي ل `stackalloc` الكلمة الرئيسية

StackOverflow https://stackoverflow.com/questions/785226

  •  16-09-2019
  •  | 
  •  

سؤال

وقد أي شخص يستخدم فعلا stackalloc بينما البرمجة في C #؟ أنا على علم بما هو عليه، ولكن المرة الوحيدة التي تظهر بها في التعليمات البرمجية هي عن طريق الصدفة، لأن Intellisense يشير إلى ذلك عندما أبدأ الكتابة static, ، علي سبيل المثال.

على الرغم من أنه لا يرتبط بسيناريوهات الاستخدام stackalloc, ، أقوم فعلا بكمية كبيرة من التركيب interop في تطبيقاتي، لذلك كل الآن وبعد ذلك يمكنني اللجوء إلى استخدام unsafe الشفرة. ولكن مع ذلك عادة ما أجد طرقا لتجنب unsafe تماما.

ومنذ حجم المكدس لمؤشر موضوع واحد في .NET هو ~ 1 ميجابايت (تصحيح لي إذا كنت مخطئا)، فأنا أكثر احتياجا من استخدام stackalloc.

هل هناك بعض الحالات العملية التي يمكن فيها أن يقول المرء: "هذا هو بالضبط الكمية المناسبة للبيانات والمعالجة بالنسبة لي للذهاب غير آمنة واستخدامها stackalloc"?

هل كانت مفيدة؟

المحلول

السبب الوحيد للاستخدام stackalloc هو الأداء (إما للحسابات أو interop). باستخدام stackalloc بدلا من مجموعة مخصصة لك كومة، تقوم بإنشاء ضغط GC أقل (يحتاج GC إلى تشغيل أقل)، لا تحتاج إلى تثبيت الصفائف لأسفل، فهو أسرع في تخصيصها من صفيف الكومة، وهي تحرير تلقائيا عند الخروج من الطريقة ( يتم إلغاء تخصيص صفائف الكومة المخصصة فقط عند تشغيل GC). أيضا باستخدام stackalloc بدلا من مصلح أصلي (مثل Malloc أو ما يعادلها .NET) أيضا اكتساب السرعة والتفاصيل التلقائية عند خروج النطاق.

الأداء الحكيم، إذا كنت تستخدم stackalloc أنت تزيد كثيرا من فرصة مخبأ يضرب في وحدة المعالجة المركزية بسبب محلية البيانات.

نصائح أخرى

لقد استخدمت Stackalloc لتخصيص المخازن المؤقتة ل [القريب] DSP العمل في الوقت الحقيقي. لقد كانت حالة محددة للغاية حيث يحتاج الأداء إلى أن تكون متسقة قدر الإمكان. ملاحظة هناك اختلاف بين الاتساق والإنتاجية الإجمالية - في هذه الحالة لم أكن مهتما بمخصصات الكومة بطيئة للغاية، فقط مع عدم تحديد تحدد جمع القمامة في تلك المرحلة في البرنامج. لن أستخدمها في 99٪ من الحالات.

stackalloc هو فقط ذات الصلة للحصول على رمز غير آمن. للحصول على التعليمات البرمجية المدارة، لا يمكنك تحديد مكان تخصيص البيانات. يتم تخصيص أنواع القيمة على المكدس لكل تقصير (ما لم تكن جزءا من نوع مرجعي، وفي هذه الحالة يتم تخصيصها على كومة الكومة). يتم تخصيص أنواع المراجع على كومة الكومة.

حجم المكدس الافتراضي لتطبيق Vanilla .NET عادي هو 1 ميغابايت، ولكن يمكنك تغيير هذا في رأس PE. إذا كنت تبدأ الخيوط بشكل صريح، فقد تقوم أيضا بحجم مختلف عبر التحميل الزائد المنشئ. بالنسبة للتطبيقات ASP.NET، فإن حجم المكدس الافتراضي هو 256 كيلو فقط، وهو شيء يجب وضعه في الاعتبار إذا كنت تبحث بين البيئتين.

تهيئة stackalloc يمتد. في الإصدارات السابقة من C #، لا يمكن تخزين نتيجة Stackalloc إلا في متغير محلي مؤشر. اعتبارا من C # 7.2، يمكن الآن استخدام Stackalloc كجزء من تعبير ويمكن أن يستهدف فترة، ويمكن القيام بذلك دون استخدام الكلمة الأساسية غير الآمنة. وهكذا، بدلا من الكتابة

Span<byte> bytes;
unsafe
{
  byte* tmp = stackalloc byte[length];
  bytes = new Span<byte>(tmp, length);
}

يمكنك الكتابة ببساطة:

Span<byte> bytes = stackalloc byte[length];

هذا مفيد للغاية أيضا في المواقف التي تحتاج فيها إلى بعض مساحة خدش لإجراء عملية، ولكنها ترغب في تجنب تخصيص ذاكرة الكومة لأحجام صغيرة نسبيا

Span<byte> bytes = length <= 128 ? stackalloc byte[length] : new byte[length];
... // Code that operates on the Span<byte>

مصدر: C # - كل شيء عن الفترة: استكشاف .NET الرئيسية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top