Kita semua tahu bahwa optimasi prematur adalah akar dari semua kejahatan karena mengarah pada kode yang tidak dapat dibaca / tidak dapat dipelihara. Yang lebih buruk adalah pesimisasi, ketika seseorang mengimplementasikan "optimisasi" karena mereka pikir itu akan lebih cepat, tetapi akhirnya menjadi lebih lambat, serta menjadi buggy, tidak dapat dipelihara, dll. Apa contoh paling konyol dari hal ini yang pernah Anda lihat ?
performance
optimization
dsimcha
sumber
sumber
Jawaban:
Pada proyek lama kami mewarisi beberapa programmer sistem embedded (jika tidak unggul) yang memiliki pengalaman Z-8000 yang masif.
Lingkungan baru kami adalah Solaris 32-bit.
Salah satu dari mereka pergi dan mengubah semua int menjadi celana pendek untuk mempercepat kode kami, karena mengambil 16 bit dari RAM lebih cepat daripada mengambil 32 bit.
Saya harus menulis program demo untuk menunjukkan bahwa mengambil nilai 32-bit pada sistem 32-bit lebih cepat daripada mengambil nilai 16-bit, dan menjelaskan bahwa untuk mengambil nilai 16-bit, CPU harus membuat lebar 32-bit akses memori dan kemudian tutup atau geser bit yang tidak diperlukan untuk nilai 16-bit.
sumber
Saya pikir ungkapan "optimisasi prematur adalah akar dari semua kejahatan" adalah cara, cara yang terlalu sering digunakan. Bagi banyak proyek, menjadi alasan untuk tidak mempertimbangkan kinerja sampai terlambat dalam suatu proyek.
Ungkapan ini seringkali merupakan penopang bagi orang untuk menghindari pekerjaan. Saya melihat frasa ini digunakan ketika orang harus benar-benar mengatakan "Wah, kami benar-benar tidak memikirkan itu di muka dan tidak punya waktu untuk menghadapinya sekarang".
Saya telah melihat lebih banyak contoh "konyol" masalah kinerja bodoh daripada contoh masalah yang diperkenalkan karena "pesimisasi"
Apa yang saya pikir adalah pernyataan yang lebih baik adalah ini: "optimasi tanpa mengukur dan memahami bukan optimasi sama sekali - hanya perubahan acak".
Kinerja yang baik adalah pekerjaan yang memakan waktu - seringkali lebih untuk pengembangan fitur atau komponen itu sendiri.
sumber
Basis data adalah pesimisasi playland.
Favorit meliputi:
Itu di atas kepala saya.
sumber
Saya pikir tidak ada aturan mutlak: beberapa hal yang terbaik dioptimalkan dimuka, dan beberapa tidak.
Misalnya, saya bekerja di perusahaan tempat kami menerima paket data dari satelit. Setiap paket menghabiskan banyak uang, sehingga semua data sangat dioptimalkan (mis. Dikemas). Misalnya, lintang / bujur tidak dikirim sebagai nilai absolut (mengapung), tetapi sebagai offset relatif terhadap sudut "barat laut" dari zona "saat ini". Kami harus membongkar semua data sebelum dapat digunakan. Tapi saya pikir ini bukan pesimisasi, ini adalah optimasi cerdas untuk mengurangi biaya komunikasi.
Di sisi lain, arsitek perangkat lunak kami memutuskan bahwa data yang tidak dibongkar harus diformat menjadi dokumen XML yang sangat mudah dibaca, dan disimpan dalam basis data kami (sebagai lawan setiap bidang disimpan dalam kolom yang sesuai). Gagasan mereka adalah "XML adalah masa depan", "ruang disk murah", dan "prosesor murah", jadi tidak perlu mengoptimalkan apa pun. Hasilnya adalah bahwa paket 16-byte kami diubah menjadi dokumen 2kB yang disimpan dalam satu kolom, dan bahkan untuk pertanyaan sederhana kami harus memuat megabyte dokumen XML dalam memori! Kami menerima lebih dari 50 paket per detik, sehingga Anda dapat membayangkan betapa mengerikannya kinerja (BTW, perusahaan bangkrut).
Jadi sekali lagi, tidak ada aturan absolut. Ya, terkadang optimasi terlalu dini adalah kesalahan. Tapi terkadang motto "cpu / disk space / memory is cheap" adalah akar sebenarnya dari semua kejahatan.
sumber
Ya Tuhan, kurasa aku telah melihat semuanya. Lebih sering daripada tidak itu merupakan upaya untuk memperbaiki masalah kinerja oleh seseorang yang terlalu malas untuk memecahkan masalah mereka hingga PENYEBAB masalah kinerja tersebut atau bahkan meneliti apakah sebenarnya ada masalah kinerja. Dalam banyak kasus ini saya bertanya-tanya apakah itu bukan hanya kasus orang yang ingin mencoba teknologi tertentu dan mati-matian mencari paku yang sesuai dengan palu baru mereka yang mengkilap.
Berikut ini contoh terbaru:
Arsitek data datang kepada saya dengan proposal yang rumit untuk mempartisi tabel kunci secara vertikal dalam aplikasi yang cukup besar dan kompleks. Dia ingin tahu jenis upaya pengembangan apa yang diperlukan untuk menyesuaikan perubahan. Percakapan berlangsung seperti ini:
Saya: Mengapa Anda mempertimbangkan ini? Apa masalah yang Anda coba selesaikan?
Dia: Tabel X terlalu luas, kami mempartisi untuk alasan kinerja.
Aku: Apa yang membuatmu berpikir itu terlalu lebar?
Dia: Konsultan mengatakan terlalu banyak kolom dalam satu tabel.
Saya: Dan ini mempengaruhi kinerja?
Dia: Ya, pengguna telah melaporkan pelambatan berselang di modul XYZ aplikasi.
Saya: Bagaimana Anda tahu lebar tabel adalah sumber masalahnya?
Dia: Itu adalah tabel kunci yang digunakan oleh modul XYZ, dan itu seperti 200 kolom. Itu pasti masalahnya.
Saya (Menjelaskan): Tetapi modul XYZ secara khusus menggunakan sebagian besar kolom dalam tabel itu, dan kolom yang digunakannya tidak dapat diprediksi karena pengguna mengonfigurasi aplikasi untuk menampilkan data yang ingin ditampilkan dari tabel itu. Sangat mungkin bahwa 95% dari waktu kita akhirnya bergabung dengan semua tabel kembali bersama yang akan merusak kinerja.
Dia: Konsultan mengatakan itu terlalu luas dan kita perlu mengubahnya.
Saya: Siapa konsultan ini? Saya tidak tahu kami menyewa konsultan, juga tidak berbicara dengan tim pengembang.
Dia: Yah, kita belum mempekerjakan mereka. Ini adalah bagian dari proposal yang mereka tawarkan, tetapi mereka bersikeras kami perlu merancang kembali database ini.
Saya: Uh huh. Jadi konsultan yang menjual jasa desain ulang basis data berpikir kita memerlukan desain ulang ...
Percakapan terus berlanjut seperti ini. Setelah itu, saya melihat lagi tabel yang dimaksud dan memutuskan bahwa itu mungkin bisa dipersempit dengan normalisasi sederhana tanpa perlu strategi partisi yang eksotis. Ini, tentu saja ternyata menjadi titik diperdebatkan setelah saya menyelidiki masalah kinerja (sebelumnya tidak dilaporkan) dan melacaknya ke dua faktor:
Tentu saja arsitek masih mendorong partisi vertikal dari tabel yang bergantung pada meta-masalah "terlalu lebar". Dia bahkan memperkuat kasusnya dengan mendapatkan proposal dari konsultan basis data lain yang dapat menentukan bahwa kami memerlukan perubahan desain besar pada basis data tanpa melihat aplikasi atau menjalankan analisis kinerja.
sumber
Saya telah melihat orang menggunakan alphadrive-7 untuk benar-benar menetaskan CHX-LT. Ini adalah praktik yang tidak biasa. Praktek yang lebih umum adalah menginisialisasi transformator ZT sehingga bufferication berkurang (karena resistensi overload bersih yang lebih besar) dan membuat bytegraphications gaya java.
Benar-benar pesimis!
sumber
Tidak ada yang Menghancurkan Bumi, saya akui, tetapi saya telah menangkap orang menggunakan StringBuffer untuk menyatukan Strings di luar loop di Jawa. Itu sesuatu yang sederhana seperti berputar
ke
Ini dulunya merupakan praktik yang cukup umum untuk menggunakan teknik dalam satu lingkaran, karena itu terukur lebih cepat. Masalahnya, StringBuffer disinkronkan, jadi sebenarnya ada overhead tambahan jika Anda hanya menggabungkan beberapa Strings. (Belum lagi bahwa perbedaannya sangat sepele pada skala ini.) Dua poin lain tentang praktik ini:
sumber
Saya pernah melihat database MSSQL yang menggunakan tabel 'Root'. Tabel Root memiliki empat kolom: GUID (uniqueidentifier), ID (int), LastModDate (datetime), dan CreateDate (datetime). Semua tabel dalam database adalah Foreign Key'd ke tabel Root. Setiap kali baris baru diciptakan pada setiap tabel di db, Anda harus menggunakan beberapa prosedur tersimpan untuk memasukkan entri di tabel Root sebelum Anda bisa sampai ke tabel aktual yang Anda pedulikan (daripada database yang melakukan pekerjaan untuk Anda dengan beberapa pemicu pemicu sederhana).
Ini menciptakan kekacauan yang tidak sengaja dan sakit kepala yang tidak berguna, diperlukan apa pun yang tertulis di atasnya untuk menggunakan sprocs (dan menghilangkan harapan saya untuk memperkenalkan LINQ ke perusahaan. Itu mungkin tapi tidak sebanding dengan sakit kepala), dan to top it off tidak layak Bahkan tidak mencapai apa yang seharusnya dilakukan.
Pengembang yang memilih jalur ini mempertahankannya dengan asumsi bahwa ini menghemat banyak ruang karena kami sendiri tidak menggunakan Guids di tabel (tapi ... bukankah GUID dibuat di tabel Root untuk setiap baris yang kita buat?) , meningkatkan kinerja, entah bagaimana, dan membuatnya "mudah" untuk mengaudit perubahan pada basis data.
Oh, dan diagram database tampak seperti laba-laba mutan dari neraka.
sumber
Bagaimana dengan POBI - pesimisasi jelas dengan niat?
Collegue milik saya di tahun 90-an bosan ditendang di pantat oleh CEO hanya karena CEO menghabiskan hari pertama dari setiap rilis perangkat lunak ERP (kustom) dengan menempatkan masalah kinerja dalam fungsi-fungsi baru. Bahkan jika fungsi-fungsi baru itu berderak gigabyte dan membuat yang tidak mungkin menjadi mungkin, ia selalu menemukan beberapa detail, atau bahkan masalah yang tampaknya besar, untuk dikeluhkan. Dia diyakini tahu banyak tentang pemrograman dan mendapatkan tendangannya dengan menendang pantat programmer.
Karena sifat kritik yang tidak kompeten (dia adalah CEO, bukan cowok IT), kolega saya tidak pernah berhasil melakukannya dengan benar. Jika Anda tidak memiliki masalah kinerja, Anda tidak dapat menghilangkannya ...
Sampai untuk satu rilis, ia menempatkan banyak panggilan fungsi Delay (200) (itu adalah Delphi) ke dalam kode baru. Butuh hanya 20 menit setelah ditayangkan, dan dia diperintahkan untuk muncul di kantor CEO untuk mengambil penghinaan tertunda secara langsung.
Hanya hal yang tidak biasa sejauh ini adalah kolega saya bisu ketika dia kembali, tersenyum, bercanda, pergi untuk satu atau dua BigMac sementara dia biasanya akan menendang meja, berbicara tentang CEO dan perusahaan, dan menghabiskan sisa hari berubah menjadi mati .
Secara alami, kolega saya sekarang beristirahat selama satu atau dua hari di mejanya, meningkatkan keterampilan membidik di Quake - kemudian pada hari kedua atau ketiga ia menghapus panggilan Penundaan, membangun kembali dan merilis "tambalan darurat" di mana ia menyebarkan berita bahwa dia telah menghabiskan 2 hari dan 1 malam untuk memperbaiki lubang kinerja.
Ini adalah pertama (dan satu-satunya) yang dikatakan CEO jahat "pekerjaan hebat!" untuk dia. Itu yang terpenting, bukan?
Ini adalah POBI asli.
Tapi itu juga semacam optimasi proses sosial, jadi 100% ok.
Kupikir.
sumber
"Kemerdekaan Basis Data". Ini berarti tidak ada procs, pemicu, dll yang tersimpan - bahkan tidak ada kunci asing.
sumber
Penggunaan terbaik StringBuilder yang pernah saya lihat.
sumber
Menggunakan regex untuk membagi string ketika string sederhana.split sudah cukup
sumber
Sangat terlambat untuk utas ini saya tahu, tetapi saya melihat ini baru-baru ini:
Kau tahu, kalau-kalau boolean memiliki beberapa nilai tambahan ...
sumber
Contoh terburuk yang dapat saya pikirkan adalah basis data internal di perusahaan saya yang berisi informasi tentang semua karyawan. Itu mendapat pembaruan setiap malam dari HR dan memiliki layanan web ASP.NET di atas. Banyak aplikasi lain menggunakan layanan web untuk mengisi hal-hal seperti bidang pencarian / dropdown.
Pesimisme adalah bahwa pengembang berpikir bahwa panggilan berulang ke layanan web akan terlalu lambat untuk membuat kueri SQL berulang. Jadi apa yang dia lakukan? Acara mulai aplikasi membaca di seluruh database dan mengonversikan semuanya menjadi objek dalam memori, disimpan tanpa batas waktu hingga kumpulan aplikasi didaur ulang. Kode ini sangat lambat, butuh 15 menit untuk memuat kurang dari 2000 karyawan. Jika Anda secara tidak sengaja mendaur ulang kumpulan aplikasi pada siang hari, itu bisa memakan waktu 30 menit atau lebih, karena setiap permintaan layanan web akan memulai beberapa pemuatan ulang secara bersamaan. Karena alasan ini, karyawan baru tidak akan muncul di basis data pada hari pertama ketika akun mereka dibuat dan karenanya tidak akan dapat mengakses sebagian besar aplikasi internal pada beberapa hari pertama mereka, memutar-mutar ibu jari mereka.
Pesimisme tingkat kedua adalah bahwa manajer pengembangan tidak ingin menyentuhnya karena takut merusak aplikasi yang bergantung, tetapi kami terus mengalami pemadaman aplikasi kritis di seluruh perusahaan secara sporadis karena buruknya desain komponen sederhana tersebut.
sumber
Sepertinya tidak ada yang menyebutkan penyortiran, jadi saya akan melakukannya.
Beberapa waktu yang berbeda, saya telah menemukan bahwa seseorang telah membuat kerajinan tangan peleburan, karena situasinya "tidak memerlukan" panggilan ke algoritma quicksort "terlalu mewah" yang sudah ada. Pengembang puas ketika gelembung buatan tangan mereka bekerja cukup baik pada sepuluh baris data yang mereka gunakan untuk pengujian. Itu tidak berjalan dengan baik setelah pelanggan menambahkan beberapa ribu baris.
sumber
Saya pernah mengerjakan aplikasi yang penuh kode seperti ini:
Cukup menghapus
found
, kembalinull
di akhir, dan mengubah baris keenam menjadi:Menggandakan kinerja aplikasi.
sumber
Saya pernah mencoba mengubah kode yang menyertakan permata ini di kelas Konstanta
Masing-masing digunakan beberapa kali di sisa aplikasi untuk tujuan yang berbeda. COMMA_DELIMINATOR mengotori kode dengan lebih dari 200 penggunaan dalam 8 paket berbeda.
sumber
Yang terbesar sepanjang masa, yang saya temukan berulang kali dalam perangkat lunak internal:
Tidak menggunakan fitur-fitur DBMS karena alasan "portabilitas" karena "kami mungkin ingin beralih ke vendor lain nanti".
Baca bibirku. Untuk pekerjaan in-house apa pun: TIDAK AKAN TERJADI!
sumber
Saya memiliki rekan kerja yang mencoba mengecoh optimisator C compiler dan kode penulisan ulang rutin yang hanya bisa dibaca olehnya. Salah satu trik favoritnya adalah mengubah metode yang dapat dibaca seperti (membuat beberapa kode):
dalam hal ini:
Yaitu, baris pertama dari metode yang pernah dibaca akan menjadi "
return
" dan semua logika lainnya akan diganti dengan ekspresi terniary yang bersarang. Ketika Anda mencoba untuk berdebat tentang bagaimana hal ini tidak dapat dipelihara, ia akan menunjukkan fakta bahwa output perakitan dari metodenya adalah tiga atau empat instruksi perakitan lebih pendek. Itu tidak selalu lebih cepat tetapi selalu kecil sedikit lebih pendek. Ini adalah sistem tertanam di mana penggunaan memori sesekali penting, tetapi ada optimasi yang jauh lebih mudah yang bisa dibuat daripada ini yang akan membuat kode dapat dibaca.Kemudian, setelah ini, untuk beberapa alasan dia memutuskan itu
ptr->structElement
itu terlalu tidak terbaca, jadi dia mulai mengubah semua ini menjadi(*ptr).structElement
teori bahwa itu lebih mudah dibaca dan lebih cepat juga.Mengubah kode yang dapat dibaca menjadi kode yang tidak dapat dibaca untuk paling banyak peningkatan 1%, dan kadang-kadang kode lebih lambat.
sumber
if
. Desakan pada pernyataan atas ekspresi dalam C adalah dogma budaya / agama, bukan praktik objektif apa pun. (Pedoman yang lebih baik: jika terner bersarang terlalu panjang untuk dibaca, Anda tidak boleh menggunakanif
keduanya.)if
fungsi dan menggantinya dengan ternary. Itu bagus, dan seringkali lebih mudah dibaca. Saya sedang berbicara tentang mengganti seluruh metode garis 30+ dengan pernyataan kembali tunggal dan terner bersarang. Tidak ada yang mengira kode baru itu lebih mudah dibaca, tetapi satu pengembang berpikir itu lebih cepat.Dalam salah satu pekerjaan pertama saya sebagai pengembang penuh, saya mengambil alih proyek untuk sebuah program yang mengalami masalah penskalaan. Ini akan bekerja dengan cukup baik pada set data kecil, tetapi akan benar-benar macet ketika diberikan sejumlah besar data.
Ketika saya menggali, saya menemukan bahwa programmer asli berusaha untuk mempercepat dengan memparalelkan analisis - meluncurkan utas baru untuk setiap sumber data tambahan. Namun, dia membuat kesalahan karena semua utas membutuhkan sumber daya bersama, yang semuanya menemui jalan buntu. Tentu saja, semua manfaat konkurensi menghilang. Selain itu crash sebagian besar sistem untuk meluncurkan 100 utas hanya untuk memiliki semua kecuali satu dari mereka mengunci. Mesin dev berdaging saya adalah pengecualian karena mesin itu mengaduk-aduk 150 sumber data dalam waktu sekitar 6 jam.
Jadi untuk memperbaikinya, saya menghapus komponen multi-threading dan membersihkan I / O. Tanpa perubahan lain, waktu eksekusi pada set data sumber 150 turun di bawah 10 menit pada mesin saya, dan dari tak terbatas hingga di bawah setengah jam pada mesin rata-rata perusahaan.
sumber
Saya kira saya bisa menawarkan permata ini:
Karena akar kuadrat dihitung di tempat yang sangat sensitif, saya mendapat tugas mencari cara untuk membuatnya lebih cepat. Refactoring kecil ini mengurangi waktu eksekusi hingga sepertiganya (untuk kombinasi perangkat keras dan kompiler yang digunakan, YMMV):
Tentu saja ada lebih cepat DAN cara yang lebih baik untuk melakukan ini, tapi saya pikir itu adalah contoh pesimisasi yang cukup rapi.
Sunting: Kalau dipikir-pikir, loop terbuka sebenarnya pesimisasi rapi. Menggali melalui kontrol versi, saya dapat menyajikan tahap kedua refactoring juga, yang berkinerja lebih baik daripada yang di atas:
Algoritma ini persis sama, walaupun implementasinya sedikit berbeda, jadi saya kira itu memenuhi syarat.
sumber
isqrt()
menghitungfloor(sqrt())
, tetapi, mengapa kode ini bekerja?Ini mungkin berada pada tingkat yang lebih tinggi dari apa yang Anda kejar, tetapi memperbaikinya (jika diizinkan) juga melibatkan tingkat rasa sakit yang lebih tinggi:
Bersikeras dengan tangan menggulirkan Object Relationship Manager / Data Access Layer alih-alih menggunakan salah satu perpustakaan yang sudah mapan, teruji, dan sudah ada di luar sana (bahkan setelah ditunjukkan kepada Anda).
sumber
Semua batasan kunci asing telah dihapus dari database, karena jika tidak, akan ada begitu banyak kesalahan.
sumber
Ini tidak persis sesuai dengan pertanyaan, tetapi saya akan tetap menyebutkannya sebagai kisah peringatan. Saya sedang mengerjakan aplikasi terdistribusi yang berjalan lambat, dan terbang ke DC untuk duduk di sebuah pertemuan yang utamanya ditujukan untuk menyelesaikan masalah. Pimpinan proyek mulai menguraikan arsitektur ulang yang ditujukan untuk menyelesaikan penundaan. Saya mengajukan diri bahwa saya telah melakukan beberapa pengukuran selama akhir pekan yang mengisolasi kemacetan menjadi satu metode. Ternyata ada catatan yang hilang pada pencarian lokal, menyebabkan aplikasi harus pergi ke server jarak jauh pada setiap transaksi. Dengan menambahkan catatan kembali ke toko lokal, penundaan itu dieliminasi - masalah diselesaikan. Perhatikan bahwa arsitektur ulang tidak akan menyelesaikan masalah.
sumber
Memeriksa sebelum SETIAP operasi javascript apakah objek yang Anda operasikan ada.
Masalah saya dengan kode jenis ini adalah tidak ada yang peduli bagaimana jika itu tidak ada? Tidak melakukan apa-apa? Jangan memberikan umpan balik kepada pengguna?
Saya setuju bahwa
Object expected
kesalahannya mengganggu, tetapi ini bukan solusi terbaik untuk itu.sumber
Bagaimana dengan ekstremisme YAGNI. Ini adalah bentuk pesimisasi dini. Sepertinya kapan saja Anda menerapkan YAGNI, maka Anda akhirnya membutuhkannya, menghasilkan upaya 10 kali untuk menambahkannya daripada jika Anda telah menambahkannya di awal. Jika Anda membuat program yang berhasil maka kemungkinan besar ANDA AKAN MEMBUTUHKANNYA. Jika Anda terbiasa membuat program yang hidupnya habis dengan cepat maka teruslah berlatih YAGNI karena saya kira YAGNI.
sumber
Bukan optimasi yang terlalu dini - tetapi tentu saja salah arah - ini dibaca di situs BBC, dari sebuah artikel yang membahas Windows 7.
Sekarang, saya belum mencoba Windows 7, jadi saya mungkin salah, tapi saya berani bertaruh bahwa ada masalah lain di sana yang lebih penting daripada berapa lama untuk mematikan. Lagi pula, begitu saya melihat pesan 'Shutting down Windows', monitor dimatikan dan saya berjalan pergi - bagaimana manfaatnya 400 milidetik?
sumber
Seseorang di departemen saya pernah menulis kelas string. Antarmuka seperti
CString
, tetapi tanpa ketergantungan Windows.Satu "optimasi" yang mereka lakukan adalah tidak mengalokasikan lebih banyak memori daripada yang diperlukan. Tampaknya tidak menyadari bahwa alasan mengapa kelas suka
std::string
mengalokasikan memori berlebih adalah agar urutan+=
operasi dapat berjalan dalam waktu O (n).Sebagai gantinya, setiap
+=
panggilan tunggal memaksa realokasi, yang mengubah penambahan berulang menjadi algoritma O (n²) Schlemiel the Painter .sumber
Seorang mantan rekan kerja tambang (seorang soab , sebenarnya) ditugaskan untuk membangun modul baru untuk Java ERP kami yang seharusnya mengumpulkan dan menganalisis data pelanggan (industri ritel). Dia memutuskan untuk membagi SETIAP bidang Kalender / Datetime dalam komponennya (detik, menit, jam, hari, bulan, tahun, hari dalam seminggu, bimester, trimester (!)) Karena "bagaimana lagi saya akan meminta 'setiap Senin'?"
sumber
Jangan tersinggung siapa pun, tapi saya baru saja menilai tugas (java) yang punya ini
sumber