2010-10-25 10 views
14

मैं एक एप्लीकेशन (.NET 4.0, C#) विकसित कर रहा हूं जो:
1. फ़ाइल सिस्टम स्कैन करता है।
2. कुछ फ़ाइलों को खोलता है और पढ़ता है।.NET अनुप्रयोग में I/O संचालन को सीमित कैसे करें?

ऐप पृष्ठभूमि में काम करेगा और डिस्क उपयोग पर कम प्रभाव डालना चाहिए। यदि उपयोगकर्ताओं को उनके सामान्य कार्य कर रहे हैं और डिस्क उपयोग उच्च है तो इसे उपयोगकर्ताओं को परेशान नहीं करना चाहिए। और इसके विपरीत, अगर कोई डिस्क का उपयोग नहीं कर रहा है तो ऐप तेजी से जा सकता है।
मुख्य मुद्दा यह है कि मुझे फ़ाइलों को पढ़ने के लिए API (mapi32.dll) का उपयोग करने के कारण I/O संचालन की वास्तविक राशि और आकार नहीं पता है। अगर मैं कुछ करने के लिए एपीआई से पूछता हूं तो मुझे नहीं पता कि यह मेरी प्रतिक्रिया को संभालने के लिए कितने बाइट पढ़ता है।

तो प्रश्न डिस्क उपयोग की निगरानी और प्रबंधन कैसे करें? फ़ाइल सिस्टम स्कैनिंग और फ़ाइलों को पढ़ने सहित ...
मानक प्रदर्शन मॉनीटर टूल द्वारा उपयोग किए जाने वाले प्रदर्शन काउंटर की जांच करें? या किसी अन्य तरीके?

धन्यवाद

+0

क्या सेवा में व्यवस्थापकीय विशेषाधिकार हैं या सामान्य उपयोगकर्ता खाते के रूप में चलेंगे? (भौतिक डिस्क के लिए प्रदर्शन काउंटरों को व्यवस्थापक विशेषाधिकार की आवश्यकता होती है)। उत्तर के आधार पर, एक और तरीका हो सकता है। –

+0

हां, इसमें व्यवस्थापकीय विशेषाधिकार होंगे। – Anatoly

उत्तर

19

System.Diagnostics.PerformanceCounter कक्षा का उपयोग करके, आप जिस सूचकांक को अनुक्रमणित कर रहे हैं उससे संबंधित फिजिकडिस्क काउंटर से संलग्न करें।

नीचे कुछ कोड है जो चित्रित करने के लिए है, हालांकि वर्तमान में इसे "सी:" ड्राइव में कोड किया गया है। आप अपनी प्रक्रिया को स्कैन करने वाले किसी भी ड्राइव को "सी:" बदलना चाहेंगे। (यह प्रदर्शन काउंटरों के अस्तित्व को स्पष्ट करने के लिए केवल एक मोटा नमूना कोड है - इसे सटीक जानकारी प्रदान करने के रूप में न लें - हमेशा एक गाइड के रूप में उपयोग किया जाना चाहिए। अपने स्वयं के उद्देश्य के लिए बदलें)

% निष्क्रिय समय का निरीक्षण करें काउंटर जो इंगित करता है कि ड्राइव कितनी बार कर रही है। 0% निष्क्रिय का मतलब है कि डिस्क व्यस्त है, लेकिन इसका मतलब यह नहीं है कि यह फ्लैट-आउट है और अधिक डेटा स्थानांतरित नहीं कर सकता है।

साथ वर्तमान डिस्क पंक्ति लंबाई कम्बाइन % निष्क्रिय समय और इस आपको पता चलेगा कि ड्राइव इतना व्यस्त है कि यह डेटा के लिए सभी अनुरोधों को सेवा नहीं कर सकते हो रही है। एक सामान्य दिशानिर्देश के रूप में, 0 से अधिक कुछ का मतलब है कि ड्राइव शायद व्यस्त है और 2 से अधिक का मतलब है कि ड्राइव पूरी तरह से संतृप्त है। ये नियम एसएसडी और एचडीडी दोनों पर काफी अच्छी तरह से लागू होते हैं।

इसके अलावा, आपके द्वारा पढ़े गए किसी भी मूल्य को समय पर एक तात्कालिक मूल्य है। आपको कुछ परिणामों पर चलने वाला औसत करना चाहिए, उदा। निर्णय लेने के लिए परिणाम से जानकारी का उपयोग करने से पहले हर 100 एमएमएस और औसत 5 रीडिंग्स को पढ़ने से पहले (यानी, आपके अगले आईओ अनुरोध करने से पहले काउंटर व्यवस्थित होने तक प्रतीक्षा करें)।

internal DiskUsageMonitor(string driveName) 
{ 

    // Get a list of the counters and look for "C:" 

    var perfCategory = new PerformanceCounterCategory("PhysicalDisk"); 
    string[] instanceNames = perfCategory.GetInstanceNames(); 

    foreach (string name in instanceNames) 
    { 
     if (name.IndexOf("C:") > 0) 
     { 
      if (string.IsNullOrEmpty(driveName)) 
       driveName = name; 
     } 
    } 


    _readBytesCounter = new PerformanceCounter("PhysicalDisk", 
               "Disk Read Bytes/sec", 
               driveName); 

    _writeBytesCounter = new PerformanceCounter("PhysicalDisk", 
               "Disk Write Bytes/sec", 
               driveName); 

    _diskQueueCounter = new PerformanceCounter("PhysicalDisk", 
               "Current Disk Queue Length", 
               driveName); 

    _idleCounter = new PerformanceCounter("PhysicalDisk", 
              "% Idle Time", 
              driveName); 
    InitTimer(); 
} 

internal event DiskUsageResultHander DiskUsageResult; 

private void InitTimer() 
{ 
    StopTimer(); 
    _perfTimer = new Timer(_updateResolutionMillisecs); 
    _perfTimer.Elapsed += PerfTimerElapsed; 
    _perfTimer.Start(); 
} 

private void PerfTimerElapsed(object sender, ElapsedEventArgs e) 
{ 
    float diskReads = _readBytesCounter.NextValue(); 
    float diskWrites = _writeBytesCounter.NextValue(); 
    float diskQueue = _diskQueueCounter.NextValue(); 
    float idlePercent = _idleCounter.NextValue(); 

    if (idlePercent > 100) 
    { 
     idlePercent = 100; 
    } 

    if (DiskUsageResult != null) 
    { 
     var stats = new DiskUsageStats 
         { 
           DriveName = _readBytesCounter.InstanceName, 
           DiskQueueLength = (int)diskQueue, 
           ReadBytesPerSec = (int)diskReads, 
           WriteBytesPerSec = (int)diskWrites, 
           DiskUsagePercent = 100 - (int)idlePercent 
         }; 
     DiskUsageResult(stats); 
    } 
} 
+0

महान उत्तर! मेरा मतलब एक ही काउंटर था लेकिन सिस्टम से संबंधित वर्गों को याद किया। डायग्नोस्टिक्स नामस्थान। बहुत उपयोगी उदाहरण। अब मैं समाधान को बेहतर देखता हूं। यह दृष्टिकोण मेरी उम्मीदों को पूरा करता है। बहुत धन्यवाद!!! – Anatoly

0

जांचें कि स्क्रीनसेवर चल रहा है या नहीं? अच्छा संकेत है कि उपयोगकर्ता कीबोर्ड से

+0

ऐप को विन सेवा – Anatoly

+0

के रूप में तैनात किया जाएगा, साथ ही, एकाधिक उपयोगकर्ताओं को एक ही समय में लॉग इन किया जा सकता है। और मेरे लिए मैं आमतौर पर स्क्रीनसेवर को बंद कर देता हूं;) तो सुनिश्चित नहीं है कि यह एक अच्छा विचार है। – Anatoly

+0

बीटीडब्ल्यू, कोई अन्य सेवाएं डिस्क का उपयोग कर सकती है यहां तक ​​कि कोई भी लॉग इन नहीं है। मैं उनके प्रदर्शन को प्रभावित नहीं कर सकता। – Anatoly

1

संबंधित प्रश्नों के लिए this question और this also देखें। मैं एक साधारण समाधान के लिए सुझाव दूंगा कि वर्तमान डिस्क & सीपीयू उपयोग% के लिए अक्सर पूछताछ की जा रही है, और केवल वर्तमान कार्य के साथ जारी रहें जब वे परिभाषित सीमा के अंतर्गत हों। बस सुनिश्चित करें कि आपका काम आसानी से कार्यों में टूटा हुआ है, और यह कि प्रत्येक कार्य आसानी से & कुशलतापूर्वक प्रारंभ/बंद हो सकता है।

+0

दूसरे लिंक के लिए धन्यवाद। मेरे पास काउंटर हैं लेकिन प्रबंधित रैपर मिस्ड हैं। – Anatoly

1

एक लंबे समय पहले माइक्रोसॉफ्ट रिसर्च ने इस पर एक पेपर प्रकाशित किया था (क्षमा करें मुझे यूआरएल याद नहीं है)।
से मैं क्या याद:

  • कार्यक्रम शुरू कर दिया बहुत कुछ "काम आइटम" कर रही।
  • उन्होंने माप लिया कि यह उनके प्रत्येक "कार्य आइटम" के लिए कितना समय लगा।
  • थोड़ी देर के लिए दौड़ने के बाद, वे काम कर सकते थे कि "काम आइटम" कितनी तेजी से सिस्टम पर लोड नहीं था।
  • तब से, अगर "काम आइटम" तेज थे (जैसे कोई अन्य प्रोग्रामर अनुरोध करने की), वे और अधिक अनुरोध किए थे, अन्यथा वे समर्थित बंद

