jump to navigation

Membuat Kelas StopWatch untuk Mengukur Waktu Eksekusi Kode Program 18 Juni 2008

Posted by firstyuyu in .net framework.
trackback

Sering kali kita ingin mengukur waktu eksekusi kode program yang kita jalankan. Terutama jika kita sedang membandingkan antara beberapa alternatif algoritma untuk mencari algoritma yang paling cepat. Kita bisa membuat sendiri pengukur waktu seperti ini dengan memanfaatkan High-Resolution Timer.

Win32 API menyediakan dua buah fungsi yang bisa kita gunakan untuk mengukur waktu, yaitu

  • QueryPerformanceCounter: fungsi ini akan mengembalikan nilai high-resolution performance counter saat ini, (high-resolution performance counter yaitu nilai yang akan selalu bertambah setiap rentang waktu yang sangat singkat – karena itulah disebut high-resolution).
  • QueryPerformanceFrequency: fungsi ini akan mengembalikan nilai jumlah counter per detik.

Dengan memanggil fungsi QueryPerformanceCounter tepat sebelum sebuah kode dieksekusi lalu memanggil kembali fungsi ini tepat setelah kode selesai dieksekusi, maka kita bisa menghitung selisih counter yang terjadi. Dengan membagi selisih counter ini dengan nilai frekuensi counter per detik, maka kita bisa mendapatkan waktu eksekusi sebuah kode program.

Misalnya, anggap saja fungsi QueryPerformanceFrequency menyatakan bahwa high-resolution performance counter bernilai 50.000 counter per detik. Kemudian, pemanggilan fungsi QueryPerformanceCounter tepat sebelum dan tepat sesudah suatu kode program mengembalikan nilai 1500 dan 3500. Maka kita bisa menghitung waktu yang dibutuhkan dengan rumus sbb: (3500 – 1500) / 50000 = 0,04 detik.

Catatan: Jika Anda ingin langsung melihat source code lengkap dari kelas StopWatch, silakan langsung melihat ke akhir artikel ini.

Sebagaimana dijelaskan di dalam Scenario-Driven Design, maka kita akan mulai dahulu dengan membuat skenario penggunaan kelas StopWatch ini. Misalnya, kita menginginkan skenario penggunaan kelas StopWatch ini sbb:

StopWatch sw = new StopWatch();

sw.Start();

 

RunTest();

 

sw.Stop();

Console.WriteLine(“Duration in seconds: {0}”, sw.DurationInSeconds);

Dari sini, kita akan mendesain public API yang akan mengakomodasi skenario di atas, sbb:

public class StopWatch

{

    public void Start();

    public void Stop();

    public double DurationInSeconds { get; }

}

Kemudian kita membuat implementasi dengan tidak mengubah public API yang telah kita spesifikasikan di atas. Karena QueryPerformanceCounter dan QueryPerformanceFrequency merupakan fungsi Win32 API, maka kita perlu membuat deklarasinya dahulu di dalam kelas StopWatch.

public class StopWatch

{

    [DllImport(“KERNEL32”)]

    private static extern bool QueryPerformanceCounter(

      out long lpPerformanceCount);

 

    [DllImport(“Kernel32.dll”)]

    private static extern bool QueryPerformanceFrequency(

        out long lpFrequency);

}

Kedua deklarasi di atas akan memberitahukan kepada compiler bahwa implementasi method QueryPerformanceCounter dan QueryPerformanceFrequency berada di tempat lain, yaitu di file kernel32.dll. Agar kita bisa mengunakan atribut DllImport, kita harus mengimpor namespace
System.Runtime.InteropServices. Kedua method di atas akan mengembalikan nilai counter serta frekuensi melalui parameter output yang diberikan padanya.

Kita juga akan mempunyai beberapa field yang bersifat private untuk menyimpan nilai counter awal dan akhir, frequency, serta durasi, sbb:

private long start;

private long stop;

private long frequency;

private double duration = 0;

Pada konstruktor kelas StopWatch yang kita buat, kita akan memanggil method QueryPerformanceFrequency untuk mendapatkan nilai counter per detik sekaligus mengetes apakah sistem yang kita gunakan mendukung high-resolution performance counter. Jika method ini mengembalikan nilai false, berarti sistem kita tidak mendukung high-resolution performance counter. Jika mengembalikan nilai true, maka nilai frekuensinya bisa kita dapatkan dengan membaca parameter outputnya

public StopWatch()

{

    if (QueryPerformanceFrequency(out frequency) == false)

    {

        // Frequency not supported

        throw new Win32Exception();

    }

}

Selanjutnya pada method Start kita memanggil fungsi Win32 API QueryPerformanceCounter dan pada method Stop kita memanggil kembali fungsi QueryPerformanceCounter kemudian mencari selisih nilai counter yang didapat dan menghitung durasi waktunya.

public void Start()

{

    QueryPerformanceCounter(out start);

}

 

public void Stop()

{

    QueryPerformanceCounter(out stop);

    CalculateDuration();

}

 

private void CalculateDuration()

{

    duration = (double)(stop – start) / (double)frequency;

}

————————————————— 

Source code lengkap kelas StopWatch adalah sbb:

using System;

using System.ComponentModel;

using System.Runtime.InteropServices;

 

public class StopWatch

{

    [DllImport(“KERNEL32”)]

    private static extern bool QueryPerformanceCounter(

      out long lpPerformanceCount);

 

    [DllImport(“Kernel32.dll”)]

    private static extern bool QueryPerformanceFrequency(

        out long lpFrequency);

 

    private long start;

    private long stop;

    private long frequency;

    private double duration = 0;

 

    public StopWatch()

    {

        if (QueryPerformanceFrequency(out frequency) == false)

        {

            // Frequency not supported

            throw new Win32Exception();

        }

    }

 

    public void Start()

    {

        QueryPerformanceCounter(out start);

    }

 

    public void Stop()

    {

        QueryPerformanceCounter(out stop);

        CalculateDuration();

    }

 

    public double DurationInSeconds

    {

        get { return duration; }

    }

 

    private void CalculateDuration()

    {

        duration = (double)(stop – start) / (double)frequency;

    }

} 

 

Iklan

Komentar»

1. MHarryCalgery - 19 Juni 2008

Ini yang aku cari. Terus apa bedanya dengan menggunakan kelas timer yud?

2. firstyuyu - 19 Juni 2008

Yang ini presisinya jauh lebih tinggi. Bisa sampai micro detik bahkan lebih.

3. Mirza - 20 Juni 2008

Scenario Driven Design Reset()

kok kayak dejavu gini ya Yud…
Aku juga sdg perlu Stopwatch neh…!!!
tapi pake java bukan .net 🙂

Yud bikin tutorial ttg cara pake Attribute dunks…
aku gak ngerti ttg Attribute
kayak -> [DllImport(“Kernel32.dll”)]

memangnya kalo ada itu, ato kalo ga ada bedanya apa?

4. firstyuyu - 23 Juni 2008

iya, kelas di atas masih bisa dikembangkan kok biar lebih robust dan nyaman digunakna, misalnya bisa ditambahkan property DurationInMiliseconds, kemudian bagaimana jika developer memanggil method Stop() sebelum memanggil method Start(), dll

Iya mir makasih masukannya. Sudah dimasukin ke antrian artikel yang mau ditulis 🙂

5. arunamemangmanis - 8 September 2008

yudi, makasih ya..
kelas stopwatchmu
ku pake loh.
hehhehe…

6. firstyuyu - 8 September 2008

Iya, aku juga ikut senang klo apa yang aku tulis bisa berguna 🙂

7. chibi prima (@primakid14) - 28 April 2012

runtest itu apa ya??

8. gumuxhijack - 11 Juli 2013

Bagaimana cara mencari entry point dari dll dan parameter-parameter yang dibutuhkan disetiap entry point tersebut? Bisa membuat sebuah contoh? Terima kasih

9. Ardy Riyandika S U - 2 Juli 2015

boleh tau sumber nya dari mana mas?

10. firstyuyu - 2 Juli 2015

Sumbernya dari sini: http://amzn.com/0735614229


Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: