Aspnetcore: Asp.net Core لا يقوم بجمع القمامة

تم إنشاؤها على ٢١ مارس ٢٠١٧  ·  136تعليقات  ·  مصدر: dotnet/aspnetcore

لا أستطيع أن أفهم لماذا لا يبدو أن جوهر Asp.net يقوم بجمع القمامة. في الأسبوع الماضي ، سمحت بتشغيل خدمة ويب لبضعة أيام ، ووصل استخدام الذاكرة لدي إلى 20 جيجابايت. لا يبدو أن GC تعمل بشكل صحيح. لاختبار ذلك ، كتبت طريقة ويب بسيطة جدًا تعيد مجموعة كبيرة من السلاسل النصية. بدأ التطبيق باستخدام 124 ميجابايت فقط ، ولكن مع كل مرة اتصلت فيها بطريقة الويب ، استمر استخدام الذاكرة في الارتفاع حتى وصل إلى 411 ميجابايت. كان من الممكن أن يكون أعلى إذا واصلت استدعاء طريقة الويب. لكنني قررت التوقف عن الاختبار.

كان كود الاختبار الخاص بي هو:

"

[HttpGet]
مهمة عامة غير متزامنة> TestGC () {
رسالة سلسلة const = "اختبار" ؛
إرجاع Enumerable.Repeat (رسالة ، 100000000) ؛
}
"

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

كما ترى من لقطة الشاشة أدناه ، حتى بعد استدعاء GC ، لم يتم تحرير الذاكرة.
netcorescreenshot

شكرا للمساعدة!
جاي

investigate

التعليق الأكثر فائدة

أي أخبار عن هذا؟ أنا أستخدم Core 2 عبر Net Framework ولا يزال هذا يحدث. كل مكالمة إلى _Controller_ تزيد من الذاكرة المستخدمة ، لكنها لا تنخفض أبدًا. (_ لقد استخدمت قالب WebApi_)

ال 136 كومينتر

تضمين التغريدة

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

من المحتمل أن يعضك كومة الكائنات الكبيرة هنا. إذا قمت بتخصيص كائنات أكبر من 85 كيلو بايت في الحجم ، فسيتم وضعها في LOH ونادرًا ما يتم ضغطها . راجع http://stackoverflow.com/questions/8951836/why-large-object-heap-and-why-do-we-care لمزيد من التفاصيل (أو https://github.com/dotnet/coreclr/blob/master /Documentation/botr/garbage-collection.md#design-of-allocator إذا كنت تريد التعمق أكثر).

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

ما الذي تفعله خدمتك بحيث تصنع مثل هذه الأشياء الكبيرة؟ يجب أن تحاول أخذ ملف تفريغ للذاكرة قبل أن يصبح كبيرًا جدًا ، حيث سيظهر لك ذلك بوضوح الأشياء التي تلتصق بها ولماذا يتم الاحتفاظ بها (يمكنك استخدام الاستوديو البصري للنظر في مقالب أو أداة أكثر تقدمًا مثل windbg أو perfview).

حاول تخصيص المصفوفة من البداية بدلاً من استدعاء Enumerable. كرر
أو ضغط الذاكرة باستخدام GCSettings.LargeObjectHeapCompactionMode (مدعوم في .Net Standard)

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

zorthgo متأكد من أنها ليست Dapper؟ إذا قمت بإنشاء البرامج النصية الخاصة بك عن طريق إدخال المعلمات مباشرة إلى نصوص SQL الخاصة بك كما هو الحال في PHP ، فسوف ينتهي بك الأمر مع الكثير من نصوص SQL المخزنة مؤقتًا. هنا هو كيف Dapper يفعل ذلك
https://github.com/StackExchange/Dapper/blob/fe5c270aceab362c936456087a830e6fe1603cac/Dapper/SqlMapper.cs
يجب عليك استخدام ملف تعريف ذاكرة لمعرفة ما الذي يحتفظ بالإشارات إلى الذاكرة المخصصة. يجب أن يكون Visual Studio 2017 قادرًا على مساعدتك في أخذ بعض اللقطات من الذاكرة قبل وبعد مكالمات متعددة لتطبيقك ومقارنتها.

zorthgo نعم لقد رأيت هذا أيضًا. كان يستخدم servicestack في تطبيق وحدة التحكم الأساسية .net الخاص بي وفي كل مرة أقوم فيها بإجراء مكالمة إلى API ، زاد استخدام الذاكرة بكميات هائلة تبلغ 50 ميجا بايت. افترضت أنه خطأ VS2017 ولكني أكدت بعد ذلك الاستخدام العالي في مدير المهام. كما ذكر zorthgo بمجرد إجراء مكالمات بسيطة لواجهة برمجة التطبيقات ، فإن استخدام الذاكرة يزداد بشكل كبير ولا يبدو أنه يحرر الذاكرة.

هل يحدث هذا فقط على ASP.NET Core على .NET Core أم أنه مشكلة أيضًا مع ASP.NET Core على .NET Framework؟

هل يمكنك كتابة تطبيق مشابه باستخدام MVC 5 (على System.Web) والتحقق من أنك لا ترى نفس السلوك؟

لا يمكنني إحراز أي تقدم بشأن هذه القضية في وضعها الحالي.

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

لست متأكدًا مما إذا كان هذا سيساعد أي شخص. عينة من التطبيق الذي يدعو hellorequest. في هذا التطبيق ، تبلغ ذاكرة بدء التشغيل 85 ميغا بايت ، ثم من خلال الطلب المتكرر تمكنت من رفع استخدام الذاكرة إلى حوالي 145 ميغا بايت. يتراجع أحيانًا إلى 125 ميغا بايت ولكنه يبقى هناك. لست متأكدًا مما إذا كان هذا سلوكًا طبيعيًا لأنني لست معتادًا على تطبيقات .Net Core console. كنت أفترض دائمًا أنني كنت أفعل شيئًا خاطئًا أو لا أقوم بإنشاء مثيل بشكل صحيح.

https://drive.google.com/open؟id=0B0Gm-m-z_U84TU5keWFTMzc1ZWc

تواجه نفس المشكلة هنا على تطبيق Asp.Net Core الذي تم نشره للإنتاج مع 3000-5000 مستخدم نشط .. زادت الذاكرة على الخادم إلى 15 غيغابايت بالأمس ... كان علي تكوين IIS لإعادة تشغيل AppPool كل 3 ساعات بينما لا أزال حاول معرفة ما هي المشكلة.

هل قام أي شخص بتفريغ الذاكرة ونظر إلى ما يشغل كل الذاكرة في تطبيقاتك الخاصة؟

تضمين التغريدة
أنا أعمل في شركة كبيرة ، ونريد بدء مشروع جديد باستخدام ASP.NET Core ، ولكن عندما رأيت هذه المشكلة ، كنت خائفًا: قلق:. هذه مشكلة حرجة ويمكن أن تعيق دورة حياة مشروعنا.

لذا من فضلك ، هل هو متعلق بـ ASP.NET Core أو .NET Core (CoreCLR)؟ سنستهدف Full .NET (4.6) لهذا السبب أطالب بذلك.

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

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

لقد غيرت المصدر قليلاً:

كائن عام أي (طلب TestGC)
{
رسالة سلسلة const = "اختبار" ؛
إرجاع Enumerable.Repeat (رسالة ، 100000) ؛
}

تضمين التغريدة
شكرا لك ، سوف أتحقق من السلوك من جانبي.

ماذا عن هذا الخطأ في 2.0؟

أي أخبار عن هذا؟ أنا أستخدم Core 2 عبر Net Framework ولا يزال هذا يحدث. كل مكالمة إلى _Controller_ تزيد من الذاكرة المستخدمة ، لكنها لا تنخفض أبدًا. (_ لقد استخدمت قالب WebApi_)

أهلا،

لدي نفس المشكلة مع ASP.NET Core 2. لقد أخذت ملف تفريغ ذاكرة وحاولت التحليل. من ما أراه ، فإن المشكلة هي بالضبط كما قال OP. يبدأ تطبيقي بتخصيص 75 ميجابايت ، وبسرعة كبيرة يصل إلى 750 ميجابايت تقريبًا ، منها 608 ميجابايت "ذاكرة غير مستخدمة مخصصة لـ .NET".

اللقطة الأولى عند بدء التطبيق:
image

لقطة ثانية بعد 3 دقائق و 100 طلب:
image

نحن نواجه أيضًا نفس المشكلة ، وحدة التحكم الخاصة بنا تتعامل مع كمية كبيرة من البيانات ، (وهو تصميم سيء وسيتم استبداله قريبًا) ، كل مكالمة إلى وحدة التحكم هذه تتسبب في نمو الذاكرة. تقل الذاكرة ولكن فقط 40-50٪ (كسب 50 ميجا بايت ، يقلل 30-35 ميجا بايت) ، كل مكالمة تزيد الذاكرة في نطاق 10-15 ميجا بايت في كل مرة. الخدمة مستضافة داخل نسيج الخدمة.

