Semua orang mengatakan bahwa saya harus membuat kode saya modular, tetapi bukankah kurang efisien jika saya menggunakan lebih banyak pemanggilan metode daripada metode yang lebih sedikit, tetapi lebih besar? Apa perbedaan dalam Java, C, atau C ++ dalam hal ini?
Saya mendapatkan bahwa lebih mudah untuk mengedit, membaca, dan memahami, terutama dalam sebuah grup. Jadi, apakah kerugian waktu komputasi tidak signifikan dibandingkan dengan manfaat kerapian kode?
java
c++
c
efficiency
fatsokol
sumber
sumber
Jawaban:
Ya, itu tidak relevan.
Komputer adalah mesin eksekusi yang hampir tak kenal lelah, hampir sempurna yang bekerja pada kecepatan yang sama sekali tidak dapat dibandingkan dengan otak. Meskipun ada jumlah waktu yang dapat diukur yang ditambahkan oleh fungsi panggil ke waktu eksekusi suatu program, ini tidak ada artinya dibandingkan dengan waktu tambahan yang dibutuhkan oleh otak orang berikutnya yang terlibat dengan kode ketika mereka harus mengurai rutinitas yang tidak dapat dibaca. untuk bahkan mulai memahami cara bekerja dengannya. Anda dapat mencoba perhitungan untuk lelucon - asumsikan bahwa kode Anda harus dipertahankan hanya sekali , dan itu hanya menambah setengah jam dari waktu yang dibutuhkan seseorang untuk menerima kode tersebut. Ambil kecepatan jam prosesor Anda dan hitung: berapa kali kode harus dijalankan bahkan untuk mimpi mengimbangi itu?
Singkatnya, kasihan pada CPU sepenuhnya, benar-benar sesat 99,99% dari waktu. Untuk sisa kasus yang jarang terjadi, gunakan profiler. Apakah tidak berasumsi bahwa Anda dapat melihat kasus-kasus - Anda tidak bisa.
sumber
Tergantung.
Dalam dunia yang sangat lambat yaitu pemrograman Web, di mana segala sesuatu terjadi pada kecepatan manusia, pemrograman metode-berat, di mana biaya pemanggilan metode sebanding dengan atau melebihi biaya pemrosesan yang dilakukan oleh metode, mungkin tidak masalah .
Dalam dunia pemrograman sistem tertanam dan penangan interupsi untuk interupsi tingkat tinggi, itu tentu saja penting. Dalam lingkungan itu, model biasa "akses memori murah" dan "prosesornya sangat cepat" mogok. Saya telah melihat apa yang terjadi ketika seorang programmer berorientasi objek mainframe menulis penangan interrupt tingkat tinggi pertamanya. Itu tidak cantik.
Beberapa tahun yang lalu, saya melakukan pewarnaan gumpalan konektivitas 8 arah non-rekursif pada citra FLIR waktu-nyata, yang pada waktu itu merupakan prosesor yang baik. Upaya pertama menggunakan panggilan subrutin, dan panggilan subrutin memakan prosesor hidup-hidup. (4 panggilan PER PIXEL x 64K piksel per frame x 30 frame per detik = Anda mengetahuinya). Upaya kedua mengubah subrutin menjadi makro C, tanpa kehilangan keterbacaan, dan semuanya mawar.
Anda harus melihat KERAS pada apa yang Anda lakukan dan pada lingkungan di mana Anda akan melakukannya.
sumber
Pertama-tama: Program dalam bahasa yang lebih tinggi adalah untuk dibaca oleh manusia bukan oleh mesin.
Jadi, tuliskan programnya sehingga Anda memahaminya. Jangan berpikir tentang kinerja (jika Anda memiliki masalah kinerja serius maka profil aplikasi Anda dan tingkatkan kinerja di mana diperlukan).
Bahkan jika memang benar bahwa memanggil suatu metode atau fungsi membutuhkan beberapa overhead, ini tidak masalah. Kompiler hari ini harus dapat mengkompilasi kode Anda ke dalam bahasa mesin yang efisien sehingga kode yang dihasilkan efisien untuk arsitektur target. Gunakan sakelar optimisasi kompiler Anda untuk mendapatkan kode yang efisien.
sumber
Biasanya ketika Anda akan memiliki fungsi besar dan Anda membaginya menjadi banyak yang lebih kecil, yang lebih kecil ini akan digarisbawahi karena satu-satunya downside inlining (mengulangi instruksi yang sama terlalu banyak) tidak relevan dalam kasus ini. Itu berarti kode Anda akan bertindak seolah-olah Anda telah menulis satu fungsi besar.
Jika mereka tidak diuraikan karena alasan tertentu dan ini menjadi masalah kinerja, maka Anda harus mempertimbangkan inlining manual. Tidak semua aplikasi adalah formulir CRUD jaringan dengan latensi intrinsik yang besar.
sumber
Mungkin tidak ada biaya perhitungan. Biasanya kompiler / JIT selama 10-20 tahun terakhir atau lebih berkaitan dengan fungsi inlining dengan sangat baik. Untuk C / C ++ biasanya terbatas pada fungsi 'inlinable' (yaitu definisi fungsi tersedia untuk kompiler selama kompilasi - yaitu di header file yang sama) tetapi teknik KPP saat ini mengatasinya.
Jika Anda harus menghabiskan waktu untuk optimasi tergantung pada area yang sedang Anda kerjakan. Jika Anda berurusan dengan aplikasi 'normal' yang menghabiskan sebagian besar waktu menunggu input - mungkin Anda tidak perlu khawatir tentang optimasi kecuali aplikasi 'terasa' lambat.
Bahkan dalam kasus seperti itu Anda harus berkonsentrasi pada banyak hal sebelum melakukan optimasi mikro:
O(n)
menjadiO(log n)
memiliki dampak yang jauh lebih besar daripada apa pun yang dapat Anda capai dengan optimasi mikro.List
saat Anda membutuhkanHashSet
sehingga Anda memilikiO(n)
pencarian saat Anda bisa melakukannyaO(1)
.Bahkan jika Anda memutuskan bahwa Anda perlu untuk melakukan mikro-optimasi (yang secara praktis berarti bahwa perangkat lunak Anda digunakan dalam HPC, tertanam atau hanya digunakan oleh sangat banyak orang - jika biaya tambahan pemeliharaan mengatasi biaya waktu komputer) Anda perlu untuk mengidentifikasi hotspot (kernel) yang ingin Anda percepat. Tapi Anda mungkin harus:
Sebagai ucapan terakhir. Biasanya satu-satunya masalah yang Anda miliki dengan pemanggilan metode adalah lompatan tidak langsung (metode virtual) yang tidak diprediksi oleh prediktor cabang (sayangnya lompatan tidak langsung adalah kasus yang sulit untuk itu). Namun:
sumber
Jawaban saya mungkin tidak akan berkembang terlalu luas pada jawaban yang ada, tetapi saya merasa bahwa dua sen saya mungkin membantu.
Pertama; ya, untuk modularitas, Anda biasanya memberikan beberapa tingkat waktu eksekusi. Menulis segala sesuatu dalam kode rakitan akan memberi Anda kecepatan terbaik. Yang mengatakan ...
Anda kenal YouTube? Kemungkinan situs dengan bandwidth paling tinggi yang ada, atau yang kedua setelah Netflix? Mereka menulis sebagian besar kode mereka dalam Python, yang merupakan bahasa yang sangat modular tidak cukup dibangun untuk kinerja terbaik.
Masalahnya adalah, ketika ada sesuatu yang salah, dan pengguna mengeluh tentang memuat video lambat, tidak ada banyak skenario di mana kelambatan itu pada akhirnya akan dikaitkan dengan lambatnya kecepatan eksekusi Python. Namun, kompilasi ulang Python yang cepat, dan kemampuan modularnya untuk mencoba hal-hal baru tanpa pengecekan tipe mungkin akan memungkinkan para insinyur untuk men-debug apa yang salah dengan cukup cepat ("Wow. Magang baru kami menulis sebuah loop yang melakukan sub-query SQL baru untuk hasil SETIAP. ") atau (" Oh, Firefox telah mencabut format header caching yang lama; dan mereka membuat perpustakaan Python untuk mengatur yang baru dengan mudah ")
Dalam hal itu, bahkan dalam hal waktu eksekusi, bahasa modular dapat dianggap lebih cepat karena setelah Anda menemukan apa yang menjadi hambatan Anda, itu akan menjadi lebih mudah untuk mengatur ulang kode Anda untuk membuatnya bekerja dengan cara terbaik. Begitu banyak insinyur akan memberi tahu Anda bahwa kinerja yang hebat tidak berada di tempat yang mereka kira (dan sebenarnya hal-hal yang mereka optimalkan hampir tidak diperlukan; atau, bahkan tidak bekerja seperti yang mereka harapkan!)
sumber
Iya dan tidak. Seperti yang telah dicatat program lain untuk keterbacaan pertama, kemudian untuk efisiensi. Namun, ada praktik standar yang dapat dibaca dan juga efisiensi. Sebagian besar kode dijalankan agak jarang, dan Anda tidak akan mendapatkan banyak keuntungan dari mengoptimalkannya.
Java bisa sebaris panggilan fungsi yang lebih kecil, jadi ada sedikit alasan untuk menghindari menulis fungsi. Pengoptimal cenderung bekerja lebih baik dengan kode yang lebih mudah dibaca. Ada penelitian yang menunjukkan cara pintas yang secara teoritis harus berjalan lebih cepat, sebenarnya membutuhkan waktu lebih lama. Kompiler JIT cenderung bekerja lebih baik kode lebih kecil dan potongan yang sering dijalankan dapat diidentifikasi dan dioptimalkan. Saya belum mencobanya tetapi saya akan mengharapkan satu fungsi besar yang relatif jarang dipanggil untuk tidak dikompilasi.
Ini mungkin tidak berlaku untuk Java, tetapi satu studi menemukan fungsi yang lebih besar benar-benar berjalan lebih lambat karena memerlukan model referensi memori yang berbeda. Ini khusus perangkat keras dan pengoptimal. Untuk modul yang lebih kecil digunakan instruksi yang berfungsi dalam halaman memori. Ini lebih cepat dan lebih kecil dari instruksi yang diperlukan ketika fungsi tidak sesuai dengan halaman.
Ada beberapa kasus di mana ada baiknya untuk mengoptimalkan kode, tetapi umumnya Anda perlu profil kode untuk menentukan di mana itu. Saya sering menemukan itu bukan kode yang saya harapkan.
sumber