Rabu, 19 Oktober 2016

Kenapa Fungsi Macro Lebih Cepat? Ini Jawabannya



Macro adalah fitur umum yang sudah banyak disediakan oleh berbagai macam bahasa pemrograman. Mereka berkata, "Ayo, gunakan bahasa pemrograman kami. Ada macro-nya lho, bisa bikin program anda lebih cepat". Buset dah.. haha

Tapi kalau kalian tahu, fungsi macro sebenarnya tidak akan membawa pengaruh besar jika kita hanya membuat program kecil.

Maksudnya?

Fungsi yang dibuat dalam bentuk macro akan diselipkan bersama dengan caller (fungsi yang memanggil/memerlukan) macro tersebut, sehingga akan menggurangi function call overhead.

Dalam program berskala besar, ada banyak sekali kode yang harus dieksekusi. Nah, masalahnya tidak semua runtutan program diletakkan pada fungsi main() kan? Ada fungsi lain yang menjalankan kerja program secara spesifik; dan jumlahnya banyak! Semakin sering fungsi tersebut dipanggil, semakin buang-buang sumber daya waktu prosesor.

Namun, hal tersebut dapat diminimalisir dengan penggunaan fungsi macro dan inline function.

Jika anda mengenal bahasa assembly, maka anda akan sering melihat instruksi CALL dan RET dalam alur perjalanan kode fungsi. Belum lagi kalau fungsi yang dipanggi menangani parameter, maka ada instruksi lain yang digunakan, antara lain:
PUSH EBP; MOV EBP,ESP; SUB ESP,8; MOV ESP,EBP dan POP EBP.

Jika sebuah fungsi dipanggil secara berulang-ulang, tentu akan menurunkan efektivitas program.

Contoh sederhanya, kita akan mencoba menulis beberapa baris fungsi. Compile, lalu lakukan disassembly dengan objdump, atau program semacamnya.

int add(int a,int b){
    return a + b;
}
int x=1,y=2;
int caller(){
    return add(x,y);
}


00000000 <_add>:
   0:   55                   push   ebp
   1:   89 e5                mov    ebp,esp
   3:   8b 55 08             mov    edx,DWORD PTR [ebp+0x8]
   6:   8b 45 0c             mov    eax,DWORD PTR [ebp+0xc]
   9:   01 d0                add    eax,edx
   b:   5d                   pop    ebp
   c:   c3                   ret

0000000d <_caller>:
   d:   55                   push   ebp
   e:   89 e5                mov    ebp,esp
  10:   83 ec 08             sub    esp,0x8
  13:   8b 15 04 00 00 00    mov    edx,DWORD PTR ds:0x4
  19:   a1 00 00 00 00       mov    eax,ds:0x0
  1e:   89 54 24 04          mov    DWORD PTR [esp+0x4],edx
  22:   89 04 24             mov    DWORD PTR [esp],eax
  25:   e8 d6 ff ff ff       call   0 <_add>
  2a:   c9                   leave
  2b:   c3                   ret



Sekarang, coba kita ubah fungsi add di atas ke dalam bentuk macro seperti ini:

#define ADD(a,b) (a + b)

int x=1,y=2;
int caller(){
    return ADD(x,y);
}


00000000 <_caller>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   8b 15 00 00 00 00       mov    edx,DWORD PTR ds:0x0
   9:   a1 04 00 00 00          mov    eax,ds:0x4
   e:   01 d0                   add    eax,edx
  10:   5d                      pop    ebp
  11:   c3                      ret


Nah, kelihatan kan bedanya?
Sebenarnya tidak ada perbedaan jauh tentang penggunaan macro dan fungsi biasa. Yang menjadi perbedaan mencolok adalah pada penggunaan instruksi CALL dan RET. Semakin sering fungsi tersebut dipanggil, semakin tidak efisien hasilnya. Pada program kecil, ini tidak memiliki pengaruh yang berarti, karena rata-rata instruksi tersebut tidak memakan waktu melebihi 10 clock cycle prosesor. Atau, jika direrata pada prosesor 2GHz, setiap instruksi tersebut hanya memakan waktu prosesor 1 / 200.000.000 detik.

Beda kasusnya dengan program besar yang berjalan pada server yang on 24 jam. Di sini, penulisan kode sepertinya mulai perlu untuk dipertimbangkan.
Load disqus comments

0 comments