يبدو أن لدي مشكلة مماثلة في خدمة الإنتاج لدينا (20-100 req / s) باستخدام مزيج من:

  • ASP.NET Core 2.0.4
  • ServiceStack.Core 1.0.44.0 تحديث
  • SkiaSharp 1.59.2.2 تحديث
  • Docker v17.09.0-ce ، بناء afdb6d4 على Ubuntu 16.04 x64
  • x4 خوادم @ 40 وحدة معالجة مركزية ، ذاكرة 128 جيجا بايت
  • الخادم GC هو الصحيح
  • تم تعيين كل حاوية Docker على مشاركة وحدة المعالجة المركزية 12 كيلو (ميجاهرتز) ، وذاكرة الوصول العشوائي 8 جيجابايت

يحتوي التطبيق على خادم ويب الأمامي وعامل (موضحين على التوالي في الرسوم البيانية أدناه).

خادم الويب (آخر 6 ساعات)
screen shot 2018-01-13 at 1 06 24 pm

عامل (آخر 6 ساعات)
screen shot 2018-01-13 at 1 07 55 pm

كلاهما يستخدم مصفوفات البايت الكبيرة لأن الخدمة تعمل كوكيل تخزين كائن ، وبالتالي تضع الكائنات في LOH. سؤالي هو ، هل هذا أحد القيود المعروفة لـ .NET Core في الوقت الحالي؟ يبدو كما لو أن LOH لم يتم تنظيفه أو تجزئته بالكامل.

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

sebastienros - أي أفكار حول هذا؟ هل لاحظنا أي سلوك مشابه في أنظمتنا؟

  • نقيس هذا فقط على 2.1 ، وسأبحث في إضافة نفس الشيء لـ 2.0
  • يبدو أن جميع التعليقات مرتبطة بقضية LOH التي تم ذكرها ، والتي يجب أخذها في الاعتبار في التطبيق وتجميع المصفوفات الكبيرة قدر الإمكان

sebastienros ، عدة أسئلة:

  1. لقد استخدمت ملف تعريف النمل لقياس استخدام الذاكرة ، وفقًا لذلك ، لم يتم اكتشاف تجزئة LOH. هل يمكنكم إفادة كيف يمكنني التحقق مما إذا كان طلبي يعاني من مشاكل تجزئة LOH؟
  2. ما هي النتائج على .net core 2.1؟ هل تم حل المشكلة لأن Kestrel يستخدم Span؟
  3. ماذا لو لم نتمكن من تجميع المصفوفات - هل يمكنك توفير حل بديل؟ هل يجب أن نستخدم GCSettings.LargeObjectHeapCompactionMode.CompactOnce؟

ما هي النتائج على .net core 2.1؟ هل تم حل المشكلة لأن Kestrel يستخدم Span؟

نحن شخصيا لم نر أي دليل على أن المشكلة في كيستريل. لا يزال يبدو وكأنه مشكلة في التطبيق.

ماذا لو لم نتمكن من تجميع المصفوفات - هل يمكنك توفير حل بديل؟ هل يجب أن نستخدم GCSettings.LargeObjectHeapCompactionMode.CompactOnce؟

jkotas @ Maoni0 أي نصيحة هنا؟

كيف يمكنني التحقق مما إذا كنت أعاني من نفس المشكلة؟ يعد LOH وفقًا لملف تعريف ذاكرة redgate فارغًا تقريبًا كما يصف sinapis ولكنه لا يزال يستخدم أكثر من 1 جيجابايت لمستخدم واحد فقط

جمع التتبع وتحليله باستخدام perfview. هناك عدد من البرامج التعليمية بواسطة فانس وآخرين حول كيفية تتبع تسرب ذاكرة .NET: https://www.bing.com/search؟q=.NET٪20memory٪20leak٪20perfview .

يحتوي https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/linux-performance-tracing.md على إرشادات خاصة بنظام Linux لتجميع الآثار.

إذا كنت تعتقد أنه لا يوجد تسرب للذاكرة وأن GC يحتفظ فقط بمزيد من الذاكرة التي تريدها ، فيمكنك تجربة:

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

أهلا،

أعتقد أنني أواجه نفس النوع من المشاكل مع واجهة برمجة تطبيقات الويب .Net Core Web API في الإنتاج.

التطبيق يعمل على Windows Server 2016 مع .Net Core 2.0.3. الجهاز عبارة عن جهاز Hyper-V VM مزود بـ 28 مركزًا لوحدة المعالجة المركزية و 24 جيجابايت من ذاكرة الوصول العشوائي. إذا لم نقم بإعادة استخدام تجمع تطبيقات IIS بشكل كافٍ ، فسنستخدم في النهاية كل الذاكرة المتاحة. عندما يبدأ التطبيق في استخدام قدر كبير من الذاكرة (> = 95٪ من إجمالي ذاكرة النظام) ، يزداد استخدام وحدة المعالجة المركزية أيضًا بقوة (من 2٪ إلى 70٪ في بعض الأحيان). لست متأكدًا مما إذا تم تشغيل استثناء OOM أم لا ، فنحن دائمًا نعيد استخدام التجمع قبل حدوثه (كان الحد الأقصى لاستخدام الذاكرة الذي رأيته هو 98٪ من الذاكرة المستخدمة بواسطة dotnet.exe).

تحليل تفريغ ذاكرة الإنتاج باستخدام ".Net Memory Porfiler" (برنامج SciTech) هنا هو ما وجدته:
image

إذا كان هذا التحليل صحيحًا ، فسيكون حوالي 95٪ من الذاكرة في حالة "حمل> غير مستخدم". إليك كيفية وصف محرر ملف تعريف الذاكرة هذا الفئة (في المنتدى الخاص بهم):
_ "Overhead-> Unused" هي الذاكرة التي تم الالتزام بها بواسطة .NET runtime من أجل كومة الذاكرة المؤقتة المُدارة. إنه غير مستخدم حاليًا ، ولكنه متاح لعمليات تخصيص المثيلات المستقبلية. هناك الكثير من القواعد التي يستخدمها وقت التشغيل لتحديد ما إذا كان سيتم الاحتفاظ بالذاكرة المخصصة أو تحريرها لنظام التشغيل. يعتمد ذلك على عوامل مثل الذاكرة المتاحة وأنماط التخصيص وعدد المعالجات وما إذا كان الخادم GC مستخدَمًا وما إلى ذلك.

jkotas سأقوم بتطبيق توصياتك (كائن وظيفة Windows ، والتبديل إلى محطة العمل GC) وسأخبرك بالنتيجة. يرجى إعلامي إذا كان بإمكاني استخراج أي معلومات مفيدة أخرى من مقالب ذاكرة الإنتاج لدي.

شكرا

تضمين التغريدة
هل سيتمكن أي منكم من مشاركة تطبيق يُظهر المشكلة؟ إذا كان بإمكاني إعادة عرضه ، فسنكون قادرين على العثور على السبب ، أو على الأقل إزالة بعض التعليمات البرمجية قطعة قطعة وعزل الحد الأدنى من repro.

sebastienros لا يمكنني مشاركة التطبيق ، لكن يمكنني مشاركة الجلسة من جلسة PerfView + تفريغ الذاكرة .
بعض الوصف: لدي واجهة برمجة تطبيقات ويب ASP.NET Core 2 ، لقد قمت بإنشاء اختبار تحميل لـ 200 مستخدم يرسلون جميعًا نفس الطلب خلال 10 ثوانٍ. تم تجهيز 775 طلبا إجمالاً.

قفز هذا التطبيق إلى ما يقرب من 1 غيغابايت من استخدام الذاكرة في إدارة المهام وظل كذلك. بالنظر إلى التفريغ يمكنني الاعتماد على حوالي 18 ميغا بايت:

image

إذن فالأسئلة هي أين ذهب ما يقرب من 1 غيغابايت؟

sinapis شكرا

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

سنرى بالتأكيد مشكلة إذا استمرت في الزيادة. أفترض أنك إذا لم ترسل المزيد من الطلبات وتركت تطبيقك يعمل ، فسترى أن استخدام الذاكرة ينخفض.

هل يمكنك تشغيل نفس الشيء حتى يستهلك معظم ذاكرة نظامك؟ أو على الأقل لفترة كافية مع نفس العبء الذي سيظهر أنه ينمو باستمرار؟ سأستمر في إلقاء نظرة على مكباتك الحالية.

