Apa yang para programmer “optimalkan-mikro” untuk hari ini? [Tutup]

14

Kembali ke "masa lalu yang indah," ketika kami akan menyalin shareware ke disket untuk teman-teman, kami juga menggunakan sedikit perakitan. Ada praktik umum "optimasi mikro," di mana Anda akan menatap dan menatap garis-garis perakitan sampai Anda menemukan cara untuk mengekspresikannya dalam satu instruksi yang lebih sedikit. Bahkan ada pepatah, yang secara matematis tidak mungkin, bahwa " Anda selalu dapat menghapus satu instruksi lagi. " Mengingat bahwa mengubah kinerja runtime oleh faktor konstan kecil bukanlah masalah utama untuk (kebanyakan) pemrograman saat ini, adalah pemrogram mentransfer mikro ini upaya optimasi di tempat lain?

Dengan kata lain, bisakah praktik terbaik dibawa ke keadaan ekstrem di mana praktik itu tidak lagi menambah nilai? Dan bukannya membuang-buang waktu?

Sebagai contoh: Apakah programmer membuang waktu untuk menggeneralisasi metode pribadi yang hanya dipanggil dari satu tempat? Apakah waktu terbuang mengurangi data kasus uji? Apakah programmer (masih) terlalu khawatir tentang pengurangan baris kode?

Ada dua contoh hebat dari apa yang saya cari di bawah ini: (1) Menghabiskan waktu untuk menemukan nama variabel yang tepat, bahkan mengganti nama semuanya; dan (2) Menghapus bahkan duplikasi kode kecil dan renggang.


Perhatikan bahwa ini berbeda dari pertanyaan " Apa yang Anda optimalkan? ", Karena saya bertanya apa yang tampaknya dipaksakan oleh pemrogram lain, dengan stigma pengoptimalan "mikro" ini, dan karenanya bukan penggunaan waktu yang produktif.

Macneil
sumber
@ Macneil, saya tidak tahu untuk apa programmer lain mengoptimalkan mikro, tapi saya tidak punya banyak waktu untuk itu. Rekan kerja saya juga sibuk (Hanya 2 sen saya).
Pekerjaan
@ Pekerjaan: Anda belum pernah melihat seseorang membuang-buang waktu, mengubah kode tanpa alasan? Anggap dirimu beruntung. Ada dua contoh bagus di bawah ini: Nama variabel dan duplikasi kode kecil.
Macneil
1
Pertanyaannya, seperti yang sekarang dikatakan, adalah peningkatan. Saya tidak dapat menghapus suara dekat, tetapi akan menua dalam beberapa hari. Sebenarnya, pertanyaannya menarik beberapa jawaban yang cukup bagus.
Robert Harvey
1
BTW, praktik terbaik apa pun dapat dilakukan sedemikian ekstrem sehingga tidak lagi menghasilkan nilai.
Robert Harvey

Jawaban:

22

Pemformatan kode

