سؤال

يبدو أن استخدام الأقسام المهمة كثيرًا في نظام التشغيل Vista/Windows Server 2008 يؤدي إلى عدم استعادة نظام التشغيل الذاكرة بالكامل.لقد وجدنا هذه المشكلة في تطبيق دلفي ومن الواضح أن السبب هو استخدام CS API.(انظر الى هذا هذا سؤال)

هل رآه أي شخص آخر مع التطبيقات المطورة بلغات أخرى (C++، ...)؟

كان نموذج التعليمات البرمجية يقوم فقط بتهيئة 10000000 CS، ثم حذفها.يعمل هذا بشكل جيد في XP/Win2003 ولكنه لا يحرر كل الذاكرة القصوى في Vista/Win2008 حتى ينتهي التطبيق.
كلما زاد استخدامك لـ CS، زاد احتفاظ تطبيقك بالذاكرة مقابل لا شيء.

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

المحلول

لقد غيرت مايكروسوفت بالفعل الطريق InitializeCriticalSection يعمل على نظام التشغيل Vista وWindows Server 2008 وربما أيضًا Windows 7.
لقد أضافوا "ميزة" للاحتفاظ ببعض الذاكرة المستخدمة لمعلومات التصحيح عند تخصيص مجموعة من CS.كلما قمت بتخصيص المزيد، تم الاحتفاظ بمزيد من الذاكرة.قد يكون مقاربًا ثم يتسطح في النهاية (لم يتم شراءه بالكامل لهذا).
لتجنب هذه "الميزة"، عليك استخدام واجهة برمجة التطبيقات الجديدة تهيئة CriticalSectionEx وتمرير العلم CRITICAL_SECTION_NO_DEBUG_INFO.
وتتمثل ميزة ذلك في أنه قد يكون أسرع، لأنه في كثير من الأحيان، سيتم استخدام عدد الدوران فقط دون الحاجة إلى الانتظار فعليًا.
العيوب هي ذلك قد تكون تطبيقاتك القديمة غير متوافقة, ، تحتاج إلى تغيير الكود الخاص بك وهو الآن يعتمد على النظام الأساسي (عليك التحقق من الإصدار لتحديد الإصدار الذي ستستخدمه).وأيضًا تفقد القدرة على تصحيح الأخطاء إذا كنت بحاجة.

مجموعة أدوات الاختبار لتجميد نظام التشغيل Windows Server 2008:
- أنشئ مثال C++ هذا كـ CSTest.exe

#include "stdafx.h" 
#include "windows.h" 
#include <iostream> 

using namespace std; 

void TestCriticalSections() 
{ 
  const unsigned int CS_MAX = 5000000; 
  CRITICAL_SECTION* csArray = new CRITICAL_SECTION[CS_MAX];  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    InitializeCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    EnterCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    LeaveCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    DeleteCriticalSection(&csArray[i]); 

  delete [] csArray; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
  TestCriticalSections(); 

  cout << "just hanging around..."; 
  cin.get(); 

  return 0; 
}

-...قم بتشغيل هذا الملف الدفعي (يحتاج إلى ملف Sleep.exe من خادم SDK)

@rem you may adapt the sleep delay depending on speed and # of CPUs 
@rem sleep 2 on a duo-core 4GB. sleep 1 on a 4CPU 8GB. 

@for /L %%i in (1,1,300) do @echo %%i & @start /min CSTest.exe & @sleep 1 
@echo still alive? 
@pause 
@taskkill /im cstest.* /f

-...وشاهد خادم Win2008 بسعة 8 جيجابايت ووحدة معالجة مركزية رباعية النواة يتم تجميدها قبل الوصول إلى 300 مثيل تم إطلاقها.
-... كرر ذلك على خادم يعمل بنظام التشغيل Windows 2003 وشاهده يتعامل معه كالسحر.

نصائح أخرى

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

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

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

وأنت ترى شيئا آخر.

ولقد بنيت ويدير هذا الرمز الاختبار. كل القانون الأساسي استخدام الذاكرة هو ثابت - وحدات البايت الخاصة، مجموعة العمل، والالتزام، وهلم جرا

int _tmain(int argc, _TCHAR* argv[])
{
    while (true)
    {
        CRITICAL_SECTION* cs = new CRITICAL_SECTION[1000000];
        for (int i = 0; i < 1000000; i++) InitializeCriticalSection(&cs[i]);
        for (int i = 0; i < 1000000; i++) DeleteCriticalSection(&cs[i]);
        delete [] cs;
    }

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