يمكنك أيضًا أخذ مقالب أثناء المهام وفي نهايتها ، حتى نتمكن من رؤية المنافذ.

مرحبا sebastienros

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

لقد قمت بتحديث وضع GC من _server_ إلى _workstation_ على خادم إنتاج واحد ، وسأخبرك في غضون ساعات قليلة من الآن إذا كان يغير أي شيء في استخدام الذاكرة.

أجريت أيضًا اختبارًا آخر: نحن نشغل تطبيقنا خلف موازن التحميل ، على 4 أجهزة افتراضية. بعد إزالة أحد الأجهزة من تجمع موازن التحميل ، لم تقل الذاكرة المستخدمة بواسطة dotnet.exe وظلت على نفس المستوى حتى بعد 30 دقيقة. (ومع ذلك ، كان التطبيق لا يزال يعالج بعض الطلبات: طلب واحد يتم إرساله بواسطة SCOM على نقطة نهاية وهمية كل 30 ثانية). لم يتم تحرير الذاكرة وإعادتها إلى النظام.

شكرا لك

sinapis نظرت إلى تتبع ETW الخاص بك. إنه لأمر محير بالنسبة لي - لقد نجوت قليلاً جدًا في الجيل الثاني المستحث الأخير ولكننا ما زلنا نختار الاحتفاظ بهذا القدر من الذاكرة. يبدو التطبيق الخاص بك حالة متطورة (لقد قمت في الغالب فقط بعمل GCs في الخلفية بسبب تخصيصات LOH) - أتساءل عما إذا كانت لدينا بعض الأخطاء المحاسبية هناك (هناك احتمال آخر وهو وجود أخطاء في الأرقام المبلغ عنها ولكن إذا كنت قد تحققت بالفعل من أنك ملتزم بهذا القدر فهذه احتمال أصغر). إذا كان بإمكانك توبيخ شيء يمكنك مشاركته معي ، فسيكون ذلك رائعًا ؛ وإلا إذا كان من الممكن تشغيل تطبيقك ببعض عمليات التسجيل من GC (يمكنني أن أقدم لك التزامًا يقوم بذلك) فسيكون ذلك مفيدًا أيضًا.

@ Maoni0 يرجى مشاركة كيف يمكنني تمكين تسجيل GC
إذا كانت هناك بعض البيانات الأخرى التي ترغب في تقديمها من أجل دحض الخطأ المحاسبي ، فيرجى إبلاغي بما يجب أن أقدمه لك وكيف (ربما أخبر perfview بجمع المزيد من البيانات؟)
سأحاول إنشاء حد أدنى من repro ، لكن لست متأكدًا من نجاحي لأنني لا أعرف مكان المشكلة.

sebastienros آمل أن أقدم تفريغًا آخر مع زيادة استهلاك الذاكرة اليوم

مرحبًاsebastienros @ Maoni0 ،

قمت بتشغيل تطبيقنا مع وضع GC في محطة العمل لمدة 12 ساعة ولكن نفس النتيجة. لقد أعدت أيضًا ترجمة التطبيق باستخدام .Net 2.1 Preview 2 على عقدة إنتاج واحدة لمدة ساعة ، وسأعلمك بالنتيجة ، ولكن في الوقت الحالي ، تستخدم العملية بالفعل 2 غيغابايت + من ذاكرة الوصول العشوائي.

image

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

إذا كان من الممكن أن يساعد ، يمكنني أيضًا جمع المزيد من المقاييس أو سجلات GC. شكرا لك

@ ronald7 _redacted_ يمكنني إعادة توجيهها إلى @ Maoni0

مرحبًاsebastienros @ Maoni0 ، لقد أرسلت إليك للتو بريدًا إلكترونيًا يحتوي على اثنين من PerfView gcdump وملف VMMap ، وآمل أن يساعد هذا. من جانبي ، ما زلت أحاول إعادة إنتاج سلوك استخدام الذاكرة العالية هذا باستخدام تطبيق وهمي.

شكرا!

أنا أيضا أواجه نفس المشكلة. جمع القمامة لا يحدث أبدا! تُظهر لقطة الشاشة استخدام الذاكرة بعد إجراء حوالي 50 طلبًا باستخدام تطبيق dotnet core API بسيط إلى حد ما.

memory-profile2

لقد قمت للتو بترقية تطبيق ASP.NET Core يعمل على Ubuntu 16.04 من 1.1 إلى 2.0 وواجهت هذه المشكلة. إنه أمر شديد الخطورة ، مما يتسبب في قيام kernel بإيقاف التطبيق بشكل متكرر بسبب أخطاء OOM ، وأنا أفكر فيما إذا كنت سأعود إلى الإصدار 1.x. هناك صفحات معينة لا يمكننا تحميلها على الإطلاق - حتى بعد إعادة تشغيل Kestrel ، يستنفد التطبيق الذاكرة المتوفرة فورًا بعد طلب واحد! فكرت في ترقية الخادم ، ولكن بناءً على التعليقات هنا حول تطبيقات ASP.NET Core باستخدام كل الذاكرة المتاحة ، لا آمل أن يساعد ذلك. مجموعتنا هي أساسًا ASP.NET MVC Core + EF Core ... لا شيء رائع جدًا. إذا حصلت على بعض الوقت ، فسأحاول إنشاء عينة لإعادة إنتاج المشكلة - لا أعتقد أنه يجب أن يكون بهذه الصعوبة ، نظرًا لبساطة مجموعتنا.

FWIW ، النظام الذي قمت بترقيته يحتوي أيضًا على تطبيق .NET Core console ، ولا يبدو أنه يعاني من أي مشاكل في الذاكرة بعد ترقية 2.0 ، لذلك يبدو أن هذا بالتأكيد مشكلة متعلقة بـ ASP.NET Core.

danports هل حاولت استدعاء GC.Collect () لترى ما إذا كان استخدام الذاكرة سينخفض ​​بشكل كبير؟ من شأنه أن يعطينا فكرة عن المكان الذي يجب أن نبدأ منه. إذا كان GC.Collect () (أو GC.Collect / GC.WaitingForPendingFinalizers / GC.Collect Sequent) غير قادر على جعل استخدام الذاكرة ينخفض ​​بشكل كبير ، فهذا يعني ببساطة أن هناك الكثير من الذاكرة التي يجب أن تكون حية حتى لا يتمكن GC من استعادتها.

@ Maoni0 لم أحاول ذلك بعد. لا أعتقد أن مشكلتي تتعلق بـ GC ، لأنني رأيت انخفاضًا في استخدام الذاكرة من وقت لآخر - يبدو أن تطبيقات .NET Core 2.0 الخاصة بي تستهلك ما يقرب من 2-3x من الذاكرة التي كانت تستخدمها مقارنة بوقت تشغيلها. NET Core 1.1.1 تحديث 😞

لقد رجعت إلى الإصدار السابق من .NET Core 1.1 في الوقت الحالي وسأعيد النظر في هذا لاحقًا عندما يكون لدي المزيد من الوقت ، ربما بعد إصدار .NET Core 2.1. (واجهت كومة من المشكلات مع الإصدار 2.0 وكانت هذه مجرد واحدة منها).

GC.Collect() لا يساعد. جربت واجهة برمجة تطبيقات ASP.NET Core 2.0 و 2.1 Web API بسيطة للغاية تحتوي على وحدة تحكم واحدة تُرجع قاموسًا من 200 كيلو بايت. تستمر الذاكرة المخصصة في الارتفاع مع كل طلب ، على الرغم من أن التطبيق لا يستخدم أي ذاكرة إضافية.

Serjster إرجاع 200 ألف أعداد صحيحة (4B) سيستغرق 800 كيلوبايت. في هذه الحالة أنت تواجه المشكلة الموضحة في هذا التعليق: https://github.com/aspnet/Home/issues/1976#issuecomment -289336916

في هذه الحالة ، يجب عليك استخدام مجموعة مصفوفة لإعادة استخدامها عبر الطلبات.

من الجيد أيضًا معرفة أنه إذا كان الرمز يعمل في وضع 64 بت ، فإن المصفوفات / القائمة وما إلى ذلك التي تحتوي على مؤشرات تكون ضعف الحجم مقارنة بـ 32 بت. إذا كنت أتذكر بشكل صحيح ، فإن الإطار الكامل يعمل على تشغيل أي كود وحدة المعالجة المركزية 32 بت في نظام تشغيل 64 بت افتراضيًا. لذلك قد يواجه الأشخاص الذين يرحلون رموزهم مشكلات LOH عن طريق الخطأ.