Don't     get    me   wrong             ,
code      should be   consistent        & 
readable                                , 
but       some   take it         too far.
JeffO
sumber
Ah ya, tipe variabel lama yang baik dan nama variabel perlu kolom mereka sendiri dalam serangkaian deklarasi variabel. Oh! Lupa baris tambahan untuk =dan keempat untuk inisialisasi!
Macneil
[Sialan, akan membesarkan hati, tetapi batas harian saya tercapai ...]
Macneil
3
Profesor kami memaksa kami untuk memformat kode untuk tugas keluar dengan cara ini. Butuh waktu bertahun-tahun untuk menyingkirkan kebiasaan ini.
Oliver Weiler
Oh sayang. Pada jawaban lain saya tertawa, tetapi yang ini benar-benar sakit :-(
Steve314
2
+1 Saya pernah bekerja dengan perpustakaan di mana pengembang menolak untuk membuat kodenya benar-benar karena mengacaukan kode yang diformat kolomnya ...
Dean Harding
20

Saya biasa menulis banyak assembler kembali pada hari itu. Bukan saja kompiler menjadi lebih baik, tetapi sebagian besar perangkat keras sekarang memiliki banyak logika yang dikhususkan untuk eksekusi kode yang out-of-order. Masalah mikro sebenarnya adalah penjadwalan, sebagian besar instruksi komputer mengambil beberapa jam mesin untuk menghasilkan hasil - dan beban memori yang meluputkan cache mungkin membutuhkan beberapa ratus! Jadi idenya adalah untuk menjadwalkan instruksi lain untuk melakukan sesuatu yang bermanfaat, alih-alih menunggu hasil. Dan mesin modern dapat mengeluarkan beberapa instruksi per periode jam. Setelah kami mulai mengeksekusi HW yang tidak sesuai pesanan, saya menemukan bahwa mencoba untuk mendapatkan kinerja yang hebat dengan hand coding menjadi permainan mug. Pertama HW rusak tidak akan menjalankan instruksi dalam pesanan Anda dibuat dengan hati-hati, arsitektur HW baru yang mewah telah mengurangi penalti cukup penjadwalan perangkat lunak yang tidak optimal sehingga kompiler biasanya dalam beberapa persen dari kinerja Anda. Saya juga menemukan bahwa kompiler sekarang menerapkan trik yang terkenal tetapi menghasilkan kompleksitas, seperti membuka gulungan, memuat bawah, pipelining perangkat lunak dll. Intinya, Anda harus bekerja sangat keras, lewati beberapa trik ini dan kompiler mengalahkan Anda. Gunakan semuanya dan jumlah instruksi assembler yang Anda butuhkan bertambah beberapa kali lipat!

Mungkin bahkan lebih penting, sebagian besar masalah kinerja, bukan tentang tingkat masalah instruksi, tetapi memasukkan data ke dalam CPU. Seperti yang saya sebutkan di atas, latensi memori sekarang ratusan siklus, dan CPU dapat menjalankan beberapa instruksi per periode jam, jadi kecuali program-dan terutama struktur data dirancang sehingga tingkat hit cache sangat tinggi, microtuning pada instruksi level tidak akan memiliki hasil. Sama seperti tipe militer mengatakan taktik bicara amatir, logistik pro bicara. Pemrograman kinerja sekarang lebih dari 90% logistik (memindahkan data). Dan ini sulit untuk diukur, karena manajemen memori modern biasanya memiliki beberapa tingkat cache, dan halaman memori virtual ditangani oleh unit perangkat keras yang disebut TLB. Juga penyejajaran tingkat rendah dari alamat menjadi penting, karena transfer data aktual, tidak dalam satuan byte, atau bahkan panjang 64bit, tetapi mereka datang dalam satuan garis cache. Kemudian sebagian besar mesin modern memiliki perangkat keras yang mencoba memprediksi baris cache yang Anda lewatkan dalam waktu dekat dan mengeluarkan prefetch otomatis untuk memasukkannya ke dalam cache. Jadi kenyataannya adalah bahwa dengan model kinerja CPU modern begitu rumit sehingga hampir tidak dapat dimengerti. Bahkan simulator perangkat keras terperinci tidak akan pernah bisa menandingi logika chip yang tepat, sehingga penyetelan yang tepat tidak mungkin dilakukan lagi.

Masih ada tempat untuk beberapa kode tangan. Pustaka matematika (seperti fungsi exp), seperti operasi aljabar linier yang lebih penting (seperti matriks berlipat ganda) masih biasanya dikodekan dengan tangan oleh para ahli yang bekerja untuk vendor perangkat keras (yaitu Intel atau AMD, atau IBM), tetapi mereka mungkin hanya perlu beberapa programmer assembler kedudukan tertinggi per mega-komputer corp.

Omega Centauri
sumber
1
Pengkodean tangan semakin sulit bagi orang yang bekerja di luar vendor CPU, karena tugas semakin tergantung pada pengetahuan orang dalam dan alat khusus vendor (kompiler dan profiler). spiral.net mencoba memodelkan pengoptimalan CPU dan mengotomatiskan pencarian untuk solusi optimal.
rwong
Banyak bahasa komputer mendorong pemrogram untuk mengoptimalkan mikro secara tidak masuk akal dengan membuatnya susah menggunakan presisi ganda untuk perhitungan yang hasilnya akan ditampilkan float. Untuk beberapa alasan saya tidak dapat mengerti, banyak orang melihat bahwa ini adalah hal yang baik.
supercat
10

Saya kadang-kadang menghabiskan (buang?) Waktu ketika memilih nama baik untuk variabel atau metode sehingga tidak hanya deskriptif tetapi juga memiliki gaya bahasa yang baik.

Ini sedikit lebih jauh ketika saya mencoba untuk menempatkan seluruh karya (program) ke dalam gaya bahasa yang sama. Kadang pendapat saya berubah dan saya merevisi buku itu. :)

