سؤال

أرغب في قياس تنفيذ جزء من التعليمات البرمجية وأتساءل ما هي أفضل طريقة للقيام بذلك؟

الخيار 1:

DateTime StartTime = DateTime.Now;

//Code

TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");

الخيار 2: استخدام System.Diagnostics ؛

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

    //Code

    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

    // Format and display the TimeSpan value.
    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
    Console.WriteLine(elapsedTime, "RunTime");

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

ما هو الخيار الأفضل لرمز الإنتاج ، أم أن أي شخص آخر يستخدم شيئًا مختلفًا وربما أفضل؟

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

المحلول

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

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

على وجه التحديد ، و Frequency الحقل و GetTimestamp يمكن استخدام الطريقة بدلاً من واجهات برمجة تطبيقات Win32 غير المدارة QueryPerformanceFrequency و QueryPerformanceCounter.

هناك خلفية مفصلة عن تلك واجهات برمجة التطبيقات Win32 [هنا] وفي مستندات MSDN المرتبطة 2.

توقيت عالي الدقة

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

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

ال QueryPerformanceCounter تسترجع الدالة القيمة الحالية لعداد الأداء عالي الدقة. من خلال استدعاء هذه الوظيفة في بداية ونهاية قسم من الكود ، يستخدم التطبيق العداد بشكل أساسي كموقت عالي الدقة. على سبيل المثال ، افترض ذلك QueryPerformanceFrequency يشير إلى أن تواتر عداد الأداء عالي الدقة هو 50000 تهم في الثانية. إذا استدعاء التطبيق QueryPerformanceCounter مباشرة قبل وبعد أن يتم توقيت قسم الكود مباشرة ، قد تكون قيم العداد 1500 تهم و 3500 تهم ، على التوالي. تشير هذه القيم إلى أن .04 ثانية (2000 حساب) انقضت أثناء تنفيذ الكود.

نصائح أخرى

ليس ذلك فقط StopWatch هو أكثر دقة ، ولكن أيضا ذلك DateTime.Now سوف يعطي نتائج غير صحيحة في بعض الظروف.

ضع في اعتبارك ما يحدث خلال فترة التوفير في ضوء النهار ، على سبيل المثال-باستخدام DateTime.Now يمكن في الواقع إعطاء ملف نفي إجابه!

أنا أستخدم عمومًا StopWatch لهذا النوع من الموقف.

من MSDN صفحة:

ساعة التوقيف

يوفر مجموعة من الأساليب والخصائص التي يمكنك استخدامها لقياس الوقت المنقضي بدقة.

في المنشور التالي ، أستخدمه لمقارنة وقت تنفيذ LINQ مقابل Plinq:

LINQ (PLINQ) مع Visual Studio 2010

لن يؤذي الأداء ، لأنك تقول إنه ليس بهذا الحرج. تبدو ساعة التوقيت أكثر ملاءمة - فأنت تطرح وقتًا فقط من الوقت وليس تاريخًا من آخر. تستغرق Date Stuff المزيد من الذاكرة ووقت وحدة المعالجة المركزية للتعامل معها. هناك أيضًا طرق لجعل الكود منظفًا ، في حال كنت تخطط لإعادة استخدامه في عدة أماكن. التحميل الزائد using يتبادر إلى الذهن. سأبحث عن مثال. حسنًا ، تم سرق الرمز من:

http://stevesmithblog.com/blog/great-uses-of-using-statement-in-c//

public class ConsoleAutoStopWatch : IDisposable
{
    private readonly Stopwatch _stopWatch;

    public ConsoleAutoStopWatch()
    {
        _stopWatch = new Stopwatch();
        _stopWatch.Start();
    }

    public void Dispose()
    {
        _stopWatch.Stop();
        TimeSpan ts = _stopWatch.Elapsed;

        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                           ts.Hours, ts.Minutes, ts.Seconds,
                                           ts.Milliseconds / 10);
        Console.WriteLine(elapsedTime, "RunTime");
    }
}

private static void UsingStopWatchUsage()
{
    Console.WriteLine("ConsoleAutoStopWatch Used: ");
    using (new ConsoleAutoStopWatch())
    {
        Thread.Sleep(3000);
    }
}

من المحتمل أن يناسب كلاهما احتياجاتك بشكل جيد ، لكنني أقول استخدام StopWatch. لماذا ا؟ لأن الأمر مخصص للمهمة التي تقوم بها.

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

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

لدي فئة صغيرة للقيام بهذا النوع من الأشياء المخصصة. يستخدم فئة ساعة التوقيت - ج# اختبار perfomance.

على سبيل المثال.

var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));

استخدم الرمز أدناه

DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
      TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
                  lblExecutinTime.Text = "total time taken " +   Math.Round(span.TotalMinutes,2) + " minutes .   >>---> " + DateTime.Now.ToShortTimeString();

أخذت إجابة هاميش تبسيطها وجعلتها أكثر عمومية في حال احتجت إلى تسجيل إلى مكان آخر:

public class AutoStopWatch : Stopwatch, IDisposable {

    public AutoStopWatch() {
        Start();
    }

    public virtual void Dispose() {
        Stop();
    }
}

 public class AutoStopWatchConsole : AutoStopWatch {

    private readonly string prefix;

    public AutoStopWatchConsole(string prefix = "") {
        this.prefix = prefix;
    }

    public override void Dispose() {
        base.Dispose();

        string format = Elapsed.Days > 0 ? "{0} days " : "";
        format += "{1:00}:{2:00}:{3:00}.{4:00}";

        Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
    }
}

private static void Usage() {

    Console.WriteLine("AutoStopWatch Used: ");
    using (var sw = new AutoStopWatch()) {
        Thread.Sleep(3000);

        Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
    }

    Console.WriteLine("AutoStopWatchConsole Used: ");
    using (var sw = new AutoStopWatchConsole()) {
        Thread.Sleep(3000);
    }

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