أنا أعمل مع Serjster ، وهذا ما وجدته. إذا قمت بإنشاء مشروع واجهة برمجة تطبيقات لويب الفانيليا باستخدام asp.net core (استخدمت 2.1 في آخر اختباري) ، فقد لاحظت أنه عندما أقوم بتشغيل أداة التشخيص (أو حتى التحقق من الذاكرة العاملة للعملية المحددة في الكود) ، فإن عدد البايت يعود يواصل التسلق عندما وصلت إلى نقطة النهاية. على سبيل المثال ، إذا كانت لدي نقطة نهاية واحدة لواجهة برمجة تطبيقات ويب تعرض قاموسًامع وجود 20000 عنصر بداخله ، يحدث ما يلي:

  1. أول زيارة لأسلوب وحدة التحكم تضع ذاكرة العملية عند 83 ميجا بايت.
  2. أنتظر بضع ثوان ، ثم انتقلت الزيارة الثانية إلى 86 ميغا بايت.
  3. أنتظر بضع ثوان ، وتنتقل الزيارة الثالثة إلى 90 ميغا بايت.
  4. مرة أخرى - 94 ميغا بايت.
  5. أفعل هذا n عدد المرات ، ويصل أخيرًا إلى حوالي 304 ميغا بايت. بمجرد أن يفعل هذا فإنه يستوي.

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

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

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

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

EDIT - redavidfowl تعليق: فيما يتعلق بتعليقك حول الأشياء التي يتم جمعها نادرًا ... قد يكون هذا منطقيًا. ولكن كم من الوقت يستغرق عادة؟ يمكنني الانتقال أكثر من 30 ثانية بين الطلبات ، ولا يبدو أن GC أبدًا تعيد رقم الذاكرة هذا في مخطط التشخيص إلى أسفل. أنا متأكد من أنني جاهل بشيء ما هنا ، لكنني أشعر بالفضول فقط.

تحرير 2 - الآن بعد أن قرأت رابط SO الذي نشره ديفيد أعلاه بمزيد من التفصيل ، بدأت أعتقد أن هذه هي بالتأكيد المشكلة التي نراها. إذا كنا نعمل في بيئة ذات ذاكرة محدودة (ونحن في بيئة التطوير الخاصة بنا حيث نشهد ذلك لأننا رخيصون) فإننا نواجه مشاكل مع هذا.

عدل 3 - سؤال واحد باقٍ. لماذا يتم رفع ذاكرة العملية باستمرار ، ولكن حجم الكومة لا يرتفع إذا كانت هذه مشكلة LOH؟ في الواقع ، قد أفهم هذا الآن. الكومة هي الذاكرة المستخدمة. الذاكرة المخصصة للمعالج هي الذاكرة المستخدمة بالإضافة إلى كتل الذاكرة المجزأة غير المستخدمة.

RemyArmstro هل يمكنك تغيير Dictionary<int, int> إلى SortedDictionary<int, int> ؟ ربما يقوم القاموس بتخصيص ذاكرة مستمرة ، وقد يضيف بعض البيانات الإضافية إلى كل إدخال. تم تطبيق طريقة SortedDictionary وسوف تقوم بإجراء العديد من التخصيصات الصغيرة بدلاً من تخصيص واحد كبير.

تحرير: إذا قمت بالتسلسل إلى سلسلة وليس مباشرة إلى تدفق إخراج الاستجابة ، فقد يتسبب ذلك أيضًا في تخصيصات LOH.

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

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

أتمنى أن تقوم Microsoft بإنشاء تطبيقات مقسمة يمكن للجميع استخدامها في مثل هذه المواقف.

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

Serjster ربما أنا أعمى فقط لكني لا أرى أي منشورات منك حيث قلت إن إرسال عنصر واحد أو قائمة صغيرة سيؤدي إلى حدوث ذلك. هل قمت بحذفه؟

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

private struct Entry
{
  public int hashCode;    // Lower 31 bits of hash code, -1 if unused
  public int next;        // Index of next entry, -1 if last
  public TKey key;           // Key of entry
  public TValue value;         // Value of entry
}

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

تفاصيل تنفيذ القاموس Dictionary.cs

تحرير: عنوان url ثابت