Tidak, itu membutuhkan banyak waktu. Agak jarang. Tapi saya suka menjaga tata bahasa yang baik dalam program saya.


sumber
3
Penamaan itu sulit. Oleh karena itu Anda harus merevisi nama ketika Anda memikirkan nama yang jauh lebih baik. Perhatikan bahwa ini menangkap upaya pikiran, dan semoga juga mengkristal "mengapa".
1
Ini adalah hal yang sangat berotak kiri (sisi kiri otak Anda bertanggung jawab untuk memproses bahasa). Sebagai seorang programmer berotak kanan, saya cenderung menghabiskan lebih sedikit waktu untuk mengkhawatirkan semantik dan lebih banyak waktu mengkhawatirkan tentang bagaimana semua bagian saling cocok.
Jason Baker
7
Penamaan variabel dan metode adalah bagian penting dari pemeliharaan. Seseorang harus meluangkan waktu untuk memikirkan nama, sehingga 5 tahun dari sekarang, orang yang memelihara kode memiliki waktu yang lebih mudah dengannya.
GrandmasterB
@ grandmaster: Tidak bisa setuju lebih banyak.
Robert Harvey
4
@ right-brainers: Silakan kode untuk lef-tbrainers, jadi saya juga bisa membaca kode Anda
Juan Mendes
10

Kompleksitas waktu. Saya menghabiskan terlalu banyak waktu untuk mengoptimalkan hal-hal untuk kinerja kasus terburuk pada skala yang urutan besarnya lebih besar daripada apa pun yang saya tahu program akan bertemu secara realistis.

Saya terlalu obsesif untuk melepaskan tulang 'tapi itu bisa tumbuh sebesar itu', bahkan ketika keputusan desain lainnya menghalangi hal itu dari terjadi secara realistis.

Namun, dalam pembelaan saya, seandainya yang tidak realistis menjadi kenyataan .. optimalisasi sebenarnya bukan 'mikro' lagi. Catatan, saya tidak mengatakan tidak mungkin , tetapi tidak realistis .

Tentu saja, persyaratan diutamakan.

Pos Tim
sumber
1
Saya bekerja di perusahaan yang karam karena hal ini.
Henry
2
@Henry - Saya berjanji, bukan saya :)
Tim Post
1
@ Henry: Maksud Anda, mereka menyia-nyiakan waktu untuk mengoptimalkan hal-hal yang kemungkinan tidak akan pernah terjadi, atau mereka tidak memikirkan hal-hal yang kemungkinan akan "tidak pernah" terjadi ... sampai hal itu terjadi dan sudah terlambat?
Dean Harding
2
@ Henry: Jika sebuah perusahaan memiliki produk yang sangat skalabel dan masih tenggelam, itu adalah kesalahan penjualan dan pemasaran (karena tidak menargetkan pelanggan volume tinggi dan tidak menentukan harga dengan tepat), bukan pengembangan.
rwong
1
Perusahaan menghabiskan terlalu banyak waktu merancang sistem untuk jutaan pengguna ketika mereka tidak memiliki 1 pengguna. Pasti karena kesalahan pemasaran. Ya mari kita menyalahkan pemasaran, orang-orang itu idiot.
Henry
8

Saya pikir saya sudah menghabiskan waktu berminggu-minggu untuk mengutak-atik handler pengecualian Java.

Ini banyak pekerjaan untuk kode yang gagal dua atau tiga kali per tahun. Haruskah ini menjadi peringatan atau info? Kesalahan atau fatal? Apakah ini benar-benar fatal, prosesnya akan muncul kembali dalam lima menit? Apakah ini benar-benar peringatan jika semuanya masih dalam kondisi standar?

Banyak pusar yang memandang dan berdiskusi tentang sifat kesalahan IO. Jika Anda tidak dapat membaca file melalui jaringan, apakah itu kesalahan file atau kesalahan jaringan? Dan seterusnya.

Pada satu titik saya mengganti semua string concat dengan String.formatsehingga kesalahan file tahunan tidak menghasilkan objek tambahan di heap. Itu sia-sia.

sal
sumber
3
Ini pekerjaan penting. Harga kegagalan = pesan kesalahan Anda ditampilkan di WTF harian.
Steve314
7

Saya kira saya terlalu khawatir dengan LOC. Tidak begitu banyak LOC itu sendiri, tetapi lebih pada jumlah pernyataan dan bahkan lebih banyak lagi pernyataan duplikat. Saya alergi terhadap kode rangkap. Secara umum saya suka refactoring, tapi saya kira sekitar 50% dari apa yang saya lakukan tidak membuat kode lebih baik.

back2dos
sumber
4
+1 untuk "Saya alergi terhadap kode rangkap". Lihat juga balasan saya di sini: programmers.stackexchange.com/questions/14610/…
Macneil
Berpikir tentang itu - Saya memiliki masalah ini dengan loop yang berhubungan dengan titik Knuth dibuat tentang kebagian, dan kadang-kadang harus berdagang satu atau dua siklus atau beberapa kode duplikat untuk menulis kode terstruktur. Saya akan menggunakan goto dalam kasus yang sangat jarang (paling umum = kode yang dihasilkan), tetapi variasi saya dari gangguan ini adalah membuang-buang waktu mengkhawatirkan dan mengutak-atik lingkaran tanpa henti berusaha menghilangkan inefisiensi sepele namun tetap membuat kode dapat dibaca.
Steve314
5

Membaca file baris demi baris alih-alih hanya membaca seluruh baris menjadi sebuah string dan memproses string dalam satu waktu.

Tentu, ini membuat perbedaan dalam kecepatan eksekusi tetapi jarang sepadan dengan baris kode tambahan. Itu membuat kode jauh lebih sedikit perawatan dan meningkatkan ukuran kode.

Ya, ini mungkin tidak masuk akal jika file tersebut 3GB besar tetapi sebagian besar file tidak sebesar itu (setidaknya bukan yang saya kerjakan ;-)).

Oliver Weiler
sumber
3
Bahkan jika itu 3GB atau lebih, mesin 64-bit dapat menanganinya dengan memori virtual. Gunakan file yang dipetakan memori dan bahkan tidak akan membaca bagian dari file Anda sampai dibutuhkan. Pikiran Anda, bahkan itu optimasi mikro dalam kasus normal.
Steve314
3

Ketika saya sedang menulis bahasa assembly, masuk akal untuk memeriksa byte dan siklus, tapi itu sudah lama sekali dan kompiler telah datang jauh sejak saat itu. Saya tidak akan mencoba untuk mengoptimalkan secara manual sekarang.

Demikian pula, ketika saya beralih ke menulis dalam C itu cukup mudah untuk melakukan pekerjaan yang lebih baik daripada kompiler C, tetapi setiap tahun Borland atau Microsoft atau seseorang akan merilis yang baru dan yang lebih baik yang menendang yang sebelumnya di sekitar ruangan. Saya mulai memperhatikan kode perakitan aktual yang dipancarkan oleh kompiler dan, menggantung jika tidak menulis beberapa kode yang bagus dan ketat, membuka gulungan loop, memindahkan variabel di luar loop, dll.

Sekarang, saya menulis dalam banyak bahasa yang lebih tinggi seperti Perl, Python dan Ruby. Saya menggunakan beberapa trik kompiler di depan, seperti loop membuka gulungan jika itu masuk akal, memindahkan variabel statis di luar loop, dll., Tapi saya tidak terlalu khawatir tentang hal itu karena CPU sedikit lebih cepat sekarang. Jika suatu aplikasi tampaknya diseret secara tidak terduga maka saya akan menggunakan profiler dan melihat apa yang dapat saya temukan, dan kemudian jika sesuatu dapat diperbaiki saya akan mulai membuat tolok ukur berbagai cara yang dapat saya pikirkan untuk melakukan sesuatu lebih cepat, dan kemudian lihat bagaimana itu meningkat.

Secara umum saya mencoba untuk menjadi pintar tentang bagaimana saya menulis kode, berdasarkan pengalaman bertahun-tahun.

Manusia Timah
sumber
Halo Greg, terima kasih atas jawabannya, tetapi saya sedang mencari apa yang programmer lakukan untuk membuang waktu, bukan untuk mengoptimalkan kinerja runtime. Ada dua contoh hebat di atas: Nama variabel dan menghapus duplikasi kode bahkan kecil.
Macneil
3

Pengoptimalan mikro: meningkatkan kinerja hal-hal tunggal yang dapat diparalelkan atau yang dapat ditingkatkan dengan perangkat keras baru.

Jika ada sesuatu yang lambat pada komputer dari 10 tahun yang lalu, solusi yang lebih murah mungkin untuk membeli komputer yang lebih baru, lebih cepat, daripada membuang waktu programmer mengoptimalkan. Fokus besar optimasi yang dipertimbangkan adalah mencari cara untuk menggunakan 8 core yang bisa Anda dapatkan hari ini, atau 64 core yang bisa Anda dapatkan dalam beberapa tahun, alih-alih merasa kesal tentang minutia seperti biaya tambahan sampah koleksi.

Kevin Cantu
sumber
2

Mikro-optimasi dalam hal kinerja runtime hampir tidak menjadi masalah tertutup bahkan hari ini (walaupun mungkin kurang umum). Saya kadang-kadang harus menjelaskan kepada orang-orang bahwa overhead mengalokasikan objek tambahan setiap permintaan atau menambahkan panggilan fungsi tambahan dapat diabaikan.

Selain itu, saya juga melihat programmer mengoptimalkan mikro untuk kesederhanaan (termasuk saya sendiri). Saya belum bekerja di suatu tempat yang saya tidak perlu menjelaskan perbedaan antara kesederhanaan dan kesederhanaan.

Jason Baker
sumber
Mengapa programmer. berbeda? Apa bedanya, tolong.
Dan Rosenstark
@ Yar - Mengapa programmer berbeda dari apa?
Jason Baker
mengapa programmers.= programmers.stackexchange.comberbeda dari setiap tempat Anda bekerja di mana Anda harus menjelaskan perbedaan antara kedua konsep ini? Tolong jelaskan perbedaannya.
Dan Rosenstark
@Yar - Saya tidak tahu itu akan terjadi. Bahkan, sebagai tujuan dari programmer. Se adalah untuk membantu programmer mengumpulkan pengetahuan, saya berharap itu tidak terjadi sehingga orang mungkin setidaknya sedikit tercerahkan oleh jawaban saya.
Jason Baker
2
Jadi apa bedanya dengan kesederhanaan dan kesederhanaan?
Dan Rosenstark
2

Saya mendukung prinsip jangan-optimalkan-kecuali-benar-benar-diperlukan. Dan saya semua untuk prinsip profil-pertama. Dan pada prinsipnya, saya hanya akan mengoptimalkan sesuatu yang akan membuat perbedaan yang dibutuhkan.

Itu pada prinsipnya. Tapi prinsip adalah pembohong.

Saya memiliki kebiasaan merawat fungsi-fungsi di perpustakaan yang sering digunakan yang saya pikir akan banyak digunakan dalam loop batin. Dan kemudian, ketika Anda melihat sesuatu di fungsi lain, itu tidak begitu sering digunakan ...

Oh - dan kemudian ada logika "Saya sedang menulis itu - tentu saja itu adalah perpustakaan yang penting".

Oh - dan BTW. Saya belum pernah menggunakan profiler untuk memandu optimasi. Tidak memiliki akses ke iklan, dan tidak pernah cukup membangun motivasi untuk mencari tahu gprof.

Pada dasarnya, saya munafik. Prinsip-prinsip ini berlaku untuk orang lain, tetapi saya terlalu takut pada seseorang yang mengatakan "tetapi mengapa Anda menulisnya dengan cara yang lambat dan jelek?" jadi saya tidak akan pernah bisa menerapkannya dengan benar pada diri saya sendiri.

Tapi aku tidak seburuk yang kulakukan di sini. Dan saya benar-benar kebal terhadap penipuan diri sendiri, jadi Anda tahu saya benar tentang itu!

EDIT

Saya harus menambahkan - salah satu hang-up bodoh utama saya adalah panggilan overhead. Tidak di mana-mana, tentu saja, tetapi dalam kasus-kasus yang saya-pikir-itu-akan-digunakan-banyak-di-dalam-loop (di mana saya tidak punya bukti objektif masalah). Saya telah menulis kode berbasis offset jahat untuk menghindari membuat panggilan metode virtual lebih dari sekali. Hasilnya bahkan mungkin lebih lambat, karena mungkin bukan gaya pengkodean yang dirancang optimis untuk menghadapinya dengan baik - tetapi lebih pintar ;-)

Steve314
sumber
+1 Ah, ya! Kelas ini mem-parsing argumen command-line aplikasi saya yang sangat spesifik dan unik, tetapi izinkan saya memformat dan mendokumentasikan sepenuhnya ketika Javadoc, karena pasti orang lain akan menggunakan ini selama bertahun-tahun! [Akan perlu diputuskan nanti, cap harian saya tercapai.]
Macneil
@ Macneil - itu Doxygen, saya ingin Anda tahu. Dengan setiap opsi yang saya temukan dinyalakan, sehingga setiap fungsi kecil akan "didokumentasikan" dengan sangat terperinci, lengkap dengan selusin grafik GraphViz yang cantik. Benar-benar membantu semua orang menghargai betapa pentingnya kode saya - dan print-out dapat wallpaper blok kantor yang cukup besar.
Steve314
1

Di masa lalu ketika komputer memiliki waktu jam diukur dalam mikrodetik, memori diukur dalam kilobyte, dan kompiler primitif, optimasi mikro masuk akal.

Kecepatan dan ukuran komputer generasi saat ini dan kualitas kompiler generasi sekarang berarti bahwa optimasi mikro biasanya membuang-buang waktu. Pengecualiannya cenderung ketika Anda benar-benar harus mendapatkan kinerja maksimum dari beberapa kode intensif komputasi ... atau Anda menulis untuk sistem tertanam dengan sumber daya yang sangat terbatas.

tapi saya sedang mencari apa yang programmer lakukan untuk membuang waktu, bukan untuk mengoptimalkan kinerja runtime.

Twitter dan Facebook muncul dalam pikiran :-)

Stephen C
sumber
Hai Stephen, itu komentar yang bagus tentang optimasi mikro, tetapi apakah Anda melihat padanan modern? [Facebook dan Twitter bukanlah "praktik terbaik" yang bisa dilakukan terlalu jauh.]
Macneil
Itu masih masuk akal. Jam waktu mungkin perintah besarnya lebih kecil, tetapi kodenya adalah pesanan besarnya lebih besar ...
hplbsh
@Stuart - itu berarti ada pesanan kode yang lebih besar untuk mengoptimalkan mikro ... yang tidak berskala.
Stephen C