क्या DateTime.Now किसी फ़ंक्शन के प्रदर्शन को मापने का सबसे अच्छा तरीका है?


474

मुझे एक अड़चन खोजने की जरूरत है और समय को यथासंभव सटीक रूप से मापने की जरूरत है।

प्रदर्शन को मापने के लिए निम्नलिखित कोड स्निपेट सबसे अच्छा तरीका है?

DateTime startTime = DateTime.Now;

// Some execution process

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);

वैसे, अगर आप कुछ जल्दी नहीं खोज रहे हैं और गंदे प्रदर्शन काउंटर का उपयोग किया जा सकता है।
जोनाथन सी डिकिंसन

1
यदि आपको स्टॉपवॉच के अधिक से अधिक सटीक उपयोग की आवश्यकता है। गेटटेस्टैम्प, अन्यथा उत्तर अच्छा है।
dbasnett

@dbasnett क्या आप एक उत्तर में अधिक विस्तार में जा सकते हैं?
डेविड बसाराब

उपर्युक्त उदाहरण में परिवर्तन शुरू और अंत में लंबे समय तक और स्टॉपवॉच को निर्दिष्ट करने के लिए। उन्हें DateTime.Now के बजाय उन्हें सेट करें। लिया गया समय (अंत-प्रारंभ) /Stopwatch.Frequency है।
dbasnett

जवाबों:


649

नहीं यह नहीं। स्टॉपवॉच (में System.Diagnostics) का प्रयोग करें

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

स्टॉपवॉच स्वचालित रूप से उच्च परिशुद्धता टाइमर के अस्तित्व के लिए जाँच करता है।

यह ध्यान देने योग्य है कि DateTime.Nowअक्सर DateTime.UtcNowकाम की वजह से काफी थोड़ा धीमा होता है जो टाइमज़ोन, डीएसटी और इस तरह से किया जाना है ।

DateTime.UtcNow में आमतौर पर 15 एमएस का रिज़ॉल्यूशन होता है। एक महान सारांश के लिए परिशुद्धता के बारे में जॉन चैपमैन का ब्लॉग पोस्ट देखें DateTime.Now

दिलचस्प सामान्य ज्ञान: स्टॉपवॉच वापस गिर जाता है DateTime.UtcNowअगर आपका हार्डवेयर उच्च आवृत्ति काउंटर का समर्थन नहीं करता है। आप यह देखने के लिए देख सकते हैं कि स्टॉपवॉच स्थिर क्षेत्र स्टॉपवॉच .sHighResolution को देखकर उच्च परिशुद्धता प्राप्त करने के लिए हार्डवेयर का उपयोग करता है या नहीं ।


3
मैं एक PerformWork () रखूँगा; "हीटिंग अप" के लिए स्टॉपवॉच से पहले।
दीवान

2
यह भी सिफारिश जोड़ना चाहिए कि यदि आपकी PerformWork()अवधि बहुत कम है, तो आप इसे बार-बार कॉल करने में सक्षम हो सकते हैं और कॉल के बैच की औसत गणना कर सकते हैं। इसके अलावा, Stopwatchएक स्ट्रोब-प्रभाव से बचने के लिए आपके शुरू करने / रोकने के बजाय कॉल का एक पूरा बैच समय जो आपके समय के माप को खराब करेगा।
devgeezer

1
स्टॉपवॉच मल्टीकोर पर थ्रेडसेफ़ नहीं है। देखें stackoverflow.com/questions/6664538/... और stackoverflow.com/questions/1149485/...
पावेल Savara

1
sw.ElapsedMilliseconds; यह भी कर सकते हैं
Flappy

2
@Pavel, स्पष्ट होने के लिए, स्टॉपवॉच की सिफारिश माइक्रोसॉफ्ट द्वारा आधुनिक मल्टीकोर प्रोसेसर पर सबसे अच्छा समाधान (कम ओवरहेड और उच्च परिशुद्धता) के रूप में की जाती है जो विंडोज 7 और विंडोज 8 पर चल रही है। msdn.microsoft.com/en-us/library/
रॉन

91

यदि आप कुछ त्वरित और गंदा चाहते हैं, तो मैं सुझाव दूंगा कि आप अधिक सटीक डिग्री के लिए स्टॉपवॉच का उपयोग करें।

Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();

Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);

वैकल्पिक रूप से, अगर आपको कुछ अधिक परिष्कृत की आवश्यकता है, तो आपको शायद एक 3 पार्टी प्रोफाइलर जैसे एएनएसटीएस का उपयोग करने पर विचार करना चाहिए ।


56

यह लेख कहता है कि सबसे पहले आपको तीन विकल्पों की तुलना करने की आवश्यकता है Stopwatch, DateTime.Nowऔर DateTime.UtcNow

यह भी दिखाता है कि कुछ मामलों में (जब प्रदर्शन काउंटर मौजूद नहीं है) स्टॉपवॉच DateTime.UtcNow + कुछ अतिरिक्त प्रसंस्करण का उपयोग कर रहा है। इसके कारण यह स्पष्ट है कि उस स्थिति में DateTime.UtcNow सबसे अच्छा विकल्प है (क्योंकि अन्य इसका उपयोग करते हैं + कुछ प्रसंस्करण)

हालाँकि, जैसा कि यह पता चला है, काउंटर लगभग हमेशा मौजूद होता है - उच्च रिज़ॉल्यूशन प्रदर्शन काउंटर और इसके अस्तित्व से संबंधित .NET स्टॉपवॉच के बारे में स्पष्टीकरण देखें ?

यहाँ एक प्रदर्शन ग्राफ है। ध्यान दें कि UtcNow ने प्रदर्शन की तुलना में कम प्रदर्शन लागत कितनी है:

यहां छवि विवरण दर्ज करें

एक्स अक्ष नमूना डेटा आकार है, और वाई अक्ष उदाहरण के सापेक्ष समय है।

एक बात Stopwatchबेहतर है कि यह उच्च संकल्प समय माप प्रदान करता है। एक और इसकी अधिक OO प्रकृति है। हालाँकि, एक OO आवरण के चारों ओर बनाना UtcNowकठिन नहीं हो सकता है।


पहली कड़ी टूटी हुई प्रतीत होती है।
पीटर मोर्टेंसन

1
टूटी हुई हां .. टाइम मशीन दिखा सकती है मुझे लगता है। Btw क्यों आप "तीन" को संपादित करते हैं, मुझे यहाँ विश्वास करने की ज़रूरत नहीं है।
वैलेंटाइन कुजब

18

अपने बेंचमार्किंग कोड को उपयोगिता वर्ग / विधि में धकेलना उपयोगी है। StopWatchवर्ग होने की जरूरत नहीं है Disposedया Stoppedत्रुटि पर। तो, सबसे सरल कोड के लिए समय कुछ कार्रवाई है

public partial class With
{
    public static long Benchmark(Action action)
    {
        var stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }
}

नमूना कॉलिंग कोड

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}

यहाँ विस्तार विधि संस्करण है

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }
}

और सैंपल कॉलिंग कोड

public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Did action in {0} ms.”, time);
}

1
बेहतर ग्रैन्युलैरिटी के बारे में क्या? कई चीजें एक से कम एमएस में होती हैं।
हेनरिक

तब बीत चुकी संपत्ति लौटाएं, यह एक TimeSpan है। मैं सिर्फ आपको पैटर्न दिखा रहा हूं। इसे लागू करने में मज़ा आया।
एंथनी मास्टरीन

Elapsed.TotalMillisecondsउच्च परिशुद्धता के लिए लौटें । इस सवाल को भी देखें stackoverflow.com/questions/8894425/…
nawfal

16

स्टॉपवॉच कार्यक्षमता बेहतर (उच्च परिशुद्धता) होगा। मैं भी सिर्फ लोकप्रिय प्रोफाइलर में से एक को डाउनलोड करने की सलाह देते हैं, हालांकि ( DotTrace और चींटियों उनके जो मेरे सबसे का उपयोग किया है रहे हैं ... DotTrace के लिए नि: शुल्क परीक्षण पूरी तरह कार्यात्मक है और दूसरों से कुछ की तरह नाग नहीं करता है)।


13

System.Diagnostics.Stopwatch वर्ग का उपयोग करें।

Stopwatch sw = new Stopwatch();
sw.Start();

// Do some code.

sw.Stop();

// sw.ElapsedMilliseconds = the time your "do some code" took.

11

डिट्टो स्टॉपवॉच, यह बेहतर तरीका है।

प्रदर्शन को मापने के बारे में आपको यह भी जांचना चाहिए कि क्या आपकी "// कुछ निष्पादन प्रक्रिया" एक बहुत छोटी प्रक्रिया है।

यह भी ध्यान रखें कि आपके "// कुछ एक्ज़ेक्यूशन प्रोसेस" का पहला रन बाद के रन की तुलना में धीमा हो सकता है।

मैं आमतौर पर एक विधि को १००० बार या १०००००० बार एक लूप में चलाकर परीक्षण करता हूं और मुझे इसे एक बार चलाने की तुलना में अधिक सटीक डेटा मिलता है।


9

समय को मापने के लिए ये सभी शानदार तरीके हैं, लेकिन यह केवल एक अप्रत्यक्ष तरीका है टोंटी खोजने के लिए।