@ wanton7 شكرا لك. أعتقد أننا ندرك ما هي القضية الآن. إنها مجرد مشكلة لا يوجد حل رائع + بسيط لذلك. يتعلق الأمر بشكل أساسي بكونك أكثر وعياً بها وتعديل كيفية كتابتك للكود. الجانب السلبي هو أن هذه الذاكرة غير المدارة تبدأ في الشعور بإدارة أكثر قليلاً. :( في النهاية ، قد يكون لدينا عدد قليل فقط من المجالات التي تنتهك حقًا حد التخصيص هذا ، ولكن أحد المجالات أساسي جدًا لتطبيقنا ، لذلك نراه كثيرًا حاليًا. أعتقد أننا نحتاج فقط إلى إعادة التفكير في هذه القطعة ، رصد ، وحاول اكتشاف أي مناطق أخرى نلاحظ هذا الزحف. شكرا مرة أخرى!

لدينا بالفعل موقف مشابه قريبًا ونحتاج إلى إنشاء تطبيق IList<T> مقسم. سأستخدم بعض الحجم للقطع التي يمكن تغييرها قليلاً حتى أتمكن من استخدام bitshift والقناع للفهرسة.

أود أن أعرف أيهما أكثر فائدة لـ GC ، أم قطعة أكبر أم قطعة أصغر؟ من أحجام بين 1KB و 64KB. تعني القطع الأصغر عددًا أكبر من المراجع لـ GC ولكني أعتقد أن الجزء الأكبر قد يكون أسوأ بالنسبة للضغط والتجزئة.

فهمك صحيح تمامًا - سأذهب بأحجام ليست كبيرة جدًا ؛ ربما حاول 4K / 8k.

@ Maoni0 شكرا لك!

لقد اخترت 4KB ، حتى لا نحصل على أي مفاجآت سيئة إذا قمنا بتشغيل الكود الخاص بنا تحت Mono. اكتشف ذلك من خلال قراءة http://www.mono-project.com/docs/advanced/garbage-collector/sgen/working-with-sgen/ أن عتبة LOH هي فقط 8000 بايت تحت Mono.

هل هناك أي تقدم لهذه القضية؟

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

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

فيما يلي بعض العناصر التي يجب مراعاتها في وضعنا:

  • نقوم فقط بإرجاع كائن Dictionary<int, int> مع 1000 قيمة عددية مخزنة. لا شيء أكثر من ذلك.
  • قمنا بتحويل مشروعنا من .NET Core 2.0 -> 2.1
  • نرى هذه المشكلة في MS Visual Studio 2017

الكود على النحو التالي:

    public async Task<IActionResult> SampleAction()
    {
        var list = new Dictionary<int, int>();
        for (int n = 0; n < 1000; n++) list.Add(n, n);
        return Ok(list);
    }

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

أرى هذا أيضًا في أحد مشاريعي ، لكن يمكنني أيضًا إعادة إنشائه في استهداف واجهة برمجة تطبيقات أساسية .net جديدة تمامًا. Net Core 2.1 (SDK 2.1.302).

لقد أرفقت نموذج مشروع API الذي قمت بإنشائه باستخدام Visual Studio 15.8.0 Preview 4. لإظهار زيادة الذاكرة ، كان لدي تطبيق .net core console ، ضرب القيم الافتراضية GET endpoint كل نصف ثانية للحصول على السلسلتين. يكون استخدام ذاكرة العملية بطيئًا ولكن في مشروع يُرجع المزيد من البيانات يمكن أن ينمو هذا بسرعة.

screenshot
WebApplication1.zip

لقد وجدت هذا المنشور على تبادل المكدس:

https://stackoverflow.com/questions/48301031/why-doesnt-garbage-collector-in-net-core-2-0-free-all-memory

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

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

image

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

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

sebastienros إذن هل السلوك الذي أراقبه أنا و @ beef3333 يتوافق مع ما يمكن توقعه؟ على وجه التحديد ، أين تظل وحدات البايت الخاصة مرتفعة على الرغم من تناقص حجم الكومة؟ إذا كان الأمر كذلك ، يبدو غريباً بالنسبة لي أن كل طلب إضافي سيستمر في التسبب في نمو وحدات البايت الخاصة على الرغم من وجود مساحة خالية من الكومة.

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

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

سأختبر طلبك بعد ذلك ، شكرًا.

قمت بتشغيل التطبيق المقدم من @ beef3333 محليًا لمدة ساعتين ، بمعدل 5K RPS ، والذاكرة مستقرة (تباين 1 ميجا بايت بشكل عام ، 400 ميجا بايت على جهاز بسعة 32 جيجا بايت). يتم استدعاء GC بشكل صحيح. لقد تفقدت أيضًا العديد من مقالب النفايات في الوقت الإضافي وتم إنشاء المثيلات المختلفة وجمعها كما هو متوقع. أنا أستخدم 2.1.1.

sebastienros شكرًا لك على النظر في هذا. أعتقد أن الوجبات الجاهزة في كل هذا هي:

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

صححني إذا كنت مخطئًا ، ولكن يبدو أن .NET Core ستعمل على زيادة الذاكرة المخصصة بناءً على متوسط ​​الطلبات لضمان أسرع وقت استجابة؟ إذا كان هذا صحيحًا ، فهل سيكون من الآمن افتراض أنه من المحتمل عدم تحرير هذه الذاكرة المخصصة حتى يتم إعادة تعيين Application Pool - أم أنها ستحرر هذه الذاكرة المخصصة بمرور الوقت إذا انخفض RPS؟

المشكلة نفسها.
لدي خدمة خلفية asp.net webapi.
المداخن هي asp.net mvc ، و autofac ، و automapper ، و Castle.dynamicproxy ، و kian framework core.
ستؤكل كل الذاكرة ، ثم تعطل الخدمة.

الإصدار 2.1.0

تحديث atpyk @ إلى 2.1.1. إذا لم يساعدك ذلك فعليك تحديد ما الذي يحتفظ بهذه الذاكرة. لقد استخدمت https://www.jetbrains.com/dotmemory/ ولكن ربما توجد أدوات أخرى يمكنها القيام بذلك أيضًا. يمكن أن يُظهر ما تم تخصيصه بالفعل في كومة الكائنات الكبيرة (LOH).

هل تعمل في وضع 32 بت؟ لأن تخصيصات كومة الكائنات الكبيرة (أكبر من 85000 بايت تقريبًا) يمكن أن تتسبب في نفاد استثناءات الذاكرة في وضع 32 بت بسبب التجزئة. يمكنك تجاوز هذا الحد بسهولة بالغة باستخدام القاموس. تحقق من هذا التعليق https://github.com/aspnet/Home/issues/1976#issuecomment -393833505

إذا كنت تقوم بتشغيل التعليمات البرمجية الخاصة بك بالكامل ، فإن السلوك الافتراضي لـ NET Framework يقوم بتشغيل أي كود وحدة المعالجة المركزية في وضع 32 بت. تحتاج إلى إلغاء تحديد تفضيل 32 بت من إعدادات المشروع أو تعيين بعض إعدادات التسجيل في سجل الخوادم على الوضع الافتراضي إلى 64 بت.

@ wanton7 جزيل الشكر. سأحاول الحلول الخاصة بك.

لقد قمت بالتحديث إلى 2.1.2 ونشرت على Microsoft Azure webapp باستخدام win-x64 ، ولكن بلا تأثير. تضمين التغريدة
dotnetcorememory

atpyk ، يرجى إنشاء لقطة ذاكرة (dump_ وتحليلها (Visual Studio ، MemoScope) لمعرفة الكائن الذي يأخذ كل الذاكرة ، أو يزيد فقط في العدد. يمكنك أيضًا أخذ اثنتين ومقارنتهما بمرور الوقت.

sabastienros أعتقد أن عددًا كافيًا من الأشخاص قد أثار قلقًا بشأن هذا الأمر الذي يجب أن تبدأ أنت / MS في تحليل هذا بنفسك. ربما يعمل هذا كما كنت تقصد ، ولكن التصميم معيب بعد ذلك.

تنفد ذاكرة تطبيقاتنا في النهاية وتتعطل ، وكل هذا يعمل في بيئة إنتاج Azure. هذا غير مقبول.

atpyk فهذا يبدو وكأنه تسرب للذاكرة. قم بتوصيف ذاكرتك لترى ما الذي يحتفظ بهذه الذاكرة كما قال sebastienros .

سؤال واحد ، هل أنت حتى تستخدم ASP.NET Core؟ قرأت لك التعليق الأول مرة أخرى وقد ذكرت ASP.NET MVC. ASP.NET MVC و ASP.NET Core منتجان مختلفان تمامًا. هذه القضايا وهذا الريبو لـ ASP..Net Core.

تحرير: فقط من أرقام الإصدارات يبدو أنك تستخدم ASP.NET Core ، لكنك تريد التأكد.

نحن نستخدم .net core MVC. تضمين التغريدة
أنا أقوم بتحليل الذاكرة. ربما يؤدي Castle Dynamic Proxy إلى تسرب الذاكرة.
memroy1
memroy2
memroy3
dynamicproxy

Serjster هل تعمل برامجك في 32 بت. NET Core وتتعطل مع استثناءات نفاد الذاكرة؟ إذا كان الكود الخاص بك يقوم بالكثير من عمليات تخصيص LOH ، فمن المحتمل أن يكون السبب هو تجزئة الذاكرة.
إذا كنت تعمل في بيئة 32 بت ، فلديك خياران ، قم بإصلاح الكود الخاص بك لتجنب LOH أو التبديل إلى بيئة 64 بت.

لست على دراية كبيرة بـ Azure ولكن بعد قليل من البحث على googling وجدت هذا https://blogs.msdn.microsoft.com/webdev/2018/01/09/64-bit-asp-net-core-on-azure-app -الخدمات/

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

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

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

في كلتا الحالتين ، أعتقد أن نقطة Serjster هي أن هذا الخيط يستمر في النمو لأنه من الواضح أن هناك بعض الالتباس هنا. في أرض ASP.NET القديمة (قبل Core 1 على ما أعتقد) ، لم نكن بحاجة إلى رؤية هذا السلوك (على الأقل ليس بهذا الحجم. قد لا يكون حقًا خطأ / مشكلة ، ولكنه بالتأكيد شيء يسبب الكثير من الأشخاص لطرح نفس السؤال مرات ومرات.

سيكون من الرائع لو كانت هناك مقالة رسمية تتناول هذا الموضوع من أعلى إلى أسفل ، بدلاً من وضعه في دوائر كما كان. أتمنى أن يساعد ذلك في التوضيح.

سيكون من الرائع لو كانت هناك مقالة رسمية تتناول هذا الموضوع من أعلى إلى أسفل ، بدلاً من وضعه في دوائر كما كان. أتمنى أن يساعد ذلك في التوضيح.

أنا أوافق على ذلك. سيكون من الجيد لنا أن نعرف لماذا يعتبر .NET Core 2.1 أكثر "انتهازية" عندما يتعلق الأمر بإدارة الذاكرة مقارنة بالإصدارات السابقة.

sebastienros هل يمكننا من فضلك الحصول على ملخص للمشكلات هنا؟ هناك 81 تعليقًا - لدي انطباع بأنهم لا يتعلقون جميعًا بالمسائل (على الرغم من أنني لم أقرأها بعناية على الإطلاق ، لذا قد أكون مخطئًا). إذا كان الأمر كذلك ، فهل يمكننا سرد جميع المشكلات المميزة هنا ومعرفة ما إذا كان لدينا نسخ لكل منها؟ هناك عدد كافٍ من الأشخاص الذين ذكروا زيادة الذاكرة ، وأعتقد أن ذلك يبررنا للحصول على إعادة نسخ ومعرفة ما إذا كانت هذه مشكلات عامة أم لا.

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

بالتوازي مع ذلك ، سأعمل على مستند يسرد جميع التوصيات ، ومشكلات الذاكرة المعروفة (LOB ، HttpClient ، ...) وطرق تحليل هذه المشكلات والإبلاغ عنها.

فقط لأؤكد لكم أننا نهتم بهذه المشكلة ومن أجل اكتشاف تسرب الذاكرة بشكل استباقي ، على مدار الأشهر الستة الماضية ، كنا نشغل تطبيقات ASP.NET بشكل مستمر على Azure ، على كل من Linux و Windows ، لمدة 24 ساعة و 7 أيام. تجلب هذه الاختبارات أحدث مصدر لـ ASP.NET في كل تكرار (يوميًا أو أسبوعيًا). نحن نقيس استخدام RPS ووقت الاستجابة ووحدة المعالجة المركزية والذاكرة. يستخدم التطبيق EF Core و MVC و Razor ، ويتم دعمه حتى 50٪ من وحدة المعالجة المركزية لمحاكاة حمل كبير.

يمكنك مشاهدة النتائج علنا هنا على هذا الموقع (تصفح للعثور على التقرير اليومي): https://msit.powerbi.com/view؟r=eyJrIjoiYTZjMTk3YjEtMzQ3Yi00NTI5LTg5ZDItNmUyMGRlOTkwMGRlIiwidCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsImMiOjV9&pageName=ReportSectioneeff188c61c9c6e3a798

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

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

تم عزل جميع التقارير الفردية وستحصل على متابعة فردية ، وسيتم إغلاقها إذا تم حلها بالفعل. لا تتردد في الاشتراك في هذه لتظل على اطلاع.

بالتوازي مع ذلك ، سأعمل على مستند يسرد جميع التوصيات ، ومشكلات الذاكرة المعروفة (LOB ، HttpClient ، ...) وطرق تحليل هذه المشكلات والإبلاغ عنها.

هذا +1 ضخم مني. أشعر أن إحدى أكبر المشكلات هنا هي مدى صعوبة "الشعور" بجمع المعلومات ، ثم محاولة المساعدة في تحديد _ ما هي المشكلة. إن وجود بعض المستندات الرائعة التي يمكن أن تسمح لنا باتباع بعض التعليمات لكل من (1) التجميع ، (2) محاولة التشخيص الذاتي و (3) نشر مقالب / نتائجنا بطريقة فعالة لفريق MS يمكن أن يساعد حقًا كليهما جوانب السياج.

إذا كان بإمكاننا (المطورين) تمكيننا بشكل أفضل من التشخيص و / أو تقديم المعلومات ، فهذا يعد فوزًا للجميع.

شكرًا مرة أخرى على الاستماع إلى sebastienros - أقدر ذلك كثيرًا يا صديقي!

ما رأيك في الوضع في الصورة أدناه؟

نقوم بتشغيل 4 تطبيقات ويب داخل نفس الخطة. في البداية كانت B1 ، وتم توسيع نطاقها إلى S2 واستمرت الذاكرة في النمو حتى ضبطت على webapp csproj الجائع:

<ServerGarbageCollection>false</ServerGarbageCollection>

وكذلك تعطيل Application Insights

  1. أعتقد أنه نظرًا لأنه يمكن الاحتفاظ بالذاكرة تحت السيطرة مع الإعداد أعلاه ، فلا يوجد تسرب للذاكرة. صيح؟
  2. هل السلوك المقدم طبيعي؟

memory eaten up

نفس الموقف هنا مثل alexiordan ، كان لدينا وحدة تحكم .net core 2.1 ، والتي تدير بعض خدمات IHostedServices المستضافة في Kube ، من Microsoft / dotnet: 2.1-runtime AS base. أردنا تمكين HealthChecks لذلك أضفنا asp.net باستخدام البرامج الوسيطة HealthChecks فقط وغيرنا الصورة الأساسية إلى microsoft / dotnet: 2.1-aspnetcore-runtime. كانت النتيجة OOM. لقد تمكنا من تحقيق الاستقرار في تخصيص الذاكرة عن طريق الإضافةخاطئة في csproj.

أظهر تحليلنا أنه في تطبيق asp.net ، يتم تجميع GC بشكل أقل تكرارًا ، كما يتم اجتياز قائمة انتظار Finalizer بشكل أقل تكرارًا.

أيضًا ، إذا أجبرنا GC على جمع واجتياز قائمة انتظار النهائية عن طريق إضافة ما يلي في خط الأنابيب لدينا ،

System.GC.Collect () ،
System.GC.WaitForPendingFinalizers () ،
System.GC.Collect () ،

ظل تخصيص الذاكرة مستقرًا.

ما رأيك في الوضع في الصورة أدناه؟

نقوم بتشغيل 4 تطبيقات ويب داخل نفس الخطة. في البداية كانت B1 ، وتم توسيع نطاقها إلى S2 واستمرت الذاكرة في النمو حتى ضبطت على webapp csproj الجائع:

<ServerGarbageCollection>false</ServerGarbageCollection>

وكذلك تعطيل Application Insights

  1. أعتقد أنه نظرًا لأنه يمكن الاحتفاظ بالذاكرة تحت السيطرة مع الإعداد أعلاه ، فلا يوجد تسرب للذاكرة. صيح؟
  2. هل السلوك المقدم طبيعي؟

memory eaten up

يا alexiordan

نشاهد أيضًا ملف تعريف ذاكرة مشابهًا جدًا عند استخدام AI (تطبيق ويب على net core 2.1) أيضًا ، هل تقدمت أكثر في حل هذا الأمر؟ من الواضح أننا نريد الاحتفاظ بالذكاء الاصطناعي في التطبيقات.

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

نسيت أن أذكر أنه بعد فترة وجيزة من إعلان نيتي لكتابة مقال حول المشكلات الموضحة في هذا الموضوع ، قمت بذلك بالفعل. يمكنك رؤيته هنا: https://github.com/sebastienros/memoryleak

يأتي مع تطبيق صغير يجعل الأنماط على الرسم البياني حية.

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

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

ضبط SGC على false ، انخفض api الأساسي asp.net الخاص بي من 150 ميجابايت إلى 48 ميجابايت ، ولم ينمو عند كل طلب بعد ذلك. إذن هل هذا في الواقع هو أفضل مكان للإنتاج في الوقت الحالي؟

kgrosvenor في الواقع ، هذا يعتمد. نقلاً عن مقال sebastienros الممتاز:

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

شكرًا لك ، هذا مفيد جدًا ، سأضع في الاعتبار - سأتبع هذا الموضوع للحصول على أي تحديثات أخرى ، يقال إنني أحب قلب asp.net تمامًا :)

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

أي أخبار في هذا الجانب؟ لدينا أيضًا نفس السلوك في ASP.Net Core v2.1. مما يمكنني رؤيته في الالتزام https://github.com/aspnet/AspNetCore/commit/659fa967a1900653f7a82f02624c7c7995a3b786 يبدو أن هناك مشكلة في إدارة الذاكرة سيتم إصلاحها في الإصدار 3.0؟

@ flo8 هل حاولت الترقية إلى 2.2 وفحصت السلوك؟ https://dotnet.microsoft.com/download

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

@ dre99gsx يبدو أنك حصلت على نسخة سهلة ، هل يمكنك مشاركة مشروع وخطوات حتى أتمكن من فعل الشيء نفسه محليًا؟

في هذه الحالة ، يجب أن تملأ LOB ولكن يجب جمعها في gen2. يرجى أيضًا مشاركة البيئة التي يمكنني إعادة نسخها ، ونظام التشغيل ، والذاكرة ، والتحميل.

آسف للرد غامض. سهل جدا:
(Windows 7 64bit و 16GB RAM و Google chrome لطلبات http ومجتمع VS2017) - ما زلت معتادًا على إضافة رمز إلى سلاسل الرسائل هذه ، والعفو عن المظهر)

  • بدء تطبيق ويب .NET Core 2.2 جديد
  • قم بإدخال فئة خدمة ، محددة النطاق (لا شيء خاص ..) في مُنشئ وحدة التحكم
  • اجعل إجراء الفهرس () لوحدة التحكم يستدعي طريقة من فئة الخدمة هذه
  • قم بإنشاء فئة نموذج (DumbClass) بخاصية واحدة: معرف int العامة {get؛ تعيين؛}
  • في طريقة فئة الخدمة ، قم بإنشاء مثيل لقائمة وقم بتعبئتها:
    var lst = قائمة جديدة() ؛
    لـ (i = 0 ؛ i <10000000 ؛ i ++) <--- ملاحظة: 10 مليون تكرار
    {
    lst.add (new DumbClass () {ID = i}) ؛
    }
  • العودة من الطريقة ، لا تحتاج إلى تمرير أي شيء مرة أخرى ، ولكن يمكنك تمرير تلك القائمة مرة أخرى أيضًا ...
  • index () إرجاع جديد EmptyResult () ؛

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

بدء التطبيق: 155 ميجا بايت
طلب الحصول على http الأول: 809 ميجا بايت
الثاني: 1.2 جيجابايت
الثالث: 1.4 جيجابايت
الرابع: 1.8 جيجابايت
الخامس: 2.1 جيجا ... 2.3 جيجا ... 2.6 جيجا ...

الآن ، في مرحلة ما ، يبدو أن GC بدأت ، لكنها لا تقل أبدًا عن 3 جيجابايت في هذا المثال. كما ذكرنا سابقًا ، إذا قمت بتحويل ServerGC إلى false ، فلن يزيد أبدًا عن 1 غيغابايت ، على الرغم من أنه لا يزال يرتفع هناك ويحوم عند 1 غيغابايت.

اسمحوا لي أن أعرف ما إذا كان ذلك يساعد ، وإذا كان يمكنك إعادة إنتاجه. أوه ، لقد قرأت من خلال منشور github الخاص بك: "إدارة الذاكرة والأنماط في ASP.NET Core" ، كتابة رائعة ، شكرًا للمساهمة!

@ dre99gsx 👋

ما زلت معتادًا على إضافة رمز إلى هذه المواضيع ، عفوا عن المظهر)

