Tidak, tapi ya, tapi mungkin, tapi mungkin sebaliknya, tapi tidak.
Seperti yang telah ditunjukkan orang, (dengan asumsi bahasa di mana penambahan adalah asosiatif-kiri, seperti C, C ++, C # atau Java) ekspresi ((1 + 2) + 3)
tersebut persis sama dengan 1 + 2 + 3
. Mereka berbeda cara menulis sesuatu dalam kode sumber, yang akan memiliki efek nol pada kode mesin atau kode byte yang dihasilkan.
Apa pun hasilnya, ini akan menjadi instruksi untuk mis. Menambah dua register dan kemudian menambahkan yang ketiga, atau mengambil dua nilai dari tumpukan, menambahkannya, mendorongnya kembali, lalu mengambilnya dan yang lain dan menambahkannya, atau menambahkan tiga register di operasi tunggal, atau cara lain untuk menjumlahkan tiga angka tergantung pada apa yang paling masuk akal di tingkat berikutnya (kode mesin atau kode byte). Dalam kasus kode byte, yang pada gilirannya kemungkinan akan mengalami penataan ulang yang serupa di dalam hal itu misalnya IL yang setara dengan ini (yang akan menjadi serangkaian beban ke tumpukan, dan pasangan popping untuk menambah dan kemudian mendorong kembali hasilnya) tidak akan menghasilkan salinan langsung dari logika itu di tingkat kode mesin, tetapi sesuatu yang lebih masuk akal untuk mesin yang bersangkutan.
Tetapi ada sesuatu yang lebih dari pertanyaan Anda.
Dalam hal setiap kompiler C, C ++, Java, atau C # yang waras, saya mengharapkan hasil dari kedua pernyataan yang Anda berikan memiliki hasil yang sama persis seperti:
int a = 6;
Mengapa kode yang dihasilkan harus membuang waktu mengerjakan matematika pada literal? Tidak ada perubahan pada keadaan program akan berhenti hasilnya dari 1 + 2 + 3
menjadi 6
, sehingga ini apa yang harus pergi dalam kode dieksekusi. Memang, mungkin bahkan tidak itu (tergantung pada apa yang Anda lakukan dengan 6 itu, mungkin kita bisa membuang semuanya; dan bahkan C # dengan filosofi itu "jangan mengoptimalkan, karena jitter akan mengoptimalkan ini pula" akan menghasilkan sama int a = 6
atau hanya membuang semuanya sebagai tidak perlu).
Namun ini menuntun kami ke kemungkinan perpanjangan pertanyaan Anda. Pertimbangkan yang berikut ini:
int a = (b - 2) / 2;
/* or */
int a = (b / 2)--;
dan
int c;
if(d < 100)
c = 0;
else
c = d * 31;
/* or */
int c = d < 100 ? 0 : d * 32 - d
/* or */
int c = d < 100 && d * 32 - d;
/* or */
int c = (d < 100) * (d * 32 - d);
(Catatan, dua contoh terakhir ini tidak valid C #, sedangkan yang lainnya di sini adalah, dan mereka valid dalam C, C ++ dan Java.)
Di sini sekali lagi kita memiliki kode yang sama persis dalam hal output. Karena mereka bukan ekspresi konstan, mereka tidak akan dihitung pada waktu kompilasi. Mungkin satu bentuk lebih cepat dari yang lain. Mana yang lebih cepat? Itu akan tergantung pada prosesor dan mungkin pada beberapa perbedaan yang agak sewenang-wenang dalam keadaan (terutama karena jika seseorang lebih cepat, itu tidak akan jauh lebih cepat).
Dan mereka tidak sepenuhnya tidak terkait dengan pertanyaan Anda, karena kebanyakan tentang perbedaan dalam urutan di mana sesuatu dilakukan secara konseptual .
Di masing-masing dari mereka, ada alasan untuk curiga bahwa satu mungkin lebih cepat daripada yang lain. Dekremen tunggal mungkin memiliki instruksi khusus, jadi (b / 2)--
memang bisa lebih cepat daripada (b - 2) / 2
. d * 32
mungkin bisa diproduksi lebih cepat dengan mengubahnya d << 5
jadi membuat d * 32 - d
lebih cepat daripada d * 31
. Perbedaan antara dua yang terakhir sangat menarik; satu memungkinkan beberapa pemrosesan dilewati dalam beberapa kasus, tetapi yang lain menghindari kemungkinan salah prediksi cabang.
Jadi, ini meninggalkan kita dengan dua pertanyaan: 1. Apakah satu sebenarnya lebih cepat dari yang lain? 2. Apakah kompiler akan mengkonversi lebih lambat menjadi lebih cepat?
Dan jawabannya adalah 1. Tergantung. 2. Mungkin.
Atau untuk memperluas, itu tergantung karena itu tergantung pada prosesor yang bersangkutan. Tentu saja ada prosesor di mana setara kode mesin naif dari satu akan lebih cepat daripada kode mesin naif yang setara dengan yang lain. Selama sejarah komputasi elektronik, tidak ada satu yang selalu lebih cepat, baik (elemen mis-prediksi cabang khususnya tidak relevan bagi banyak ketika CPU non-pipa lebih umum).
Dan mungkin, karena ada banyak optimisasi berbeda yang dilakukan oleh kompiler (dan kegugupan, dan mesin skrip), dan sementara beberapa mungkin diamanatkan dalam kasus-kasus tertentu, umumnya kita akan dapat menemukan beberapa bagian dari kode yang secara logis setara yang bahkan kompiler yang paling naif memiliki hasil yang persis sama dan beberapa bagian dari kode yang setara secara logis di mana bahkan yang paling canggih menghasilkan kode yang lebih cepat untuk satu daripada yang lain (bahkan jika kita harus menulis sesuatu yang benar-benar patologis hanya untuk membuktikan maksud kita).
Ini mungkin tampak seperti masalah optimasi yang sangat kecil,
Tidak. Bahkan dengan perbedaan yang lebih rumit daripada yang saya berikan di sini, sepertinya masalah kecil sekali yang tidak ada hubungannya dengan optimasi. Jika ada, itu masalah pesimisasi karena Anda curiga semakin sulit dibaca ((1 + 2) + 3
bisa lebih lambat daripada lebih mudah dibaca 1 + 2 + 3
.
tetapi memilih C ++ daripada C # / Java / ... adalah semua tentang optimasi (IMHO).
Jika itu yang benar-benar memilih C ++ daripada C # atau Java adalah "semua tentang" Saya akan mengatakan orang harus membakar salinan Stroustrup dan ISO / IEC 14882 mereka dan membebaskan ruang kompiler C ++ mereka untuk meninggalkan ruang untuk lebih banyak MP3 atau sesuatu.
Bahasa-bahasa ini memiliki keunggulan yang berbeda satu sama lain.
Salah satunya adalah bahwa C ++ umumnya masih lebih cepat dan lebih ringan pada penggunaan memori. Ya, ada contoh di mana C # dan / atau Java lebih cepat dan / atau memiliki penggunaan memori aplikasi yang lebih baik seumur hidup, dan ini menjadi lebih umum karena teknologi yang terlibat meningkat, tetapi kita masih bisa mengharapkan program rata-rata yang ditulis dalam C ++ menjadi dieksekusi lebih kecil yang melakukan tugasnya lebih cepat dan menggunakan lebih sedikit memori daripada yang setara di salah satu dari kedua bahasa.
Ini bukan optimasi.
Optimalisasi kadang-kadang berarti "membuat segalanya berjalan lebih cepat". Ini bisa dimengerti, karena sering kali ketika kita benar-benar berbicara tentang "optimasi" kita memang berbicara tentang membuat segalanya berjalan lebih cepat, dan karena itu seseorang telah menjadi singkatan untuk yang lain dan saya akui saya menyalahgunakan kata itu dengan cara saya sendiri.
Kata yang benar untuk "membuat segalanya berjalan lebih cepat" bukanlah pengoptimalan . Kata yang benar di sini adalah peningkatan . Jika Anda membuat perubahan pada suatu program dan satu-satunya perbedaan yang berarti adalah sekarang lebih cepat, tidak dioptimalkan dengan cara apa pun, itu hanya lebih baik.
Optimalisasi adalah ketika kami melakukan peningkatan dalam hal aspek tertentu dan / atau kasus tertentu. Contoh umum adalah:
- Sekarang lebih cepat untuk satu use case, tetapi lebih lambat untuk yang lain.
- Sekarang lebih cepat, tetapi menggunakan lebih banyak memori.
- Sekarang lebih ringan di memori, tetapi lebih lambat.
- Sekarang lebih cepat, tetapi lebih sulit untuk dipertahankan.
- Sekarang lebih mudah dirawat, tetapi lebih lambat.
Kasus-kasus seperti itu akan dibenarkan jika, misalnya:
- Kasus penggunaan yang lebih cepat lebih umum atau lebih parah terhambat untuk memulai.
- Program ini sangat lambat, dan kami memiliki banyak RAM gratis.
- Program ini terhenti karena menggunakan begitu banyak RAM sehingga menghabiskan lebih banyak waktu bertukar daripada menjalankan pemrosesan super cepat.
- Program ini sangat lambat, dan kode yang sulit dipahami didokumentasikan dengan baik dan relatif stabil.
- Program ini masih dapat diterima dengan cepat, dan basis kode yang lebih mudah dipahami lebih murah untuk dipelihara dan memungkinkan perbaikan lainnya agar lebih mudah dilakukan.
Tapi, kasus-kasus seperti itu juga tidak akan dibenarkan dalam skenario lain: Kode belum dibuat lebih baik oleh ukuran kualitas mutlak mutlak, itu dibuat lebih baik dalam hal tertentu yang membuatnya lebih cocok untuk penggunaan tertentu; dioptimalkan.
Dan pilihan bahasa memang berpengaruh di sini, karena kecepatan, penggunaan memori, dan keterbacaan semua dapat dipengaruhi olehnya, tetapi juga kompatibilitas dengan sistem lain, ketersediaan perpustakaan, ketersediaan runtime, kematangan runtime tersebut pada sistem operasi yang diberikan (untuk dosa-dosa saya, saya entah bagaimana akhirnya memiliki Linux dan Android sebagai OS favorit saya dan C # sebagai bahasa favorit saya, dan sementara Mono hebat, tetapi saya masih menghadapi yang ini sedikit).
Mengatakan "memilih C ++ daripada C # / Java / ... adalah semua tentang optimasi" hanya masuk akal jika Anda berpikir C ++ benar-benar menyebalkan, karena optimasi adalah tentang "lebih baik meskipun ..." tidak "lebih baik". Jika Anda berpikir C ++ lebih baik dari itu sendiri, maka hal terakhir yang Anda butuhkan adalah khawatir tentang kemungkinan kecil memilih mikro-opts. Memang, Anda mungkin lebih baik meninggalkannya sama sekali; hacker senang adalah kualitas untuk dioptimalkan juga!
Namun, jika Anda cenderung mengatakan "Saya suka C ++, dan salah satu hal yang saya sukai adalah memeras siklus tambahan", maka itu masalah yang berbeda. Itu masih merupakan kasus bahwa mikro-opts hanya layak jika mereka dapat menjadi kebiasaan refleksif (yaitu, cara Anda cenderung untuk kode secara alami akan lebih cepat lebih sering daripada lambat). Kalau tidak, mereka bahkan bukan optimasi prematur, mereka pesimis prematur yang hanya memperburuk keadaan.