سؤال

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

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

السؤال:في هذه الحالة, لن يكون من الحكمة أن ندعو GC.جمع() قبل الدخول في المرحلة الثانية?

بعد كل هذه مرحلتين لم تتداخل في الوقت مع بعضهم البعض و كل وتحسين الإحصاءات GC قد تجمعوا سوف يكون من فائدة هنا...

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

شكرا

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

المحلول

من ريكو مدونة...

القاعدة #1

لا.

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

القاعدة #2

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

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

يبدو أن هذه الحالة قد تندرج تحت القاعدة #2, كنت أعرف أن هناك لحظة في الوقت فيها الكثير من الأشياء القديمة قد مات وهو غير المتكررة.لكن, لا ننسى ريكو كلمات فراق.

القاعدة #1 ترامب القاعدة #2 دون أدلة قوية.

قياس, قياس, قياس.

نصائح أخرى

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

فكيف عندما كنت تستخدم كائنات COM مثل مايكروسوفت وورد أو إكسل من .الشبكة ؟ دون استدعاء GC.Collect بعد الإفراج عن كائنات COM وجدنا أن Word أو Excel تطبيق الحالات لا تزال موجودة.

في الواقع رمز نستخدمها هي:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

لذلك من شأنه أن يكون غير صحيح استخدام جامع القمامة ؟ إذا كان الأمر كذلك كيف يمكننا الحصول على إمكانية التشغيل المتداخل الكائنات تموت ؟ أيضا إذا لم يكن من المفترض أن يكون استخدام مثل هذا, لماذا GC's Collect طريقة حتى Public?

حسنا, GC هي واحدة من تلك الأشياء التي كنت قد الحب / الكراهية العلاقة مع.لدينا مكسورة في الماضي من خلال VistaDB و كتبت عن ذلك.أنها ثابتة, لكنه يأخذ وقتا طويلا للحصول على إصلاحات منها على مثل هذه الأمور.

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

بشكل عام يجب أن لا تضيف Collect إلا إذا كنت تعرف حقيقة أنت فقط ملقاة طن من الذاكرة وأنها سوف تذهب إلى أزمة منتصف العمر إذا كان GC لا تحصل على تنظيفه الآن.

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

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

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

و أن تكون كاملة في جوابي ممكن يجب أيضا اختبار تحت أحادية إذا كنت تستهدف هذه المنصة أيضا.لأنها مختلفة تماما التنفيذ قد تجربة مختلفة تماما المشاكل التي MS التنفيذ.

هناك حالات حيث انها مفيدة, ولكن بشكل عام فإنه ينبغي تجنبها.هل يمكن مقارنة ذلك إلى غوتو ، أو ركوب الدراجة:كنت تفعل ذلك عندما كنت بحاجة إلى ذلك ، ولكن لا تخبر أصدقائك عن ذلك.

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

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

بالطبع يجب الشخصي ، وانظر لنفسك.

حسنا, من الواضح أنك لا ينبغي أن كتابة التعليمات البرمجية مع متطلبات الوقت الحقيقي في اللغات غير الوقت الحقيقي جمع القمامة.

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

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

خلق الصور في حلقة - حتى إذا كنت استدعاء التصرف ، الذاكرة التي لا يتم استردادها.جمع القمامة في كل مرة.ذهبت من 1.7 GB الذاكرة على معالجة الصور التطبيق 24MB و أداء ممتاز.

هناك على الإطلاق الوقت الذي تحتاج إلى استدعاء GC.جمع.

في الواقع, أنا لا أعتقد أنه سيء للغاية ممارسة الاتصال GC.جمع.
قد تكون هناك حالات عندما نحتاج إلى ذلك.فقط على سبيل المثال, لقد شكل تشغيل مؤشر ترابط التي inturn يفتح مختلفون الجداول في قاعدة بيانات مستخلصات محتويات الحقل BLOB إلى ملف مؤقت, تشفير الملف ، ثم قراءة الملف إلى binarystream والعودة إلى النقطة حقل في جدول آخر.

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

اعتدت على OutofMemory استثناء في كثير من الأحيان وأنا أعتقد أنه سيكون من الحكمة بصورة دورية تشغيل GC.جمع على أساس متغير العداد.لقد زيادة العداد عند مستوى معين ، GC يسمى لجمع القمامة التي قد شكلت ، واستعادة أي الذاكرة المفقودة نتيجة غير متوقعة تسرب الذاكرة.

بعد هذا, وأعتقد أنه يعمل بشكل جيد, على الأقل استثناء!!!
أدعو بالطريقة التالية:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

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

وبالتالي الدعوة GC.Collect هو عرضة لزيادة المبلغ الإجمالي من العمل على النظام أن تفعل.فإنه سيتم تأخير حدوث جمع المقبل, ولكن ربما سوف تفعل بقدر العمل على الفور على النحو التالي جمع يتطلب عندما حدث ؛ في هذه النقطة عندما جمع المقبل قد وقع إجمالي مقدار الوقت المستغرق في جمع سوف يكون عن نفسه كما كان GC.Collect لا يسمى ، ولكن النظام سوف تراكمت بعض القمامة ، مما تسبب في نجاح المجموعة أن تكون مطلوبة في وقت أقرب مما كان GC.Collect لا يسمى.

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

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

في البرنامج ، تم تجهيز بعض متواضعة الحجم جداول بيانات Excel مع OpenXML.جداول البيانات الواردة في أي مكان من 5 إلى 10 "أوراق" مع حوالي 1000 الصفوف من 14 الأعمدة.

البرنامج في 32 بت البيئة (x86) تعطل مع "نفاد الذاكرة" خطأ.فعلنا على تشغيلها في بيئة x64, ولكن أردنا حل أفضل.

وجدنا واحد.

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

واصفا GC من داخل روتين فرعي لم ينجح.الذاكرة لم المستصلحة...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

عن طريق تحريك GC دعوة إلى خارج نطاق فرعي ، القمامة التي تم جمعها و الذاكرة حررت.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

آمل أن يكون هذا يساعد الآخرين يشعرون بالاحباط مع .صافي جمع القمامة عندما يظهر تجاهل المكالمات GC.Collect().

بول سميث

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

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

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

يجب أن أقول لقد كان تجميد التطبيق في كروم وفايرفوكس أن يحبط الجحيم, و حتى ذلك الحين في بعض الحالات الذاكرة ينمو دون عوائق -- إلا إذا كنت تعلم أن دعوة جامع القمامة-أو تعطيني زر حتى تبدأ في قراءة النص من صفحة يمكنني ضرب وبالتالي تكون خالية من تجمد لمدة 20 دقيقة.

أعتقد أنك على حق حول السيناريو ولكن أنا غير متأكد حول API.

وتقول مايكروسوفت أنه في مثل هذه الحالات يجب أن إضافة ضغط الذاكرة كما تلميحا إلى GC أنه ينبغي قريبا أداء مجموعة.

ما هو الخطأ في ذلك ؟ حقيقة أن كنت التخمين الثاني القمامة جامع مخصص الذاكرة التي بينهما أكبر بكثير فكرة عن التطبيق الخاص بك استخدام الذاكرة الفعلية في وقت التشغيل مما تفعله.

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

سيكون من الأفضل إذا كان يمكنك العثور على حيث كنت قد نسيت أن التصرف في الأشياء التي كنت لا تحتاج بعد الآن.

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

على .صافي الإطار نفسه لم يكن يهدف إلى تشغيل في الوقت الحقيقي البيئة.إذا كنت حقا بحاجة إلى الوقت الحقيقي تجهيز يمكنك استخدام إما جزءا لا يتجزأ الحقيقي اللغة التي ليست على أساس .صافي أو استخدام .NET Framework ضغط التشغيل على جهاز Windows CE.

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

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

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

لقد حاولت ذلك لحل مشاكل الذاكرة عدة مرات دون جدوى.أخذت بها.

باختصار, لا تضعه إلا إذا كنت الحصول على أخطاء.إذا كنت وضعت في ذلك لا يحل مشكلة في الذاكرة, نأخذها.تذكر أن الاختبار في الإفراج عن وضع مقارنة التفاح إلى التفاح.

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

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