एक थ्रेड में एक टोंटी को खोजने का सबसे सीधा तरीका यह है कि इसे चालू किया जाए, और जब भी यह आपको इंतजार कर रहा है, तो इसे रोकें या तोड़ें। ऐसा कई बार करें। यदि आपकी अड़चन में X% समय लगता है, तो X% संभावना है कि आप इसे प्रत्येक स्नैपशॉट पर कार्य में पकड़ लेंगे।

यहां बताया गया है कि यह कैसे और क्यों काम करता है, इसका अधिक पूर्ण विवरण है


7

@ सीन चेम्बर्स

FYI करें, .NET टाइमर क्लास डायग्नॉस्टिक्स के लिए नहीं है, यह एक पूर्व निर्धारित अंतराल पर घटनाओं को उत्पन्न करता है, इस तरह ( डीएनडीएन से ):

System.Timers.Timer aTimer;
public static void Main()
{
    // Create a timer with a ten second interval.
    aTimer = new System.Timers.Timer(10000);

    // Hook up the Elapsed event for the timer.
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    // Set the Interval to 2 seconds (2000 milliseconds).
    aTimer.Interval = 2000;
    aTimer.Enabled = true;

    Console.WriteLine("Press the Enter key to exit the program.");
    Console.ReadLine();
}

// Specify what you want to happen when the Elapsed event is 
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}

तो यह वास्तव में आपको यह जानने में मदद नहीं करता है कि कुछ कितना समय लगा, बस एक निश्चित समय बीत चुका है।

टाइमर को System.Windows.Forms में एक नियंत्रण के रूप में भी उजागर किया गया है ... आप इसे VS05 / VS88 में अपने डिजाइनर टूल बॉक्स में पा सकते हैं


6

यह सही तरीका है:

using System;
using System.Diagnostics;

class Program
{
    public static void Main()
    {
        Stopwatch stopWatch = Stopwatch.StartNew();

            // some other code

        stopWatch.Stop();

        // this not correct to get full timer resolution
        Console.WriteLine("{0} ms", stopWatch.ElapsedMilliseconds);

        // Correct way to get accurate high precision timing
        Console.WriteLine("{0} ms", stopWatch.Elapsed.TotalMilliseconds);
    }
}

अधिक जानकारी के लिए सटीक प्रदर्शन काउंटर प्राप्त करने के लिए डेटाटाइम के बजाय उपयोग स्टॉपवॉच से गुजरें


6

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

Microsoft के पैटर्न्स और प्रैक्टिस समूह के पास विजुअल स्टूडियो टीम सिस्टम परफॉर्मेंस टेस्टिंग गाइडेंस में कुछ मार्गदर्शन है ।


5

मुझे वंस मॉरिसन के ब्लॉग में एक कोड कोडिमर क्लास के बारे में एक पोस्ट मिली, जिसमें उन्होंने लिखा कि StopWatchआसान का उपयोग करता है और साइड में कुछ साफ-सुथरा सामान करता है।


5

यह पर्याप्त पेशेवर नहीं है:

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

एक अधिक विश्वसनीय संस्करण है:

PerformWork();

int repeat = 1000;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < repeat; i++)
{
   PerformWork();
}

sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds / repeat);

मेरे वास्तविक कोड में, मैं GC.Collect कॉल को एक ज्ञात स्थिति में प्रबंधित हीप को बदलने के लिए कॉल करूंगा, और स्लीप कॉल को जोड़ूंगा ताकि कोड के विभिन्न अंतरालों को ETW प्रोफाइल में आसानी से अलग किया जा सके।


4

मैंने इस तरह की प्रदर्शन जाँच बहुत कम की है (मुझे लगता है कि "यह धीमा है, इसे और तेज़ बनाइए") तो मैं बहुत हमेशा इस के साथ चला गया।

प्रदर्शन की जाँच के लिए एक google बहुत सारे संसाधनों / लेखों को प्रकट करता है।

कई ने प्रदर्शन की जानकारी प्राप्त करने के लिए पिनवोक का उपयोग किया। बहुत सारी सामग्री जो मैं अध्ययन करता हूं, वे वास्तव में परफ्यूम का उपयोग करके उल्लेख करते हैं ..

संपादित करें:

स्टॉपवॉच की बातचीत को देखा .. अच्छा लगा! मैंने कुछ सीखा है :)

यह एक अच्छा लेख लगता है


4

जिस तरह से मैं अपने कार्यक्रमों के भीतर उपयोग करता हूं वह स्टॉपवॉच वर्ग का उपयोग कर रहा है जैसा कि यहां दिखाया गया है।

Stopwatch sw = new Stopwatch();
sw.Start();


// Critical lines of code

long elapsedMs = sw.Elapsed.TotalMilliseconds;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.