बुनियादी आदर्श है:

"अगर वे मुझे धीमा कर रहे हैं, तो मैं उन्हें धीमा किया जाना चाहिए नीचे है, इसलिए यदि मैं धीमा किया जा रहा है कम काम करते हैं" विचार करने के लिए

3

कुछ: क्या हुआ अगर वहाँ अन्य प्रक्रिया कर रहे हैं एसईएस जो एक ही (या एक समान) रणनीति का पालन करते हैं? "निष्क्रिय समय" के दौरान कौन सा भाग जाएगा? क्या अन्य प्रक्रियाओं को निष्क्रिय समय का उपयोग करने का मौका मिलेगा?

स्पष्ट रूप से यह सही तरीके से नहीं किया जा सकता है जब तक कि निष्क्रिय समय के दौरान संसाधनों को काफी विभाजित करने के लिए कुछ प्रसिद्ध ओएस तंत्र न हो। विंडोज़ में, यह SetPriorityClass पर कॉल करके किया जाता है।

यह document about I/O prioritization in Vista कि IDLE_PRIORITY_CLASS वास्तव में मैं/हे अनुरोधों की प्राथमिकता कम नहीं होगा (हालांकि यह प्रक्रिया के लिए समय निर्धारण प्राथमिकता कम हो जाएगा) मतलब लगता है। Vista ने इसके लिए PROCESS_MODE_BACKGROUND_BEGIN और PROCESS_MODE_BACKGROUND_END मान जोड़े।

सी # में, आप आमतौर पर Process.PriorityClass संपत्ति के साथ प्रक्रिया प्राथमिकता निर्धारित कर सकते हैं। Vista के लिए नए मान उपलब्ध नहीं हैं, इसलिए आपको सीधे Windows API फ़ंक्शन को कॉल करना होगा। आप ऐसा कर सकते हैं:

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
public static extern bool SetPriorityClass(IntPtr handle, uint priorityClass); 

const uint PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000; 

static void SetBackgroundMode() 
{ 
    if (!SetPriorityClass(new IntPtr(-1), PROCESS_MODE_BACKGROUND_BEGIN)) 
    { 
     // handle error... 
    } 
} 

मैंने ऊपर दिए गए कोड का परीक्षण नहीं किया। यह न भूलें कि यह केवल Vista या बेहतर पर काम कर सकता है। आपको पहले ऑपरेटिंग सिस्टम की जांच करने और फॉल-बैक रणनीति लागू करने के लिए Environment.OSVersion का उपयोग करना होगा।

+2

'SetPriorityClass' एक हैंडल की अपेक्षा करता है, 'Process.GetCurrentProcess()। आईडी' एक प्रक्रिया आईडी है, इसलिए यह काम नहीं करेगा। सौभाग्य से आप 'नई इंटिप्रेट (-1)' को 'सेटप्रिओरिटी क्लास' तक आसानी से पास कर सकते हैं, क्योंकि यह वर्तमान प्रक्रिया के लिए एक छद्ममंडल है। इन परिवर्तनों के साथ यह काम करता है। यह भी देखने के लिए कि क्या यह वास्तव में काम करता है, आपको 'SetPriorityClass' के वापसी मूल्य की जांच करनी चाहिए। – CodesInChaos

संबंधित मुद्दे