ما هي الاستراتيجيات والأدوات المفيدة للعثور على تسرب الذاكرة في .NET؟

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

سؤال

لقد كتبت لغة C++ لمدة 10 سنوات.لقد واجهت مشكلات في الذاكرة، ولكن يمكن إصلاحها بقدر معقول من الجهد.

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

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

ما نوع الاستراتيجيات والأدوات المفيدة لمعالجة تسرب الذاكرة في .NET؟

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

المحلول

أنا استخدم سايتك MemProfiler عندما أشك في حدوث تسرب للذاكرة.

لقد وجدت حتى الآن أنها موثوقة وقوية للغاية.لقد أنقذ لحم الخنزير المقدد الخاص بي في مناسبة واحدة على الأقل.

يعمل GC بشكل جيد جدًا في .NET IMO، ولكن تمامًا مثل أي لغة أو نظام أساسي آخر، إذا كتبت تعليمات برمجية سيئة، تحدث أشياء سيئة.

نصائح أخرى

فقط لمشكلة نسيان التخلص، حاول الحل الموضح في منشور المدونة هذا.وهنا الجوهر:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif

لقد استخدمنا النمل التعريف برو بواسطة برنامج Red Gate في مشروعنا.إنه يعمل بشكل جيد مع كافة التطبيقات المستندة إلى لغة .NET.

لقد وجدنا أن برنامج .NET Garbage Collector "آمن" للغاية في تنظيف الكائنات الموجودة في الذاكرة (كما ينبغي أن يكون).من شأنه أن يبقي الأشياء حولنا فقط لأننا قد استخدامه في وقت ما في المستقبل.وهذا يعني أننا بحاجة إلى توخي المزيد من الحذر بشأن عدد الأشياء التي قمنا بتضخيمها في الذاكرة.في النهاية، قمنا بتحويل كافة كائنات البيانات الخاصة بنا إلى "تضخيم عند الطلب" (قبل طلب الحقل مباشرة) لتقليل حمل الذاكرة وزيادة الأداء.

يحرر:إليك تفسير إضافي لما أعنيه بـ "تضخيم الطلب". في نموذج كائننا لقاعدة البيانات الخاصة بنا ، نستخدم خصائص كائن الأصل لفضح الكائن (الكائنات) الطفل.على سبيل المثال، إذا كان لدينا بعض السجلات التي تشير إلى سجل "تفصيلي" أو "بحث" آخر على أساس واحد لواحد، فسننظمه على النحو التالي:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class

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

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

تبين أن هذا أكثر كفاءة لأنه تم الاحتفاظ بالكائنات خارج الذاكرة حتى يتم الحاجة إليها (تم الوصول إلى طريقة Get).لقد قدم تعزيزًا كبيرًا جدًا للأداء في الحد من عدد زيارات قاعدة البيانات وتحقيق مكاسب هائلة في مساحة الذاكرة.

لا تزال بحاجة إلى القلق بشأن الذاكرة عند كتابة تعليمات برمجية مُدارة ما لم يكن تطبيقك تافهًا.سأقترح شيئين:أولا، اقرأ CLR عبر C# لأنه سيساعدك على فهم إدارة الذاكرة في .NET.ثانيا، تعلم كيفية استخدام أداة مثل CLRProfiler (مايكروسوفت).يمكن أن يعطيك هذا فكرة عن سبب تسرب الذاكرة لديك (على سبيل المثال:يمكنك إلقاء نظرة على تجزئة كومة الكائنات الكبيرة الخاصة بك)

هل تستخدم تعليمات برمجية غير مُدارة؟إذا كنت لا تستخدم تعليمات برمجية غير مُدارة، وفقًا لمايكروسوفت، فإن تسرب الذاكرة بالمعنى التقليدي غير ممكن.

ومع ذلك، قد لا يتم تحرير الذاكرة المستخدمة بواسطة التطبيق، لذلك قد يزيد تخصيص ذاكرة التطبيق طوال عمر التطبيق.

من كيفية التعرف على تسرب الذاكرة في وقت تشغيل اللغة العامة في Microsoft.com

يمكن أن يحدث تسرب الذاكرة في تطبيق .NET Framework عند استخدام رمز غير مُدار كجزء من التطبيق.يمكن لهذا الرمز غير المُدار تسرب الذاكرة ، ولا يمكن لوقت تشغيل .NET Framework معالجة هذه المشكلة.

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

للتعامل مع هذا النوع من المشاكل، يمكنك التنفيذ يمكن التخلص منه.إذا كنت تريد أن ترى بعض الاستراتيجيات للتعامل مع إدارة الذاكرة، أود أن أقترح عليك البحث عنها IDisposable، XNA، إدارة الذاكرة حيث يحتاج مطورو الألعاب إلى جمع المزيد من البيانات المهملة التي يمكن التنبؤ بها وبالتالي يجب عليهم إجبار GC على القيام بعملها.

أحد الأخطاء الشائعة هو عدم إزالة معالجات الأحداث التي تشترك في كائن ما.سيمنع اشتراك معالج الأحداث إعادة تدوير الكائن.ألقِ نظرة أيضًا على استخدام بيان يسمح لك بإنشاء نطاق محدود لعمر المورد.

هذه المدونة يحتوي على بعض الإرشادات الرائعة حقًا باستخدام Windbg وأدوات أخرى لتعقب تسرب الذاكرة بجميع أنواعه.قراءة ممتازة لتطوير مهاراتك.

لقد حدث لي للتو تسرب للذاكرة في إحدى خدمات Windows، وقمت بإصلاحه.

أولا، حاولت MemProfiler.لقد وجدت أنه من الصعب جدًا استخدامه وليس سهل الاستخدام على الإطلاق.

ثم استخدمت JustTrace وهو أسهل في الاستخدام ويمنحك المزيد من التفاصيل حول الكائنات التي لم يتم التخلص منها بشكل صحيح.

لقد سمح لي بحل مشكلة تسرب الذاكرة بسهولة.

إذا كانت التسريبات التي تلاحظها ناتجة عن تنفيذ هارب لذاكرة التخزين المؤقت، فهذا هو السيناريو الذي يمكنك فيه قد تريد أن تنظر في استخدام WeakReference.قد يساعد هذا في ضمان تحرير الذاكرة عند الضرورة.

ومع ذلك، IMHO سيكون من الأفضل التفكير في حل مخصص - أنت فقط تعرف حقًا المدة التي تحتاجها للاحتفاظ بالأشياء، لذا فإن تصميم كود التدبير المنزلي المناسب لموقفك هو عادةً أفضل نهج.

الاسلحه الكبيره - أدوات التصحيح لنظام التشغيل Windows

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

"إذا تم كسره فهو ..." تحتوي المدونة على مقالات مفيدة جدًا حول هذا الموضوع.

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

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

واحدة من أفضل الأدوات هي استخدام أدوات التصحيح لنظام التشغيل Windows, ، وأخذ تفريغ ذاكرة للعملية باستخدام com.adplus, ، ثم استخدام com.windbg و ال استغاثة البرنامج المساعد لتحليل ذاكرة العملية، والخيوط، ومكدسات المكالمات.

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

ثم قم بالتحليل في وضع عدم الاتصال.

بعد أحد الإصلاحات التي قمت بها للتطبيق المُدار، كان لدي نفس الشيء، مثل كيفية التحقق من أن تطبيقي لن يعاني من نفس تسرب الذاكرة بعد التغيير التالي، لذلك كتبت شيئًا مثل إطار التحقق من إصدار الكائن، يرجى إلقاء نظرة على حزمة نوجيت ObjectReleaseVerification.يمكنك العثور على عينة هنا https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample, ومعلومات حول هذه العينة http://outcoldman.ru/en/blog/show/322

أنا أفضل com.dotmemory من جيت براينز

من Visual Studio 2015 فكر في استخدامه خارج الصندوق أداة تشخيص استخدام الذاكرة لجمع وتحليل بيانات استخدام الذاكرة.

تتيح لك أداة استخدام الذاكرة التقاط لقطة واحدة أو أكثر لكومة الذاكرة المُدارة والمحلية للمساعدة في فهم تأثير استخدام الذاكرة لأنواع الكائنات.

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