سؤال

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

لذلك، كنا نبحث في بعض آليات تخصيص الذاكرة البديلة التي قد تساعدنا وآمل أن يخبرني أحد بأفضلها:

1) استخدم ويندوز كومة تجزئة منخفضة

2) جيمالوك - كما هو مستخدم في فايرفوكس 3

3) دوغ ليا malloc

تم تطوير عملية الخادم لدينا باستخدام كود C++ عبر الأنظمة الأساسية، لذا فإن أي حل سيكون مثاليًا عبر الأنظمة الأساسية أيضًا (هل تعاني أنظمة التشغيل *nix من هذا النوع من تجزئة الذاكرة؟).

أيضًا، هل أنا على حق في اعتقادي أن LFH هي الآن آلية تخصيص الذاكرة الافتراضية لنظام التشغيل Windows Server 2008/Vista؟...هل "ستختفي" مشاكلي الحالية إذا قام عملاؤنا ببساطة بترقية نظام تشغيل الخادم الخاص بهم؟

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

المحلول

أولاً، أتفق مع الملصقات الأخرى التي اقترحت تسرب الموارد.تريد حقًا استبعاد ذلك أولاً.

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

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

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

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

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

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

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

نصائح أخرى

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

بافتراض أن تطبيقك يتصرف كما يلي:
تخصيص 10 ميغا بايت
تخصيص 1 بايت
10 ميجابايت مجانًا
(عفوًا، لم نحرر البايت الواحد، ولكن من يهتم بالبايت الصغير الواحد)

يبدو أن هذا تسرب صغير جدًا، بالكاد ستلاحظ ذلك عند مراقبة إجمالي حجم الذاكرة المخصصة فقط.لكن هذا التسرب سيؤدي في النهاية إلى ظهور ذاكرة التطبيق لديك بالشكل التالي:
.
.
مجاني – 10 ميجابايت
.
.
[المخصصة -1 بايت]
.
.
مجاني – 10 ميجابايت
.
.
[المخصصة -1 بايت]
.
.
مجاني – 10 ميجابايت
.
.

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

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

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

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

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

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

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

يمكنك استخدام _CrtDumpMemoryLeaks();لتفريغ تسرب الذاكرة إلى نافذة التصحيح عند تشغيل بناء تصحيح، ومع ذلك أعتقد أن هذا خاص بالمترجم Visual C.(إنه موجود في crtdbg.h)

أشك في حدوث تسرب قبل الشك في التجزئة.

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

سأطلق أداة مثل valgrind أو أقوم ببعض التسجيل المكثف للبحث عن الموارد التي لم يتم تحريرها.

@nsaners - أنا متأكد من أن المشكلة تعود إلى تجزئة الذاكرة.لقد قمنا بتحليل com.minidumps يشير ذلك إلى وجود مشكلة عند تخصيص جزء كبير من الذاكرة (5-10 ميجابايت).لقد قمنا أيضًا بمراقبة العملية (في الموقع وفي التطوير) للتحقق من تسرب الذاكرة - ولم يتم اكتشاف أي تسرب (بصمة الذاكرة منخفضة جدًا بشكل عام).

تحدث المشكلة بالفعل على نظام التشغيل Unix، على الرغم من أنها عادةً ليست بنفس السوء.

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

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

كالعادة، يمكنك عادة إضاعة الذاكرة للحصول على بعض السرعة.

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

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

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

قد تعاني ذاكرتك وسرعتك قليلاً (التبديل) ولكن الأجهزة السريعة وذاكرة الوصول العشوائي الكبيرة يجب أن تكون قادرة على المساعدة.

كانت هذه خدعة قديمة لنظام UNIX مع الشياطين، عندما لم تكن الخيوط موجودة بعد.

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

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