لا توجد مشكلات على الإطلاق :) سؤال: هل يمكنك بالفعل وضع نموذج التطبيق بالكامل على GitHub (الريبو المجاني) أو في مكان ما مشابه؟ هذه هي أبسط طريقة لأي شخص آخر لاستنساخ / تنزيل التطبيق / الريبو بأكمله بسرعة ، والذي كنت تلعب به.

أيضًا ، قد تساعد لقطات الشاشة لاستخدام الذاكرة باستخدام TaskManager (إذا كان الأمر على windows - أو المعادل في * nix .. وهو الأمر top ؟؟)

جهد كبير حتى الآن!

/ أعود لمشاهدة هذا الموضوع بصمت بجدية.

تذكير يمكنك مشاهدة بعض العروض التوضيحية والشرح لجميع الأعراض الموضحة في الموضوع هنا: https://github.com/sebastienros/memoryleak

كما تم التعامل مع كل من هذه المشكلات بشكل فردي ولم يثبت أي منها أنها أخطاء في dotnet core __ حتى الآن _ ، ولكن السلوك المتوقع.

@ dre99gsx الآن بالعودة إلى التعليق الأخير ، أود أن أحثك ​​على تقديم قضية منفصلة عن هذا الموضوع. كوني على هاتفي لم أدرك أنه كان "هذا" ؛). من أول تعليق لك تقوله

حتى نفاد الذاكرة

لذلك أتوقع استثناء OutOfMemory ، وهذا هو السبب في أنني سألت عن Repro. لكنك تذكر في تعليقك التالي:

الآن ، في مرحلة ما ، يبدو أن GC بدأت ، لكنها لا تقل أبدًا عن 3 جيجابايت في هذا المثال

لذلك لا توجد مشكلة في الذاكرة. هذا أمر نموذجي من آلة بها الكثير من النوى والكثير من الذاكرة المتاحة. ستقوم GC بتحرير الأكوام المُدارة ، لكن الذاكرة ستظل ملتزمة نظرًا لعدم وجود سبب لإلغاء الالتزام بها (الكثير من الذاكرة المتاحة). هذا سلوك قياسي في .NET ، وقد عرضته في المقالة التي أشرت إليها. يمكنك أيضًا قراءة هذا: https://blogs.msdn.microsoft.com/maoni/2018/11/16/running-with-server-gc-in-a-small-container-scenario-part-0/

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

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

هذا صحيح ، عندما ذكرت "نفاد الذاكرة" ، فإنني أؤسس ذلك على عدم رؤية أي ذاكرة متاحة لأي تطبيق آخر عبر Windows Private Working Set (مدير المهام) ؛ ليس "استثناء نفاد الذاكرة".

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

لقد قمت بتطوير تطبيقي في Asp.net core 2.2 ويواجه أيضًا نفس المشكلة المتعلقة بإصدار الذاكرة.
تعمل كل مكالمة على زيادة الذاكرة في نطاق 40-50 ميجا بايت في كل مرة لا يتم تحريرها مطلقًا.

لقد أضفت أيضًا العلامة المذكورة ServerGarbageCollection> false
لا تزال تواجه نفس المشكلة لـ 50 مستخدمًا ، فهي تستخدم حوالي 2 غيغابايت من ذاكرة الوصول العشوائي في وضع قيد المعالجة (عملية العامل w3wp iis)

الرجاء المساعدة.

الرجاء المساعدة !! نفس المشكلة مثل ankitmori14

@ ankitmori14 ، ikourfaln - إذا كنت قد قرأت تعليقsebastienros على https://github.com/aspnet/AspNetCore/issues/1976#issuecomment -449675298 وما زلت تعتقد أن هناك مشكلة في الذاكرة ، يرجى تقديم مشكلة جديدة بخطوات تفصيلية لإعادة إظهار المشكلة ، بالإضافة إلى أي معلومات وآثار أخرى لديك حول السلوك. يرجى تذكر أنه ما لم تكن هناك أخطاء بالفعل في التطبيق / العملية ، فمن غير المحتمل (ولكن ليس من المستحيل) أن يكون هناك خطأ. لا يحاول جامع القمامة الافتراضي "الخادم" استخدام أقل قدر ممكن من الذاكرة ؛ بدلاً من ذلك ، يبدأ عندما يحتاج إلى ذلك ، مثل عندما تنفد الذاكرة بالفعل. لذلك حتى التطبيق الصغير قد يستخدم ذاكرة 2 جيجا بايت وهذه ليست مشكلة لأنه لا يزال هناك 4 جيجا بايت خالية.

أهلا،

نحن نواجه هذه المشكلة: https://stackoverflow.com/questions/53868561/dotnet-core-2-1-hoarding-memory-in-linux

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

قمنا أيضًا بتعطيل GC المتزامن (أي: خلفية GC) أمس ويبدو أنه أفضل الآن ، ولكن سيتعين علينا الانتظار لمدة أسبوع على الأقل للتأكيد.

<PropertyGroup>
  <ServerGarbageCollection>false</ServerGarbageCollection>
  <ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>
</PropertyGroup>

سؤال vtortola ، عندما قمت بتكوين حد 512 ميغا بايت لتطبيقك ، هل لديك فكرة عن عدد الطلبات المتزامنة التي تريد معالجتها أو اختبار عدد الطلبات المتزامنة التي يمكن لتطبيقك معالجتها قبل السقوط ؟؟

لقد أجرينا بعض الاختبارات الأولية والتقريبية وفحصنا أنه يمكننا التعامل مع 500 موقع ويب متزامن لكل جراب باستخدام 512 ميجابايت. لقد عملنا لساعات مع 2 جراب و 1000 اتصال متزامن مع ذاكرة أقل من 150 ميجابايت. يحتوي التطبيق المنشور ، مع 2 pods ، على ما بين 150 و 300 اتصال متزامن في أي لحظة ، وتتنوع الذاكرة من أقل من 100 ميجا بايت في الأيام القليلة الأولى ، حتى تصل إلى 512 ميجا بايت في حوالي أسبوعين. يبدو أنه لا يوجد ارتباط بين عدد الاتصالات والذاكرة المستخدمة. أكثر من 70٪ من الاتصالات تدوم 10 دقائق.

هل يمكنك مشاركة ملف تفريغ للذاكرة عندما يكون حجمه 100 ميغا بايت و 512 ميغا بايت لمعرفة الحالات التي لا تزال على قيد الحياة؟

أخشى أنه لا يمكنني مشاركة ملف تفريغ ، لأنه يحتوي على ملفات تعريف الارتباط والرموز والكثير من البيانات الخاصة.

هل يمكنك المقارنة بعد ذلك محليًا؟ من حيث الشيء الذي يأخذ أكبر قدر من الذاكرة ، وما إذا كان عددهم لا يرتبط بالحمل الخاص بك. كما لو كان لديك 300 اتصال فلا ينبغي أن يكون هناك كائنات اتصال 3K.

لسوء الحظ ، لم يساعد اختبار إعداد <ConcurrentGarbageCollection>false</ConcurrentGarbageCollection> وما زالت العملية تخزن الذاكرة.

لدينا تفريغ لينكس للعملية ، والأداة الوحيدة التي لدينا لتحليلها هي lldb ونحن مستجدون جدًا في هذا الأمر.

إليك بعض البيانات في حالة قرع الجرس:

(lldb) eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00007F8481C8D0B0
generation 1 starts at 0x00007F8481C7E820
generation 2 starts at 0x00007F852A1D7000
ephemeral segment allocation context: none
         segment             begin         allocated              size
00007F852A1D6000  00007F852A1D7000  00007F853A1D5E90  0xfffee90(268430992)
00007F84807D0000  00007F84807D1000  00007F8482278000  0x1aa7000(27947008)
Large object heap starts at 0x00007F853A1D7000
         segment             begin         allocated              size
00007F853A1D6000  00007F853A1D7000  00007F853A7C60F8  0x5ef0f8(6222072)
Total Size:              Size: 0x12094f88 (302600072) bytes.
------------------------------
GC Heap Size:            Size: 0x12094f88 (302600072) bytes.

ونتيجة dumpheap -stat : https://pastebin.com/ERN7LZ0n

يمكنك معرفة كيفية قيام Grafana بالإبلاغ عن حالة الذاكرة في https://stackoverflow.com/questions/53868561/dotnet-core-2-1-hoarding-memory-in-linux

لدينا مجموعة أخرى من الخدمات في dotnet core والتي تعمل بشكل لا تشوبه شائبة ، على الرغم من أنها لا تستخدم مآخذ ويب.

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

قد يكون هناك أيضًا بعض التعارض بين GC و Kubernetes ، بطريقة لا يتم تحذير GC من أنها قريبة من حد الكبسولة.

