কোনও প্রতিনিধি বা ল্যাম্বদার সাথে স্টপ ওয়াচের সময় মোড়ানো?


96

আমি এইভাবে কোড লিখছি, কিছুটা দ্রুত এবং নোংরা টাইমিং করছি:

var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
    b = DoStuff(s);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

নিশ্চয় একটি উপায় আছে একটি অভিনব-schmancy .NET 3.0 ল্যামডা বদলে (নাউযুবিল্লাহ) হিসেবে সময়জ্ঞান কোডের এই বিট ডাকতে কাটা এবং এটি একটি কয়েক বার আটকে এবং প্রতিস্থাপন এর DoStuff(s)সঙ্গে DoSomethingElse(s)?

আমি জানি এটি একটি হিসাবে করা যেতে পারে Delegateতবে আমি ল্যাম্বদা উপায় নিয়ে ভাবছি।

উত্তর:


129

স্টপওয়াচ ক্লাস বাড়ানোর বিষয়ে কীভাবে?

public static class StopwatchExtensions
{
    public static long Time(this Stopwatch sw, Action action, int iterations)
    {
        sw.Reset();
        sw.Start(); 
        for (int i = 0; i < iterations; i++)
        {
            action();
        }
        sw.Stop();

        return sw.ElapsedMilliseconds;
    }
}

তারপরে এটিকে কল করুন:

var s = new Stopwatch();
Console.WriteLine(s.Time(() => DoStuff(), 1000));

আপনি আরও একটি ওভারলোড যুক্ত করতে পারেন যা "পুনরাবৃত্তি" পরামিতি বাদ দেয় এবং এই সংস্করণটিকে কিছু ডিফল্ট মান (1000 এর মতো) দিয়ে কল করে।


4
একই স্টপওয়াচের উদাহরণটি পুনরায় ব্যবহার করে s.Time () এর প্রতিটি টানা কলের জন্য অবিচ্ছিন্নভাবে সময় বাড়ানো রোধ করতে আপনি sw.Start () কে sw.StartNew () এর সাথে প্রতিস্থাপন করতে পারেন।
ভিভিএস

11
@ জায়ে আমি সম্মত হলাম যে গণনার সাথে "ফরচ" হ'ল রেঞ্জ কিছুটা "আধুনিক" দেখায়, তবে আমার পরীক্ষাগুলি দেখায় যে এটি একটি বৃহত গণনার চেয়ে "ফর" লুপের চেয়ে প্রায় চারগুণ ধীর। ওয়াইএমএমভি
ম্যাট হ্যামিল্টন

4
-১: এখানে একটি শ্রেণিবদ্ধ এক্সটেনশন ব্যবহার করার কোনও মানে নেই। Timeস্থিতিশীল পদ্ধতি হিসাবে আচরণ করে, বিদ্যমান বিদ্যমান সমস্ত স্থিতি ত্যাগ করে sw, সুতরাং এটি একটি উদাহরণ পদ্ধতি হিসাবে পরিচয় করিয়ে দেওয়া কেবল চটকদার দেখায়।
iljarn

4
@ জিলজাম আমি আপনার প্রশংসা করি যে আপনি আপনার উঁচু অংশটি ব্যাখ্যা করার জন্য একটি মন্তব্য রেখেছিলেন, তবে আমি মনে করি আপনি এক্সটেনশন পদ্ধতির পিছনে ধারণাকে ভুল বুঝছেন।
ম্যাট হ্যামিল্টন

4
@ ম্যাট হ্যামিল্টন: আমার মনে হয় না - তারা বিদ্যমান ক্লাসগুলিতে (যুক্তিযুক্ত) উদাহরণ পদ্ধতি যুক্ত করার জন্য। তবে, এটি আর কোনও উদাহরণ পদ্ধতি নয় Stopwatch.StartNewযা কোনও কারণে স্থির। সি # এর বিদ্যমান ক্লাসগুলিতে স্থির পদ্ধতি যুক্ত করার দক্ষতার অভাব রয়েছে (এফ # এর বিপরীতে), তাই আমি এটি করার অনুভূতিটি বুঝতে পারি, তবে এটি এখনও আমার মুখে খারাপ স্বাদ ফেলেছে।
iljarn

33

আমি যা ব্যবহার করছি তা এখানে:

public class DisposableStopwatch: IDisposable {
    private readonly Stopwatch sw;
    private readonly Action<TimeSpan> f;

    public DisposableStopwatch(Action<TimeSpan> f) {
        this.f = f;
        sw = Stopwatch.StartNew();
    }

    public void Dispose() {
        sw.Stop();
        f(sw.Elapsed);
    }
}

ব্যবহার:

using (new DisposableStopwatch(t => Console.WriteLine("{0} elapsed", t))) {
  // do stuff that I want to measure
}

এটি আমার দেখা সেরা সমাধান! কোনও এক্সটেনশন নেই (যাতে এটি বহু শ্রেণিতে ব্যবহৃত হতে পারে) এবং খুব পরিষ্কার!
ক্যালভিন

আমি নিশ্চিত না যে আমি ব্যবহারের উদাহরণটি সঠিকভাবে পেয়েছি কিনা। যখন আমি কিছু ব্যবহারের চেষ্টা Console.WriteLine("")অধীনে পরীক্ষার জন্য // do stuff that I want to measure, তবে কম্পাইলার এ সব খুশি না। আপনার কি সেখানে সাধারণ মত প্রকাশ এবং বক্তব্য দেওয়ার কথা রয়েছে?
টিম

@ টিম - আমি নিশ্চিত যে আপনি এটি কার্যকর করেছেন, তবে ব্যবহারের বিবৃতিটির অনুপস্থিত বন্ধনী ছিল
অ্যালেক্স

12

আপনি যে শ্রেণিটি ব্যবহার করছেন (বা কোনও বেস ক্লাস) তার জন্য আপনি একটি এক্সটেনশন পদ্ধতি লেখার চেষ্টা করতে পারেন।

আমার কলটি দেখতে এমন হবে:

Stopwatch sw = MyObject.TimedFor(1000, () => DoStuff(s));

তারপরে এক্সটেনশন পদ্ধতি:

public static Stopwatch TimedFor(this DependencyObject source, Int32 loops, Action action)
{
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < loops; ++i)
{
    action.Invoke();
}
sw.Stop();

return sw;
}

ডিপেন্ডেন্সিঅবজেক্ট থেকে প্রাপ্ত যে কোনও বস্তু এখন টাইমডফোর্ড (..) কল করতে পারে। ফাংশনটি সহজেই রেফ প্যারামের মাধ্যমে রিটার্ন মান সরবরাহ করতে সামঞ্জস্য করা যায়।

-

আপনি যদি না চান যে কার্যকারিতাটি কোনও শ্রেণি / অবজেক্টের সাথে আবদ্ধ থাকে আপনি যেমন কিছু করতে পারেন:

public class Timing
{
  public static Stopwatch TimedFor(Action action, Int32 loops)
  {
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < loops; ++i)
    {
      action.Invoke();
    }
    sw.Stop();

    return sw;
  }
}

তাহলে আপনি এটি ব্যবহার করতে পারেন:

Stopwatch sw = Timing.TimedFor(() => DoStuff(s), 1000);

এটি ব্যর্থ হয়ে, এই উত্তরটির মনে হচ্ছে এটির কিছু শালীন "জেনেরিক" ক্ষমতা রয়েছে:

কোনও প্রতিনিধি বা ল্যাম্বদার সাথে স্টপ ওয়াচের সময় মোড়ানো?


শীতল, তবে আমি কোনও নির্দিষ্ট শ্রেণি বা বেস শ্রেণীর সাথে এটি যেভাবে বাঁধা আছে তার জন্য যত্ন নিই না; এটি আরও উদারভাবে করা যেতে পারে?
জেফ আতউড

মায়োবজেক্ট ক্লাসের মতো এক্সটেনশন পদ্ধতির জন্য লেখা আছে? উত্তরাধিকার গাছের মধ্যে অবজেক্ট শ্রেণি বা অন্যান্য শ্রেণি প্রসারিত করার জন্য এটি সহজেই পরিবর্তন করা যেতে পারে।
মার্ক ইনগ্রাম

আমি আরও স্থির ভাবছিলাম, যেমন কোনও নির্দিষ্ট বস্তু বা শ্রেণীর সাথে আবদ্ধ নয় .. সময় এবং সময়টি সার্বজনীন এক ধরণের
জেফ আতউড

দুর্দান্ত, ২ য় সংস্করণটি আমি যা ভাবছিলাম তা আরও +1, তবে আমি ম্যাটকে প্রথমে পেয়ে যাওয়ায় তা গ্রহণ করেছি।
জেফ অ্যাটউড

7

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);
}

কোডটিতে পুনরাবৃত্তিগুলি অন্তর্ভুক্ত করার ধারণাটি আমি পছন্দ করি না StopWatch। আপনি সর্বদা অন্য পদ্ধতি বা এক্সটেনশন তৈরি করতে পারেন যা সম্পাদনকারী Nপুনরাবৃত্তিগুলি পরিচালনা করে ।

public partial class With
{
    public static void Iterations(int n, Action action)
    {
        for(int count = 0; count < n; count++)
            action();
    }
}

নমুনা কলিং কোড

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

এখানে এক্সটেনশন পদ্ধতির সংস্করণ রয়েছে

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

    public static Action Iterations(this Action action, int n)
    {
        return () => With.Iterations(n, action);
    }
}

এবং নমুনা কলিং কোড

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

আমি স্থিতিশীল পদ্ধতি এবং সম্প্রসারণের পদ্ধতিগুলি (পুনরাবৃত্তি এবং বেঞ্চমার্কের সংমিশ্রণ) এবং প্রত্যাশিত এক্সিকিউশন সময় এবং রিয়েল এক্সিকিউশন সময় এর ডেল্টা পরীক্ষা করেছি <= 1 এমএস।


এক্সটেনশন পদ্ধতির সংস্করণগুলি আমার মুখকে জল দেয়। :)
bzlm

7

আমি কিছু সময় আগে একটি সহজ কোডপ্রফিলার ক্লাস লিখেছিলাম যা কোনও অ্যাকশন ব্যবহার করে কোনও পদ্ধতি সহজেই প্রোফাইল করতে স্টপওয়াচকে জড়িয়ে দেয়: http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way

এটি আপনাকে মাল্টিথ্রেডড কোডটি সহজেই প্রোফাইল দেওয়ার অনুমতি দেবে। নিম্নলিখিত উদাহরণটি 1-16 থ্রেড সহ অ্যাকশন ল্যাম্বডাকে প্রোফাইল দেবে:

static void Main(string[] args)
{
    Action action = () =>
    {
        for (int i = 0; i < 10000000; i++)
            Math.Sqrt(i);
    };

    for(int i=1; i<=16; i++)
        Console.WriteLine(i + " thread(s):\t" + 
            CodeProfiler.ProfileAction(action, 100, i));

    Console.Read();
}

4

ধরে নিচ্ছি আপনার কেবলমাত্র একটি জিনিসের দ্রুত সময় প্রয়োজন এটি ব্যবহার করা সহজ।

  public static class Test {
    public static void Invoke() {
        using( SingleTimer.Start )
            Thread.Sleep( 200 );
        Console.WriteLine( SingleTimer.Elapsed );

        using( SingleTimer.Start ) {
            Thread.Sleep( 300 );
        }
        Console.WriteLine( SingleTimer.Elapsed );
    }
}

public class SingleTimer :IDisposable {
    private Stopwatch stopwatch = new Stopwatch();

    public static readonly SingleTimer timer = new SingleTimer();
    public static SingleTimer Start {
        get {
            timer.stopwatch.Reset();
            timer.stopwatch.Start();
            return timer;
        }
    }

    public void Stop() {
        stopwatch.Stop();
    }
    public void Dispose() {
        stopwatch.Stop();
    }

    public static TimeSpan Elapsed {
        get { return timer.stopwatch.Elapsed; }
    }
}

2

আপনি ল্যাম্বডায় যেতে চান এমন প্যারামিটারগুলির বিভিন্ন কেস কভার করতে আপনি বেশ কয়েকটি পদ্ধতি ওভারলোড করতে পারেন:

public static Stopwatch MeasureTime<T>(int iterations, Action<T> action, T param)
{
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < iterations; i++)
    {
        action.Invoke(param);
    }
    sw.Stop();

    return sw;
}

public static Stopwatch MeasureTime<T, K>(int iterations, Action<T, K> action, T param1, K param2)
{
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < iterations; i++)
    {
        action.Invoke(param1, param2);
    }
    sw.Stop();

    return sw;
}

বিকল্পভাবে, ফানক প্রতিনিধিদের যদি তাদের কোনও মান ফেরত দিতে হয় তবে তা ব্যবহার করতে পারেন। আপনি যদি প্রতিটি পুনরাবৃত্তির একটি অনন্য মান ব্যবহার করতে চান তবে আপনি প্যারামিটারগুলির একটি অ্যারে (বা আরও) তেও যেতে পারেন।


2

আমার জন্য এক্সটেনশানটি ইনটকে কিছুটা স্বজ্ঞাত বোধ করে, আপনার আর কোনও স্টপওয়াচ ইনস্ট্যান্ট করার বা এটিকে পুনরায় সেট করার বিষয়ে চিন্তা করার দরকার নেই।

সুতরাং তোমার আছে:

static class BenchmarkExtension {

    public static void Times(this int times, string description, Action action) {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < times; i++) {
            action();
        }
        watch.Stop();
        Console.WriteLine("{0} ... Total time: {1}ms ({2} iterations)", 
            description,  
            watch.ElapsedMilliseconds,
            times);
    }
}

এর নমুনা ব্যবহারের সাথে:

var randomStrings = Enumerable.Range(0, 10000)
    .Select(_ => Guid.NewGuid().ToString())
    .ToArray();

50.Times("Add 10,000 random strings to a Dictionary", 
    () => {
        var dict = new Dictionary<string, object>();
        foreach (var str in randomStrings) {
            dict.Add(str, null);
        }
    });

50.Times("Add 10,000 random strings to a SortedList",
    () => {
        var list = new SortedList<string, object>();
        foreach (var str in randomStrings) {
            list.Add(str, null);
        }
    });

নমুনা আউটপুট:

Add 10,000 random strings to a Dictionary ... Total time: 144ms (50 iterations)
Add 10,000 random strings to a SortedList ... Total time: 4088ms (50 iterations)

1

আমি ভ্যানস মরিসন (। নেট থেকে পারফরম্যান্সের অন্যতম একটি) থেকে কোডটাইমারের ক্লাসগুলি ব্যবহার করতে চাই।

তিনি দ্রুত এবং ইজিলি: কোডটাইমস পরিচালিত কোড পরিমাপ করা শিরোনাম শিরোনামে তার ব্লগে একটি পোস্ট করেছিলেন " ।

এটিতে একটি মাল্টিসম্পলকোডটাইমারের মতো দুর্দান্ত জিনিস রয়েছে। এটি গড় এবং স্ট্যান্ডার্ড বিচ্যুতিটির স্বয়ংক্রিয় গণনা করে এবং এটি আপনার ফলাফলগুলি মুদ্রণ করাও খুব সহজ।


0
public static class StopWatchExtensions
{
    public static async Task<TimeSpan> LogElapsedMillisecondsAsync(
        this Stopwatch stopwatch,
        ILogger logger,
        string actionName,
        Func<Task> action)
    {
        stopwatch.Reset();
        stopwatch.Start();

        await action();

        stopwatch.Stop();

        logger.LogDebug(string.Format(actionName + " completed in {0}.", stopwatch.Elapsed.ToString("hh\\:mm\\:ss")));

        return stopwatch.Elapsed;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.