Hitung waktu eksekusi suatu metode

533

Kemungkinan Duplikat:
Bagaimana cara mengukur berapa lama suatu fungsi berjalan?

Saya memiliki metode pengambilan waktu I / O yang menyalin data dari satu lokasi ke lokasi lain. Apa cara terbaik dan paling nyata untuk menghitung waktu eksekusi? Thread? Timer? Stopwatch? Ada solusi lain? Saya ingin yang paling tepat, dan sesingkat mungkin.

Mahdi Tahsildari
sumber

Jawaban:

1131

Stopwatch dirancang untuk tujuan ini dan merupakan salah satu cara terbaik untuk mengukur waktu eksekusi di .NET.

var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

Jangan gunakan DateTime untuk mengukur eksekusi waktu di .NET.


MEMPERBARUI:

Seperti yang ditunjukkan oleh @ series0ne di bagian komentar: Jika Anda ingin pengukuran tepat nyata dari eksekusi beberapa kode, Anda harus menggunakan penghitung kinerja yang dibangun ke dalam sistem operasi. The jawaban berikut berisi gambaran yang baik.

Darin Dimitrov
sumber
2
Tepat, dan bagaimana dengan kasus ini: saya memiliki loop foreach yang memiliki bagian ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); dalam, tetapi stopwatch berhenti sebelum semuanya dilakukan.
Mahdi Tahsildari
13
@DarinDimitrov - Stopwatch tidak sepenuhnya akurat? ingat bahwa .NET background noise (seperti JITing) menyebabkan waktu eksekusi yang berbeda-beda terjadi. Oleh karena itu, secara realistis, untuk pengukuran yang akurat, OP harus menggunakan profiler kinerja.
Matthew Layton
3
@ series0ne, poin yang sangat bagus. Saya akan memperbarui jawaban saya untuk memasukkan komentar Anda yang berharga.
Darin Dimitrov
7
@DarinDimitrov, saya baru-baru ini melakukan wawancara dengan pengembang senior yang sangat terampil. Dia menunjukkan kepada saya bahwa menggunakan DateTimes sebenarnya lebih akurat daripada menggunakan StopWatch. Dia mengatakan alasan untuk ini adalah bahwa Stopwatch di .NET tidak memperhitungkan afinitas CPU, dan karena itu, jika utas Anda bergerak dari satu inti ke inti lainnya, StopWatch tidak memperhitungkan waktu eksekusi lintas inti lainnya; hanya di mana utas memulai eksekusi. Apa pendapat Anda tentang ini?
Matthew Layton
2
@ series0ne, apa yang dikatakan pengembang senior tentang Stopwatch dan DateTime benar-benar benar. Kecuali bahwa dengan DateTime Anda tidak memiliki keakuratan yang cukup. Masalahnya adalah bahwa tidak ada kelas seperti itu dalam. NET yang akan memungkinkan Anda semua fitur tersebut.
Darin Dimitrov
75

Dari pengalaman pribadi, System.Diagnostics.Stopwatchkelas dapat digunakan untuk mengukur waktu eksekusi suatu metode, namun, WASPADALAH : Itu tidak sepenuhnya akurat!

Perhatikan contoh berikut:

Stopwatch sw;

for(int index = 0; index < 10; index++)
{
    sw = Stopwatch.StartNew();
    DoSomething();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

sw.Stop();

Contoh hasil

132ms
4ms
3ms
3ms
2ms
3ms
34ms
2ms
1ms
1ms

Sekarang Anda bertanya-tanya; "Yah, mengapa perlu waktu 132ms pertama kali, dan secara signifikan lebih sedikit dari sisa waktu?"

Jawabannya adalah itu Stopwatch tidak mengkompensasi aktivitas "latar belakang suara" di .NET, seperti JITing. Oleh karena itu saat pertama kali Anda menjalankan metode Anda, .NET JIT yang pertama. Waktu yang diperlukan untuk melakukan ini ditambahkan ke waktu eksekusi. Sama halnya, faktor-faktor lain juga akan menyebabkan waktu eksekusi berbeda-beda.

Yang benar-benar harus Anda cari adalah keakuratan absolut adalah Performance Profileing !

Lihatlah yang berikut ini:

RedGate ANTS Performance Profiler adalah produk komersial, tetapi menghasilkan hasil yang sangat akurat. - Tingkatkan kinerja aplikasi Anda dengan .NET profiling

Berikut ini adalah artikel StackOverflow tentang pembuatan profil: - What Are Some Good .NET Profiler?

Saya juga telah menulis artikel tentang Kinerja Profil menggunakan Stopwatch yang mungkin ingin Anda lihat - Profil kinerja di .NET

Matthew Layton
sumber
2
@mahditahsildari Tidak masalah. Senang bisa membantu! :-)
Matthew Layton
41
Saya tidak yakin mengapa ini adalah contoh ketidaktepatan . Stopwatch secara akurat mengukur total biaya panggilan pertama, yang tentunya merupakan hal yang relevan bagi pelanggan yang akan menjalankan kode ini. Mereka tidak peduli apakah 132 milidetik itu dibebankan pada eksekusi metode atau jitter, mereka peduli dengan total waktu yang telah berlalu.
Eric Lippert
2
@ series0ne Jika Anda peduli dengan kinerja loop, maka ukur kinerja loop. Jangan hanya berasumsi bahwa melakukan sesuatu n kali berarti itu akan persis n kali lebih lambat dari mengeksekusi sekali
svick
3
Pertama, sampel kode harus menghasilkan output dengan angka yang terus meningkat karena StopWatch tidak pernah diatur ulang dalam loop. Dan dengan "harus" Maksud saya tidak (saya memeriksa). Jadi output Anda tidak cocok dengan kode. Kedua, ketika saya memperbaiki kode untuk melakukan Stop / Write / Reset / Mulai di loop, pengukuran pertama sama dengan yang lain. Dugaan saya adalah DoSomething Anda melakukan sesuatu lebih lama saat pertama kali dijalankan. JIT mungkin atau mungkin bukan alasan untuk itu, tetapi bukan karena Stopwatch mempengaruhi pengukuran. Maka -1.
ILIA BROUDNO
2
ILIA BROUDNO benar sekali, saya mendapat hasil yang sama. @ series0ne, Anda memiliki Console.WriteLine di dalam loop, menulis ms sejauh ini; karena Anda hanya menghentikan arloji SETELAH loop berakhir, itu meningkat seiring waktu dengan setiap iterasi, jadi kita akan melihat sesuatu seperti 3, 6, 10, 12, 15 ... karena waktu terakumulasi selama eksekusi.
Rui Miguel Pinheiro
29

StopWatch kelas mencari solusi terbaik Anda.

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

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

Juga memiliki bidang statis yang disebut Stopwatch.IsHighResolution. Tentu saja, ini adalah masalah perangkat keras dan sistem operasi.

Menunjukkan apakah timer didasarkan pada penghitung kinerja resolusi tinggi.

Soner Gönül
sumber
18

Jika Anda tertarik untuk memahami kinerja, jawaban terbaik adalah menggunakan profiler.

Jika tidak, System.Diagnostics.StopWatch menyediakan timer resolusi tinggi.

Jeff Foster
sumber
Tepat sekali! Saya sedikit kecewa karena begitu banyak orang di sini menyarankan untuk menggunakan Stopwatch, karena tidak sepenuhnya akurat. Namun seperti yang Anda sarankan menggunakan profiler Kinerja, ini adalah cara yang benar untuk melakukannya! +1
Matthew Layton
7

StopWatch akan menggunakan penghitung resolusi tinggi

Stopwatch mengukur waktu yang berlalu dengan menghitung kutu timer dalam mekanisme timer yang mendasarinya. Jika perangkat keras dan sistem operasi yang diinstal mendukung penghitung kinerja resolusi tinggi, maka kelas Stopwatch menggunakan penghitung itu untuk mengukur waktu yang berlalu. Jika tidak, kelas Stopwatch menggunakan timer sistem untuk mengukur waktu yang berlalu. Gunakan bidang Frekuensi dan IsHighResolution untuk menentukan ketepatan dan resolusi implementasi penghitungan waktu Stopwatch.

Jika Anda mengukur IO maka angka Anda kemungkinan akan dipengaruhi oleh peristiwa eksternal, dan saya akan sangat khawatir. ketepatan (seperti yang Anda tunjukkan di atas). Alih-alih, saya akan melakukan serangkaian pengukuran dan mempertimbangkan rata-rata dan distribusi angka-angka itu.

Brian Agnew
sumber
0
 using System.Diagnostics;
 class Program
 {
    static void Test1()
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine("Test1 " + i);
        }
    }
  static void Main(string[] args)
    {

        Stopwatch sw = new Stopwatch();
        sw.Start();
        Test1();
        sw.Stop();
        Console.WriteLine("Time Taken-->{0}",sw.ElapsedMilliseconds);
   }
 }
Md.Rakibuz Sultan
sumber