richlander يعمل على مشكلة مماثلة. هل هذه الحالة ريتش (اقرأ آخر 6 تعليقات فقط) يمكن أن تكون مرتبطة بما تعمل عليه؟

إذا حدث أي فرق ، فلدي نفس المشكلة (أو مشابهة جدًا). لدي عشرات + .net core 2.1 و 2.2 من تطبيقات وحدة التحكم التي تعمل على docker - كل حاوية بها حد ذاكرة 512 ميجا بايت ، وأيضًا باستخدام مقابس الويب (العميل) ، وتصل التطبيقات إلى حد ذاكرة الحاوية كل 3 أيام تقريبًا. ثم يتم إغلاق الحاوية وإعادة تشغيلها.

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

ما هي المعلمات التي تستخدمها لضبط حدود الذاكرة؟ فقط --memory أو أيضًا --memory-swap ؟

عندما أختبرها ، أستطيع أن أرى أنها تؤخذ في الاعتبار جيدًا ، ولا تتجاوز أبدًا الحد الذي حددته ، حتى مع وجود حد منخفض للغاية مثل 16 ميغا بايت ، ومع ذلك يتم تبديله على القرص كالمجانين. وأقوم باختبار تطبيق يقوم بإجراء استعلامات db (EF) وعرض طرق عرض Razor.

sebastienros بالتأكيد ، لقد أنشأت https://github.com/aspnet/AspNetCore/issues/6803

اسمحوا لي أن أعرف إذا كنت بحاجة إلى مزيد من المعلومات.

أواجه حاليًا مشكلات في الذاكرة.

بعد ساعة من الإنتاج ، يتم استخدام الذاكرة بالكامل بواسطة عملية w3wp.exe (تشغيل .NET Core InProcess). تغيير GC إلى محطة عمل ، لم يفعل الحيلة بالنسبة لي.

بعد تحليل تفريغ الذاكرة ، وجدت هذه المشكلة المشابهة ، https://github.com/aspnet/AspNetCore/issues/6102.

آمل أن أجربه في الإنتاج لاحقًا اليوم ، بعد الترقية إلى أحدث وقت تشغيل لـ .NET Core ، حاليًا 2.2.3. سوف نعلمك كيف ستسير الامور.

أواجه مشكلات مماثلة في استخدام الذاكرة. إذا وضعت قيودًا على حاويات Linux الخاصة بي ، فهذا يجعلها أسرع. حتى أنه يحدث باستخدام القوالب الأساسية في Visual Studio. شيء واحد وجدته - تأثر Core 2.1 و 2.2. Core 2.0 ليس - لكنه EOL :(

أنظر فوق

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

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

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

PrefabPanda تأكد من أنك تعمل بالفعل في وضع GC لمحطة العمل عن طريق التحقق من أن System.Runtime.GCSettings.IsServerGC هو false .

ثم قد يكون هذا تسربًا حقيقيًا للذاكرة. فتح قضية منفصلة ربما أفضل خطوة.

@ wanton7 - شكرًا ، لقد راجعت مرة أخرى وتم تعيين ذلك بالتأكيد.

DAllanCarr - سأفعل

أنا على يقين من أنه ليس تسربًا للذاكرة. قد لا يتم فرض إعدادات Docker بشكل صحيح ولا يتم تشغيل GC قبل الوصول إلى الحد الأقصى. أعلم أن الإصدار 3.0 يقدم إصلاحات بهذا المعنى.

richlander ، هل تبدو هذه المشكلة وكأنها شيء معروف أنه لا يعمل في الإصدار 2.2؟

PrefabPanda ، هل تمانع في مشاركة إصدار عامل الإرساء الذي تستخدمه بالضبط وملف إنشاء عامل الإرساء؟ أحاول إعادة إجراء النسخ ولكن بين إصدارات عامل الإرساء و docker-compose أجد صعوبة في تكرار هذه المشكلة محليًا.

sebastienros ، richlander - شكرًا على عودتك إليّ. أنا فعلا أقدر ذلك.

إصدارات My Docker:

مجتمع Docker Desktop
الإصدار 2.0.0.2 (30215)

المحرك: 18.09.1
تكوين: 1.23.2

انظر مرفق مشروع الاختبار بأكمله:
WebApplication1.zip

اختبار طلبات curl.zip

فقط في حالة ، ملف Docker الخاص بي:

من mcr.microsoft.com/dotnet/core/ aspnet: 2.2 AS أساس
WORKDIR / التطبيق
كشف 80
كشف 443

من mcr.microsoft.com/dotnet/core/ sdk: 2.2 AS build
WORKDIR / SRC
COPY ["WebApplication1 / WebApplication1.csproj"، "WebApplication1 /"]
استعادة RUN dotnet "WebApplication1 / WebApplication1.csproj"
ينسخ . .
WORKDIR "/ src / WebApplication1"
RUN dotnet بناء "WebApplication1.csproj" -c Release -o / app

من بناء AS نشر
تنشر RUN dotnet "WebApplication1.csproj" -c Release -o / app

من القاعدة كنهائي
WORKDIR / التطبيق
نسخ - من = نشر / تطبيق.
ENTRYPOINT ["dotnet"، "WebApplication1.dll"]

docker-compose.yml:

الإصدار: "2.4"

خدمات:
تطبيق الويب 1:
الصورة: $ {DOCKER_REGISTRY-} webapplication1
حفظ الذاكرة: 128 م
mem_limit: 256 م
memswap_limit: 256 م
cpus: 1
يبني:
سياق الكلام: .
dockerfile: WebApplication1 / Dockerfile

docker-compose-override.yml:

الإصدار: "2.4"

خدمات:
تطبيق الويب 1:
بيئة:
- ASPNETCORE_ENVIRONMENT = التطوير
- ASPNETCORE_URLS = https: // +: 443؛ http: // +: 80
- ASPNETCORE_HTTPS_PORT = 44329
- DOTNET_RUNNING_IN_CONTAINER = صحيح
- DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = صحيح
- ASPNETCORE_preventHostingStartup = صحيح
الموانئ:
- "50996: 80"
- "44329: 443"
أحجام:
- $ {APPDATA} /ASP.NET/Https:/root/.aspnet/ https: ro
- $ {APPDATA} /Microsoft/UserSecrets:/root/.microsoft/us ersecrets: ro

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

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

PrefabPanda عندما قلت "لقد حاولت الاتصال بها صراحة" ، هل يمكنك من فضلك توضيح ما الذي يعنيه بالضبط؟ يرى GC حد ذاكرة الحاوية الصحيح إذا كان لديك حد محدد ، سواء تم تشغيله بشكل طبيعي أو مستحث. إذا اتصلت بـ GC.Collect () ، فستقوم بمجموعة حظر كاملة ؛ وإذا قمت بإجراء GC.Collect (2، GCCollectionMode.Default، true، true) ، فسوف تقوم بعمل GC ضغط كامل ، عندما يعيد هذا الكومة بأصغر حجم ممكن ، بغض النظر عن حد الحاوية أو أي شيء آخر.

مرحبًا @ Maoni0 - لقد جربت GC.Collect (2 ، GCCollectionMode.Default ، true ، true)

لقد رأيت للتو تعليقًا آخر يقول إن 256 ميجا بايت صغيرة جدًا بالنسبة إلى 2.2 ، ولكن قد يتم "إصلاحها" في الإصدار 3.0. يبدو أنني سأحتاج إلى تجربة المزيد ...

إذا جربت GC.Collect (2، GCCollectionMode.Default، true، true) ولم تنخفض الذاكرة كما تتوقع ، فهذا يعني أن لديك تسريبًا حقيقيًا للذاكرة. لست متأكدًا من مقدار الأدوات المتوفرة في بيئتك. هل يمكنك تشغيل أوامر الاستغاثة على الإطلاق؟ إذا كان الأمر كذلك ، يمكنك دائمًا البحث لمعرفة ما تبقى على الكومة بعد GC الخاص بك المستحث

شكرًا @ Maoni0 - ضع في اعتبارك أنني أستخدم نموذجًا في Visual studio - لا يوجد رمز خاص بي حرفيًا في مشروع الاختبار هذا الذي أرفقته. لدي بعض التعليقات الأخرى للعمل عليها ، وسأكون على اتصال. تشكرات.

@ Maoni0 - حاولت تعيين حد أعلى ، لا فرق. يبدو أنني سأضطر إلى تجربة معاينة 3.0

أرغب في قفل التعليقات حول هذه المشكلة لأنها مشكلة قديمة جدًا تم التعامل مع جميع حالاتها في قضايا منفصلة. لقد علقت على هذا عن طريق الخطأ معتقدًا أنني كنت أعلق على https://github.com/aspnet/AspNetCore/issues/10200

شكرا

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات