Apakah optimasi prematur benar-benar akar dari semua kejahatan?

215

Seorang kolega saya hari ini melakukan kelas yang disebut ThreadLocalFormat, yang pada dasarnya memindahkan instance kelas Java Format ke thread lokal, karena mereka tidak aman untuk thread dan "relatif mahal" untuk dibuat. Saya menulis tes cepat dan menghitung bahwa saya dapat membuat 200.000 instance per detik, bertanya kepadanya apakah dia menciptakan banyak, yang dia jawab "tidak jauh dari banyak itu". Dia adalah programmer yang hebat dan semua orang di tim sangat terampil sehingga kami tidak memiliki masalah dalam memahami kode yang dihasilkan, tapi itu jelas merupakan kasus optimalisasi di mana tidak ada kebutuhan nyata. Dia mundur kode atas permintaan saya. Bagaimana menurut anda? Apakah ini kasus "optimisasi prematur" dan seberapa buruk itu sebenarnya?

Craig Day
sumber
23
Saya pikir Anda perlu membedakan antara optimasi prematur, dan optimasi yang tidak perlu. Terlalu dini bagi saya menyarankan 'terlalu dini dalam siklus hidup' sementara yang tidak disarankan menunjukkan 'tidak menambah nilai signifikan'. IMO, persyaratan untuk optimasi akhir menyiratkan desain yang jelek.
110
Ya, tetapi kejahatan adalah polinomial dan memiliki banyak akar, beberapa di antaranya rumit.
dan_waterworth
7
Anda harus mempertimbangkan, bahwa Knuth menulis ini tahun 1974. Pada tahun tujuh puluhan itu tidak mudah untuk menulis program lambat seperti saat ini. Dia menulis dengan Pascal dalam pikiran dan bukan dengan Java atau PHP.
ceving
4
Tidak. Akar semua kejahatan adalah keserakahan.
Tulains Córdova
12
@ceving Di 70 itu semudah hari ini untuk menulis program yang lambat. Jika Anda memilih algoritma yang salah atau struktur data yang salah maka BAM! Performa buruk di semua tempat. Seseorang bisa berdebat sebaliknya. Saat ini, ada lebih banyak alat dan tidak dapat dimaafkan bahwa seorang programmer masih menulis perangkat lunak yang menderita operasi penyimpanan paling dasar. Paralelisme hampir menjadi komoditas dan kita masih menderita. Kinerja lambat tidak dapat disalahkan pada bahasa atau alat atau CPU atau memori. Ini keseimbangan yang halus dari banyak hal yang mengapa hampir tidak mungkin untuk mengoptimalkan lebih awal.
Alex

Jawaban:

322

Penting untuk diingat kutipan lengkap:

Kita harus melupakan efisiensi kecil, katakanlah sekitar 97% dari waktu: optimasi prematur adalah akar dari semua kejahatan. Namun kita tidak boleh melewatkan peluang kita dalam 3% kritis itu.

Artinya, tanpa adanya masalah kinerja yang diukur, Anda tidak boleh mengoptimalkan karena Anda pikir Anda akan mendapatkan peningkatan kinerja. Ada optimasi yang jelas (seperti tidak melakukan rangkaian string di dalam loop ketat) tetapi apa pun yang bukan optimasi yang jelas sepele harus dihindari sampai dapat diukur.

Masalah terbesar dengan "optimisasi prematur" adalah ia dapat memperkenalkan bug yang tidak terduga dan bisa menjadi pemboros waktu yang sangat besar.

Scott Dorman
sumber
7
Berasal dari Donald Knuth, saya tidak akan terkejut jika dia memiliki beberapa bukti untuk mendukungnya. BTW, Src: Pemrograman Terstruktur dengan pergi ke Pernyataan, ACM Journal Computing Survey, Vol 6, No. 4, Desember 1974. p.268. citeseerx.ist.psu.edu/viewdoc/…
mctylr
28
... Seorang programmer yang baik tidak akan terbuai oleh kepuasan dengan alasan seperti itu, ia akan bijaksana untuk melihat dengan cermat kode kritis; tetapi hanya setelah kode itu diidentifikasi (sisa kutipan yang lebih lengkap)
mctylr
21
Saya memiliki 20k pengguna rep hari ini memberi tahu saya bahwa menggunakan HashSetbukan Listoptimasi prematur. Kasus penggunaan yang dimaksud adalah koleksi yang diinisialisasi secara statis yang satu-satunya tujuan adalah untuk berfungsi sebagai tabel pencarian. Saya tidak berpikir saya salah mengatakan ada perbedaan dalam memilih alat yang tepat untuk pekerjaan versus pengoptimalan prematur. Saya pikir posting Anda mengonfirmasi filosofi ini: There are obvious optimizations...anything that isn't trivially clear optimization should be avoided until it can be measured.Optimalisasi HashSet telah diukur dan didokumentasikan dengan seksama.
naksir
9
@ Crush: ya: Setsemantik lebih benar dan informatif daripada List, jadi ada lebih dari aspek optimasi untuk itu.
Erik Allik
7
Saya ingin menambahkan bahwa optimasi prematur tidak perlu bingung dengan merancang seluruh arsitektur aplikasi Anda agar berjalan cepat secara umum, skala dan mudah dioptimalkan.
Erik Allik
111

Optimalisasi mikro prematur adalah akar dari semua kejahatan, karena optimisasi mikro mengabaikan konteks. Mereka hampir tidak pernah berperilaku seperti yang diharapkan.

Apa saja optimasi awal yang baik dalam urutan kepentingan:

  • Optimalisasi arsitektur (struktur aplikasi, cara komponen dan lapisannya)
  • Optimalisasi aliran data (di dalam dan di luar aplikasi)

Beberapa optimisasi siklus pertengahan pengembangan:

  • Struktur data, perkenalkan struktur data baru yang memiliki kinerja lebih baik atau overhead yang lebih rendah jika perlu
  • Algoritma (sekarang saat yang tepat untuk mulai memutuskan antara quicksort3 dan heapsort ;-))

Beberapa optimisasi akhir siklus pengembangan

  • Menemukan hotpot kode (pengulangan ketat, yang harus dioptimalkan)
  • Pengoptimalan berbasis profil bagian komputasi kode
  • Optimalisasi mikro dapat dilakukan sekarang karena dilakukan dalam konteks aplikasi dan dampaknya dapat diukur dengan benar.

Tidak semua optimisasi awal adalah jahat, optimisasi mikro jahat jika dilakukan pada waktu yang salah dalam siklus hidup pengembangan , karena mereka dapat mempengaruhi arsitektur secara negatif, dapat secara negatif mempengaruhi produktivitas awal, dapat menjadi kinerja yang tidak relevan, bijaksana atau bahkan memiliki efek yang merugikan pada akhirnya. pembangunan karena kondisi lingkungan yang berbeda.

Jika kinerja menjadi perhatian (dan selalu harus) selalu berpikir besar . Kinerja adalah gambaran yang lebih besar dan bukan tentang hal-hal seperti: haruskah saya menggunakan int atau panjang ? Gunakan Top Down saat bekerja dengan kinerja alih-alih Bottom Up .

Pop Catalin
sumber
"Optimasi: Musuh Terburukmu", oleh Joseph M. Newcomer: flounder.com/optimization.htm
Ron Ruble
53

optimasi tanpa pengukuran pertama hampir selalu prematur.

Saya percaya itu benar dalam kasus ini, dan benar dalam kasus umum juga.

Jeff Atwood
sumber
Sini sini! Optimalisasi yang tidak dipertimbangkan membuat kode tidak dapat dipelihara dan seringkali menjadi penyebab masalah kinerja. mis. Anda melakukan multi-utas suatu program karena Anda membayangkannya dapat membantu kinerja, tetapi, solusi sebenarnya adalah beberapa proses yang sekarang terlalu rumit untuk diterapkan.
James Anderson
kecuali jika didokumentasikan.
nawfal
Iya. setuju. Pertama-tama harus diukur. Tidak ada cara Anda tahu di mana kemacetan sampai Anda menguji sesuatu ujung ke ujung dan mengukur setiap langkah.
Oliver Watkins
Pengukuran bisa berbohong. Saya telah melihat spesialis berpengalaman menghabiskan berminggu-minggu membaca jejak dan menjalankan profil untuk menabrak dinding di mana mereka pikir tidak ada lagi yang bisa didapat. Lalu saya membaca keseluruhan kode dan dalam beberapa jam membuat beberapa perubahan holistik untuk mendapatkan peningkatan 10x. Profil tidak menunjukkan jalur panas karena seluruh kode dirancang dengan buruk. Saya juga melihat profiler mengklaim hotpath di mana seharusnya tidak ada. Seseorang yang "mengukur" akan mengoptimalkan hotpath, tetapi mereka seharusnya menyadari bahwa hotpath adalah gejala dari kode yang buruk lainnya.
Bengie
42

Optimalisasi adalah "jahat" jika menyebabkan:

  • kode kurang jelas
  • kode secara signifikan lebih banyak
  • kode kurang aman
  • waktu programmer terbuang

Dalam kasus Anda, sepertinya sedikit waktu programmer sudah dihabiskan, kodenya tidak terlalu rumit (tebakan dari komentar Anda bahwa semua orang di tim akan dapat memahami), dan kodenya sedikit lebih banyak bukti masa depan (menjadi utas aman sekarang, jika saya mengerti uraian Anda). Kedengarannya hanya sedikit jahat. :)

John Mulder
sumber
4
Hanya jika biaya, itu sesuai dengan poin-poin Anda, lebih besar dari nilai diamortisasi yang disampaikan. Seringkali kompleksitas memperkenalkan nilai, dan dalam kasus ini seseorang dapat merangkumnya sehingga melewati kriteria Anda. Itu juga akan digunakan kembali dan terus memberikan nilai lebih.
1
Dua poin pertama adalah yang utama bagi saya, dengan poin keempat menjadi konsekuensi negatif dari melakukan optimasi prematur. Secara khusus, ini adalah bendera merah setiap kali saya melihat seseorang menerapkan kembali fitur dari perpustakaan standar. Seperti, saya pernah melihat seseorang menerapkan rutinitas khusus untuk manipulasi string karena dia khawatir bahwa perintah bawaan terlalu lambat.
jhocking
8
Membuat utas kode aman bukan optimasi.
mattnz
38

Saya terkejut bahwa pertanyaan ini berumur 5 tahun, namun belum ada yang memposting lebih banyak dari apa yang Knuth katakan daripada beberapa kalimat. Beberapa paragraf yang mengelilingi kutipan terkenal menjelaskannya dengan cukup baik. Makalah yang dikutip disebut " Pemrograman Terstruktur dengan pergi ke Pernyataan ", dan sementara itu hampir 40 tahun, adalah tentang kontroversi dan gerakan perangkat lunak yang keduanya tidak ada lagi, dan memiliki contoh dalam bahasa pemrograman yang banyak orang tidak pernah mendengar, sejumlah besar mengejutkan dari apa yang dikatakannya masih berlaku.

Berikut ini kutipan yang lebih besar (dari halaman 8 dari pdf, halaman 268 dalam aslinya):

Peningkatan kecepatan dari Contoh 2 ke Contoh 2a hanya sekitar 12%, dan banyak orang akan mengatakan itu tidak signifikan. Kebijaksanaan konvensional yang dimiliki oleh banyak insinyur perangkat lunak saat ini menyerukan untuk mengabaikan efisiensi dalam hal kecil; tapi saya percaya ini hanyalah reaksi berlebihan terhadap pelanggaran yang mereka lihat dipraktekkan oleh pemrogram bodoh dan bijak, yang tidak bisa men-debug atau mempertahankan program "optimal" mereka. Dalam disiplin ilmu teknik yang mapan, peningkatan 12%, mudah diperoleh, tidak pernah dianggap marginal; dan saya percaya sudut pandang yang sama harus berlaku dalam rekayasa perangkat lunak. Tentu saja saya tidak akan repot-repot membuat optimasi seperti itu pada pekerjaan sekali pakai, tetapi ketika itu adalah pertanyaan tentang mempersiapkan program berkualitas, saya tidak ingin membatasi diri pada alat yang menyangkal efisiensi saya.

Tidak ada keraguan bahwa efisiensi akan mengarah pada penyalahgunaan. Programmer menghabiskan banyak waktu untuk memikirkan, atau mengkhawatirkan, kecepatan bagian nonkritis dari program mereka, dan upaya efisiensi ini sebenarnya memiliki dampak negatif yang kuat ketika debugging dan pemeliharaan dipertimbangkan. Kita harus melupakan efisiensi kecil, katakanlah sekitar 97% dari waktu: optimasi prematur adalah akar dari semua kejahatan.

Namun kita tidak boleh melewatkan peluang kita dalam 3% kritis itu. Seorang programmer yang baik tidak akan terbuai oleh kepuasan dengan alasan seperti itu, ia akan bijaksana untuk melihat dengan cermat kode kritis; tetapi hanya setelah kode itu diidentifikasi. Seringkali merupakan kesalahan untuk membuat penilaian apriori tentang bagian mana dari suatu program yang benar-benar kritis, karena pengalaman universal programmer yang telah menggunakan alat pengukuran adalah bahwa tebakan intuisi mereka gagal.

Bit bagus lain dari halaman sebelumnya:

Gaya pemrograman saya sendiri tentu saja telah berubah selama dekade terakhir, sesuai dengan tren zaman (misalnya, saya tidak begitu rumit lagi, dan saya menggunakan lebih sedikit ke), tetapi perubahan besar dalam gaya saya telah disebabkan untuk fenomena inner loop ini. Saya sekarang melihat dengan mata yang sangat kuning pada setiap operasi dalam loop kritis, berusaha untuk memodifikasi program dan struktur data saya (seperti dalam perubahan dari Contoh 1 ke Contoh 2) sehingga beberapa operasi dapat dihilangkan. Alasan untuk pendekatan ini adalah: a) tidak butuh waktu lama, karena loop dalam pendek; b) imbalannya nyata; dan c) Saya kemudian dapat menjadi kurang efisien di bagian lain dari program saya, yang karenanya lebih mudah dibaca dan lebih mudah ditulis dan di-debug.

Michael Shaw
sumber
20

Saya sering melihat kutipan ini digunakan untuk membenarkan kode yang jelas buruk atau kode yang, meskipun kinerjanya belum diukur, mungkin dapat dibuat lebih cepat dengan mudah, tanpa meningkatkan ukuran kode atau mengurangi keterbacaannya.

Secara umum, saya pikir optimasi mikro awal mungkin merupakan ide yang buruk. Namun, optimasi makro (hal-hal seperti memilih algoritma O (log N) daripada O (N ^ 2)) sering bermanfaat dan harus dilakukan lebih awal, karena mungkin boros untuk menulis algoritma O (N ^ 2) dan kemudian buang sepenuhnya demi pendekatan O (log N).

Perhatikan kata-kata mungkin : jika O (N ^ 2) algoritma sederhana dan mudah untuk menulis, Anda bisa membuangnya kemudian tanpa banyak rasa bersalah jika ternyata menjadi terlalu lambat. Tetapi jika kedua algoritma itu sama kompleksnya, atau jika beban kerja yang diharapkan begitu besar sehingga Anda sudah tahu Anda akan membutuhkan yang lebih cepat, maka mengoptimalkan lebih awal adalah keputusan rekayasa suara yang akan mengurangi total beban kerja Anda dalam jangka panjang.

Jadi, secara umum, saya pikir pendekatan yang tepat adalah untuk mengetahui apa pilihan Anda sebelum Anda mulai menulis kode, dan secara sadar memilih algoritma terbaik untuk situasi Anda. Yang paling penting, ungkapan "optimisasi prematur adalah akar dari semua kejahatan" bukanlah alasan untuk ketidaktahuan. Pengembang karir harus memiliki gagasan umum tentang berapa biaya operasi umum; mereka harus tahu, misalnya,

  • string itu harganya lebih mahal dari angka
  • bahwa bahasa dinamis jauh lebih lambat daripada bahasa yang diketik secara statis
  • keuntungan dari array / daftar vektor lebih dari daftar yang ditautkan, dan sebaliknya
  • kapan harus menggunakan hashtable, kapan harus menggunakan peta yang diurutkan, dan kapan harus menggunakan heap
  • bahwa (jika mereka bekerja dengan perangkat seluler) "ganda" dan "int" memiliki kinerja serupa di desktop (FP bahkan mungkin lebih cepat) tetapi "ganda" mungkin seratus kali lebih lambat pada perangkat seluler kelas bawah tanpa FPU;
  • bahwa mentransfer data melalui internet lebih lambat daripada akses HDD, HDD jauh lebih lambat dari RAM, RAM jauh lebih lambat dari cache L1 dan register, dan operasi internet dapat memblokir tanpa batas waktu (dan gagal kapan saja).

Dan pengembang harus terbiasa dengan kotak peralatan struktur data dan algoritma sehingga mereka dapat dengan mudah menggunakan alat yang tepat untuk pekerjaan itu.

Memiliki banyak pengetahuan dan kotak peralatan pribadi memungkinkan Anda untuk mengoptimalkan hampir dengan mudah. Menempatkan banyak upaya ke dalam optimasi yang mungkin tidak perlu adalah kejahatan (dan saya akui jatuh ke dalam perangkap itu lebih dari sekali). Tetapi ketika optimasi semudah memilih set / hashtable alih-alih array, atau menyimpan daftar angka dalam double [] bukannya string [], lalu mengapa tidak? Saya mungkin tidak setuju dengan Knuth di sini, saya tidak yakin, tapi saya pikir dia berbicara tentang optimasi tingkat rendah sedangkan saya berbicara tentang optimasi tingkat tinggi.

Ingat, kutipan itu awalnya dari 1974. Pada 1974 komputer lambat dan daya komputasi mahal, yang memberi beberapa pengembang kecenderungan untuk terlalu mengoptimalkan, baris demi baris. Saya pikir itulah yang mendorong Knuth. Dia tidak mengatakan "jangan khawatir tentang kinerja sama sekali", karena pada tahun 1974 itu hanya akan menjadi pembicaraan gila. Knuth menjelaskan cara mengoptimalkan; singkatnya, seseorang harus fokus hanya pada kemacetan, dan sebelum Anda melakukannya, Anda harus melakukan pengukuran untuk menemukan kemacetan.

Perhatikan bahwa Anda tidak dapat menemukan hambatan sampai Anda menulis program untuk diukur, yang berarti bahwa beberapa keputusan kinerja harus dibuat sebelum segala sesuatu ada untuk diukur. Terkadang keputusan ini sulit diubah jika Anda salah. Untuk alasan ini, ada baiknya memiliki gagasan umum tentang biaya apa saja sehingga Anda dapat membuat keputusan yang masuk akal ketika tidak ada data keras yang tersedia.

Seberapa dini untuk mengoptimalkan, dan seberapa besar kekhawatiran tentang kinerja tergantung pada pekerjaan. Saat menulis skrip yang hanya akan Anda jalankan beberapa kali, mengkhawatirkan kinerja sama sekali biasanya hanya membuang waktu. Tetapi jika Anda bekerja untuk Microsoft atau Oracle dan Anda sedang bekerja di perpustakaan yang akan digunakan oleh ribuan pengembang lain dalam ribuan cara yang berbeda, mungkin perlu untuk mengoptimalkannya, sehingga Anda dapat mencakup semua yang beragam menggunakan kasing secara efisien. Meski begitu, kebutuhan akan kinerja harus selalu diimbangi dengan kebutuhan akan keterbacaan, pemeliharaan, keanggunan, ekstensibilitas, dan sebagainya.

Qwertie
sumber
2
Amin. Optimalisasi prematur dilemparkan terlalu bebas akhir-akhir ini oleh orang-orang yang mencoba membenarkan menggunakan alat yang salah untuk pekerjaan itu. Jika Anda tahu alat yang tepat untuk pekerjaan itu sebelumnya, maka tidak ada alasan untuk tidak menggunakannya.
naksir
13

Secara pribadi, sebagaimana dibahas dalam utas sebelumnya , saya tidak percaya optimasi awal buruk dalam situasi di mana Anda tahu Anda akan mengalami masalah kinerja. Sebagai contoh, saya menulis pemodelan permukaan dan perangkat lunak analisis, di mana saya secara teratur berurusan dengan puluhan juta entitas. Perencanaan untuk kinerja optimal pada tahap desain jauh lebih unggul daripada optimasi akhir dari desain yang lemah.

Hal lain yang perlu dipertimbangkan adalah bagaimana aplikasi Anda akan berkembang di masa depan. Jika Anda menganggap bahwa kode Anda akan berumur panjang, mengoptimalkan kinerja pada tahap desain juga merupakan ide bagus.

Dalam pengalaman saya, optimasi yang terlambat memberikan imbalan yang sangat sedikit dengan harga tinggi. Mengoptimalkan pada tahap desain, melalui pemilihan algoritma dan penyesuaian, adalah cara yang lebih baik. Bergantung pada profiler untuk memahami cara kerja kode Anda bukan cara yang bagus untuk mendapatkan kode kinerja tinggi, Anda harus mengetahuinya sebelumnya.

Shane MacLaughlin
sumber
Ini tentu saja benar. Saya kira optimasi prematur adalah ketika kode dibuat lebih kompleks / sulit dipahami untuk keuntungan yang tidak jelas, dengan cara yang hanya berdampak lokal (desain memiliki dampak global).
Paul de Vrieze
2
Ini semua tentang definisi. Saya mengambil optimasi sebagai merancang dan menulis kode untuk tampil secara optimal. Sebagian besar di sini tampaknya menganggapnya sebagai peretasan dengan kode begitu mereka menemukan itu tidak cukup cepat atau efisien. Saya menghabiskan banyak waktu untuk mengoptimalkan, biasanya selama desain.
3
Optimalkan desain di awal, Optimalkan kode di akhir.
BCS
Anda cukup benar dalam kasus Anda, tetapi bagi sebagian besar programmer, mereka percaya mereka akan memukul masalah kinerja, tetapi pada kenyataannya mereka tidak akan pernah melakukannya. Banyak yang khawatir tentang kinerja ketika berhadapan dengan 1000 entitas, ketika tes dasar pada data akan menunjukkan bahwa kinerja baik-baik saja hingga mencapai 10.00000 entitas.
Toby Allen
1
"Perencanaan untuk kinerja optimal pada tahap desain jauh lebih unggul daripada optimasi akhir dari desain yang lemah" dan "optimasi akhir memberikan imbalan yang sedikit dengan harga tinggi" dengan sangat baik! Mungkin tidak benar untuk 97% dari semua sistem yang diproduksi, tetapi itu untuk banyak - membingungkan banyak - sistem.
Olof Forshell
10

Sebenarnya saya mengetahui bahwa non-optimasi dini lebih sering menjadi akar dari semua kejahatan.

Ketika orang menulis perangkat lunak pada awalnya akan mengalami masalah, seperti ketidakstabilan, fitur terbatas, kegunaan yang buruk dan kinerja yang buruk. Semua ini biasanya diperbaiki, ketika perangkat lunak matang.

Semua ini, kecuali kinerja. Sepertinya tidak ada yang peduli dengan kinerja. Alasannya sederhana: jika perangkat lunak crash, seseorang akan memperbaiki bug dan hanya itu, jika fitur hilang, seseorang akan mengimplementasikannya dan selesai, jika perangkat lunak memiliki kinerja buruk itu dalam banyak kasus bukan karena hilang optimasi mikro, tetapi karena desain yang buruk dan tidak ada yang akan menyentuh desain perangkat lunak. PERNAH.

Lihatlah Bochs. Ini sangat lambat. Apakah akan lebih cepat? Mungkin, tetapi hanya dalam kisaran beberapa persen saja. Ini tidak akan pernah mendapatkan kinerja yang sebanding dengan perangkat lunak virtualisasi seperti VMWare atau VBox atau bahkan QEMU. Karena desainnya lambat!

Jika masalah suatu perangkat lunak adalah lambat, maka karena itu SANGAT lambat dan ini hanya dapat diperbaiki dengan meningkatkan kinerja banyak orang. + 10% tidak akan membuat perangkat lunak menjadi cepat cepat. Dan Anda biasanya tidak akan mendapatkan lebih dari 10% dengan optimasi nanti.

Jadi, jika kinerja APA PUN penting untuk perangkat lunak Anda, Anda harus memperhitungkannya sejak awal, saat mendesainnya, alih-alih berpikir "oh ya, ini lambat, tapi kami bisa memperbaikinya nanti". Karena kamu tidak bisa!

Saya tahu itu tidak benar-benar cocok dengan kasus spesifik Anda, tetapi menjawab pertanyaan umum "Apakah optimasi prematur benar-benar akar dari semua kejahatan?" - dengan TIDAK jelas.

Setiap optimasi, seperti fitur apa pun, dll. Harus dirancang dengan hati-hati dan diimplementasikan dengan hati-hati. Dan itu termasuk evaluasi biaya dan manfaat yang tepat. Jangan optimalkan algoritme untuk menyimpan beberapa siklus di sana-sini, saat tidak membuat perolehan kinerja yang terukur.

Sama seperti contoh: Anda dapat meningkatkan kinerja fungsi dengan menggarisbawahi, mungkin menghemat beberapa siklus, tetapi pada saat yang sama Anda mungkin meningkatkan ukuran executable Anda, meningkatkan kemungkinan TLB dan cache misses menghabiskan ribuan siklus atau bahkan operasi paging, yang akan mematikan kinerja sepenuhnya. Jika Anda tidak memahami hal-hal ini, "optimasi" Anda dapat berubah menjadi buruk.

Optimasi bodoh lebih jahat daripada optimasi "prematur", namun keduanya masih lebih baik daripada non-optimasi prematur.

nyamuk
sumber
6

Ada dua masalah dengan PO: pertama, waktu pengembangan digunakan untuk pekerjaan yang tidak penting, yang dapat digunakan untuk menulis lebih banyak fitur atau memperbaiki lebih banyak bug, dan kedua, rasa aman palsu bahwa kode berjalan efisien. PO sering melibatkan pengoptimalan kode yang tidak akan menjadi botol-leher, sementara tidak memperhatikan kode yang akan melakukannya. Bit "prematur" berarti optimasi dilakukan sebelum masalah diidentifikasi menggunakan pengukuran yang tepat.

Jadi pada dasarnya, ya, ini kedengarannya seperti pengoptimalan prematur, tapi saya tidak perlu mundur kecuali memperkenalkan bug - lagipula, sudah dioptimalkan sekarang (!)

Harriyott
sumber
Anda bermaksud mengatakan "menulis lebih banyak tes" daripada "menulis lebih banyak fitur", bukan? :)
Greg Hewgill
1
lebih banyak fitur memerlukan lebih banyak tes :)
workmad3
Eh, ya! Itulah tepatnya yang saya maksud ...
harriyott
2
Kode memperkenalkan kompleksitas lebih lanjut, dan kemungkinan tidak akan digunakan secara universal. Mencadangkannya (dan hal-hal serupa) akan membuat kode tetap bersih.
Paul de Vrieze
3

Saya percaya itulah yang oleh Mike Cohn disebut 'pelapisan emas' kode - yaitu menghabiskan waktu untuk hal-hal yang bisa menyenangkan tetapi tidak perlu.

Dia menyarankan untuk tidak melakukannya.

PS 'Gold-plating' bisa menjadi lonceng-dan-peluit jenis fungsionalitas bijaksana. Ketika Anda melihat kode itu mengambil bentuk optimasi yang tidak perlu, kelas 'masa depan-bukti' dll.

Ilya Kochetov
sumber
2
Saya pikir "pelapisan emas" berbeda dari optimasi. Optimalisasi umumnya semua tentang mencoba untuk mendapatkan kinerja maksimal sementara "pelapisan emas" adalah tentang menambahkan "lonceng dan peluit" (semua fungsi tambahan) yang tidak penting untuk produk tetapi terlihat / terasa keren untuk dilakukan.
Scott Dorman
3

Karena tidak ada masalah dalam memahami kode, maka kasus ini dapat dianggap sebagai pengecualian.

Tetapi secara umum optimasi mengarah pada kode yang kurang dapat dibaca dan kurang dimengerti dan harus diterapkan hanya jika diperlukan. Contoh sederhana - jika Anda tahu bahwa Anda harus mengurutkan hanya beberapa elemen - maka gunakan BubbleSort. Tetapi jika Anda mencurigai bahwa unsur-unsurnya dapat meningkat dan Anda tidak tahu berapa banyak, maka mengoptimalkan dengan QuickSort (misalnya) bukanlah kejahatan, tetapi suatu keharusan. Dan ini harus dipertimbangkan selama desain program.

m_pGladiator
sumber
1
Jangan setuju. Saya akan mengatakan tidak pernah menggunakan semacam gelembung. Quicksort telah menjadi standar de facto dan dipahami dengan baik, dan mudah diimplementasikan sebagai semacam gelembung di semua skenario. Penyebut umum terendah tidak lagi rendah;)
1
Untuk jumlah barang yang sangat sedikit, rekursi yang diperlukan untuk quicksort dapat membuatnya lebih lambat daripada peleburan yang layak ... belum lagi bahwa peleburan lebih cepat dalam skenario terburuk dari quicksort (yaitu quicksorting daftar yang diurutkan)
workmad3
ya, tapi itu hanya contoh bagaimana memilih algoritma untuk kebutuhan yang berbeda;)
Benar, tetapi saya akan memiliki quicksort sebagai jenis default saya. Jika saya pikir bubblesort akan meningkatkan kinerja, ini akan menjadi optimasi, bukan sebaliknya. Saya memilih quicksort sebagai default saya karena dipahami dengan baik dan umumnya lebih baik.
2
Gagasan saya tentang pengurutan default adalah apa pun yang diberikan perpustakaan kepada saya (qsort (), .sort (), (sort ...), apa pun).
David Thornley
3

Saya telah menemukan bahwa masalah dengan optimasi prematur kebanyakan terjadi ketika menulis ulang kode yang ada menjadi lebih cepat. Saya bisa melihat bagaimana mungkin menjadi masalah untuk menulis beberapa optimasi berbelit-belit di tempat pertama, tetapi kebanyakan saya melihat optimasi prematur membesarkan kepala jelek dalam memperbaiki apa yang tidak (diketahui) rusak.

Dan contoh terburuk dari ini adalah setiap kali saya melihat seseorang menerapkan kembali fitur dari perpustakaan standar. Itu adalah bendera merah utama. Seperti, saya pernah melihat seseorang menerapkan rutinitas khusus untuk manipulasi string karena dia khawatir bahwa perintah bawaan terlalu lambat.

Ini menghasilkan kode yang lebih sulit untuk dipahami (buruk) dan menghabiskan banyak waktu untuk bekerja yang mungkin tidak berguna (buruk).

jhocking
sumber
3

Dari sudut pandang yang berbeda, ini adalah pengalaman saya bahwa sebagian besar programmer / pengembang tidak berencana untuk sukses dan "prototipe" hampir selalu menjadi Rilis 1.0. Saya memiliki pengalaman langsung dengan 4 produk asli yang terpisah di mana front-end yang berkelas, seksi, dan sangat fungsional (pada dasarnya UI) menghasilkan adopsi dan antusiasme pengguna yang tersebar luas. Di masing-masing produk ini, masalah kinerja mulai merambat dalam waktu yang relatif singkat (1 hingga 2 tahun) terutama ketika pelanggan yang lebih besar dan lebih menuntut, mulai mengadopsi produk. Segera kinerja mendominasi daftar masalah, meskipun pengembangan fitur baru mendominasi daftar prioritas manajemen. Pelanggan menjadi semakin frustrasi ketika setiap rilis menambahkan fitur baru yang terdengar hebat tetapi hampir tidak dapat diakses karena masalah kinerja.

Jadi, desain yang sangat mendasar dan kelemahan implementasi yang kurang atau tidak ada perhatian dalam "tipe proto" menjadi batu sandungan utama untuk kesuksesan jangka panjang dari produk (dan perusahaan).

Demo pelanggan Anda mungkin terlihat dan berkinerja bagus di laptop Anda dengan XML DOM, SQL Express, dan banyak data cache di sisi klien. Sistem produksi mungkin akan menyebabkan crash jika Anda berhasil.

Pada tahun 1976 kami masih memperdebatkan cara optimal menghitung akar kuadrat atau menyortir array besar dan pepatah Don Knuth diarahkan pada kesalahan fokus pada mengoptimalkan semacam itu rutin tingkat rendah di awal proses desain daripada berfokus pada pemecahan masalah. dan kemudian mengoptimalkan wilayah kode yang dilokalkan.

Ketika seseorang mengulangi pepatah sebagai alasan untuk tidak menulis kode efisien (C ++, VB, T-SQL atau lainnya), atau untuk tidak mendesain penyimpanan data dengan benar, atau untuk tidak mempertimbangkan arsitektur kerja bersih, maka IMO mereka hanya menunjukkan pemahaman yang sangat dangkal tentang sifat nyata dari pekerjaan kami. sinar

sinar
sumber
1
Haha, atau ketika demo dengan tiga pengguna menjadi rilis 1.0 dengan seribu.
Olof Forshell
1

Saya kira itu tergantung pada bagaimana Anda mendefinisikan "prematur". Membuat fungsionalitas tingkat rendah dengan cepat ketika Anda menulis tidak secara inheren jahat. Saya pikir itu salah paham dari kutipan. Terkadang saya berpikir bahwa kutipan dapat dilakukan dengan kualifikasi yang lebih banyak. Saya akan mengulangi komentar m_pGladiator tentang keterbacaan.

Dominic Rodger
sumber
1

Jawabannya adalah, tergantung. Saya akan berpendapat bahwa efisiensi adalah masalah besar untuk jenis pekerjaan tertentu, seperti permintaan basis data yang kompleks. Dalam banyak kasus lain, komputer menghabiskan sebagian besar waktunya menunggu input pengguna sehingga mengoptimalkan sebagian besar kode paling hanya merupakan usaha yang sia-sia dan paling buruk kontraproduktif.

Dalam beberapa kasus Anda dapat merancang untuk efisiensi atau kinerja (dirasakan atau nyata) - memilih algoritma yang sesuai atau merancang antarmuka pengguna sehingga operasi mahal tertentu terjadi di latar belakang misalnya. Dalam banyak kasus, pembuatan profil atau operasi lain untuk menentukan hotspot akan memberi Anda manfaat 10/90.

Salah satu contoh yang dapat saya jelaskan adalah model data yang pernah saya lakukan untuk sistem manajemen kasus pengadilan yang memiliki sekitar 560 tabel di dalamnya. Ini mulai dinormalisasi ('dinormalisasi indah' ​​seperti yang dikatakan oleh konsultan dari perusahaan besar-5 tertentu) dan kami hanya perlu memasukkan empat item data yang dinormalisasi di dalamnya:

  • Satu tampilan terwujud untuk mendukung layar pencarian

  • Satu tabel terpicu-dipelihara untuk mendukung layar pencarian lain yang tidak dapat dilakukan dengan tampilan terwujud.

  • Satu tabel pelaporan dinormalisasi (ini hanya ada karena kami harus mengambil beberapa laporan throughput ketika proyek gudang data dikalengkan)

  • Satu tabel terpicu-dipelihara untuk antarmuka yang harus mencari yang paling baru dari sejumlah besar peristiwa yang berbeda dalam sistem.

Ini adalah (pada saat itu) proyek J2EE terbesar di Australasia - lebih dari 100 tahun waktu pengembang - dan memiliki 4 item yang tidak normal dalam skema database, salah satunya tidak benar-benar termasuk di sana.

ConcernedOfTunbridgeWells
sumber
1

Optimalisasi prematur bukanlah akar dari SEMUA kejahatan, itu sudah pasti. Namun ada beberapa kelemahannya:

  • Anda menginvestasikan lebih banyak waktu selama pengembangan
  • Anda berinvestasi lebih banyak waktu untuk mengujinya
  • Anda menginvestasikan lebih banyak waktu untuk memperbaiki bug yang tidak akan ada di sana

Alih-alih optimasi prematur, orang dapat melakukan tes visibilitas awal, untuk melihat apakah ada kebutuhan aktual untuk optimasi yang lebih baik.

Herr_Alien
sumber
1

Sebagian besar dari mereka yang mematuhi "PMO" (kutipan parsial, yaitu) mengatakan bahwa optimisasi harus didasarkan pada pengukuran dan pengukuran tidak dapat dilakukan sampai pada akhir.

Ini juga pengalaman saya dari pengembangan sistem besar bahwa pengujian kinerja dilakukan pada akhir, karena pengembangan hampir selesai.

Jika kita mengikuti "nasihat" orang-orang ini, semua sistem akan sangat lambat. Mereka akan menjadi mahal juga karena kebutuhan perangkat keras mereka jauh lebih besar daripada yang dibayangkan semula.

Saya telah lama menganjurkan melakukan tes kinerja pada interval reguler dalam proses pengembangan: ini akan menunjukkan keberadaan kode baru (di mana sebelumnya tidak ada) dan keadaan kode yang ada.

  • Kinerja kode yang baru diimplementasikan dapat dibandingkan dengan yang ada, kode serupa. "Rasa" untuk kinerja kode baru akan terbentuk seiring waktu.
  • Jika kode yang ada tiba-tiba menjadi rusak, Anda memahami bahwa sesuatu telah terjadi padanya dan Anda dapat segera menyelidikinya, tidak (nanti) ketika itu mempengaruhi keseluruhan sistem.

Gagasan hewan peliharaan lainnya adalah menginstruksikan perangkat lunak pada level blok fungsi. Saat sistem dijalankan, ia mengumpulkan informasi tentang waktu eksekusi untuk blok fungsi. Ketika pemutakhiran sistem dilakukan, dapat ditentukan blok fungsi apa yang dilakukan seperti yang mereka lakukan pada rilis sebelumnya dan yang telah memburuk. Pada layar perangkat lunak, data kinerja dapat diakses dari menu bantuan.

Lihatlah bagian luar biasa ini tentang apa yang PMO mungkin atau tidak mungkin maksudkan.

Olof Forshell
sumber