Apa pendekatan terbaik untuk pengkodean dalam lingkungan kompilasi yang lambat

15

Saya terbiasa mengkodekan dalam C # dalam gaya TDD - menulis / atau mengubah sejumlah kecil kode, kompilasi ulang dalam 10 detik seluruh solusi, jalankan kembali tes dan lagi. Mudah...

Metodologi pengembangan itu bekerja sangat baik bagi saya selama beberapa tahun, sampai tahun lalu ketika saya harus kembali ke pengkodean C ++ dan benar-benar terasa bahwa produktivitas saya telah menurun secara dramatis sejak itu. C ++ sebagai bahasa bukan masalah - saya punya cukup banyak pengalaman C ++ dev ... tapi di masa lalu.

Produktivitas saya masih OK untuk proyek-proyek kecil, tetapi menjadi lebih buruk ketika dengan peningkatan ukuran proyek dan begitu waktu kompilasi mencapai 10+ menit itu menjadi sangat buruk. Dan jika saya menemukan kesalahan, saya harus memulai kompilasi lagi, dll. Itu hanya membuat frustrasi.

Jadi saya menyimpulkan bahwa dalam potongan kecil (seperti sebelumnya) tidak dapat diterima - rekomendasi apa pun bagaimana saya bisa masuk ke kebiasaan lama pengkodean selama satu jam atau lebih, ketika meninjau kode secara manual (tanpa mengandalkan kompiler C # cepat) , dan hanya mengkompilasi ulang / menjalankan kembali unit test sekali dalam beberapa jam.

Dengan C # dan TDD itu sangat mudah untuk menulis kode dengan cara evolusi - setelah selusin iterasi apa pun omong kosong yang saya mulai berakhir dengan kode yang baik, tapi itu tidak berfungsi lagi untuk saya (dalam kompilasi lambat lingkungan Hidup).

agas
sumber
stackoverflow.com/questions/5078409/... Ini mungkin harus digabung / di satu tempat.
Ben L
Lihat laso stackoverflow.com/questions/373142/… untuk mempercepat waktu kompilasi C ++.
Eclipse
2
Mulai pertarungan pedang . ; p
Steven Jeuris
Terakhir kali saya menggunakan C ++ dengan sungguh-sungguh, menggunakan header yang dikompilasi sebelumnya mengurangi waktu kompilasi dengan faktor empat.
gnasher729

Jawaban:

16

Beberapa hal muncul di benak saya:

  1. Manfaatkan kompilasi yang didistribusikan . Anda dapat melakukan ini dengan GCC ("distCC"?) Atau VC ( Xoreax 'IncrediBuild tidak bisa dibilang murah, tetapi bernilai setiap sen yang dihabiskan untuk itu.).

  2. Bagi proyek Anda menjadi pustaka yang dimuat secara dinamis, dan cobalah untuk meminimalkan ketergantungan pada pustaka tersebut. Tautan yang dapat dieksekusi lebih kecil, lebih cepat.

  3. Program terhadap proyek uji kecil daripada seluruh aplikasi besar.

  4. Gunakan pemrograman templat-meta untuk melakukan algoritma pada waktu kompilasi . Ya, ini sebenarnya akan meningkatkan waktu kompilasi, tetapi juga akan mengurangi turnaround yang dibutuhkan untuk pengujian: Jika kompilasi baik, itu selesai.

  5. Investasikan dalam perangkat keras . Kernel CPU yang lebih banyak (di mesin Anda atau di orang lain) akan bertanya-tanya dengan kompilasi terdistribusi, dan banyak memori ditambah disk cepat (SSD bukan HDD) akan banyak membantu. Jika Anda memiliki sistem 64bit dan jumlah RAM yang tidak senonoh, kompilasi pada disk RAM mungkin memberikan peningkatan kecepatan yang luar biasa.

sbi
sumber
1
cache kompiler sebenarnya adalah ide yang lebih baik daripada kompilasi yang didistribusikan dalam pengalaman saya.
pqnet
Berbicara tentang RAM disk vs SSD, saya cukup terkejut bahwa itu tidak membawa begitu banyak peningkatan kecepatan kompilasi. Proyek saya saat ini (Java pada Android) mengkompilasi dari kondisi bersih dalam ~ 45 detik dari SSD dan ~ 40 detik dari disk RAM (dan seluruh toolchain dalam disk RAM, bukan hanya sumber). Bukan peningkatan dramatis, kataku.
Haspemulator
10

Solusi teknis lain yang belum disebutkan oleh orang lain adalah beralih ke Solid State Drive bukan hard drive biasa. Dalam proyek sebelumnya yang saya kerjakan, SSD menurunkan waktu pembuatan dari kisaran 30 menit hingga 3.

Tentu saja, itu mahal. Untuk bos Anda, hitung harga waktu pengembang yang hilang terhadap harga investasi satu kali. Investasi mungkin membayar sendiri dalam beberapa bulan.

Péter Török
sumber
6
Itu menarik. Yang mengatakan 90% dari waktu membangun adalah latensi disk I / O.
Mike Dunlavey
Saya belum melihat penurunan 90%, tetapi yang substansial. Tampaknya tidak mempercepat kompilasi, tetapi pasti mempercepat penautan. Jika Anda membuat perubahan kecil pada proyek besar (jadi tidak ada banyak kompilasi dalam perubahan), dan menautkan kembali, Anda mungkin akan mendapatkannya. (Ini adalah Visual Studio 2008, menggunakan C ++.)
David Thornley
1
Ini ide yang bagus. Juga, memasang sebagian RAM pada sistem file Anda akan bekerja cepat, dan murah.
Goran Jovic
2
Ramdisk bahkan lebih cepat (dan lebih murah).
SK-logic
1
@ John: Ya, kompiler yang ditulis dengan baik harus (IMHO) terikat I / O.
Mike Dunlavey
3

Lebih banyak perencanaan, kode dalam potongan yang lebih besar, tulis tes integrasi daripada tes unit dan jalankan build + test suite dalam semalam.

Nemanja Trifunovic
sumber
3

Waktu kompilasi yang lama terkadang menjadi masalah, tetapi modularisasi yang telah disebutkan dapat membantu mengatasinya (kebanyakan).

Jauh lebih serius sedang terjebak dalam lingkungan di mana Anda tidak dapat mengkompilasi sama sekali, di mana setiap perubahan kode harus diserahkan ke departemen lain di benua lain untuk aplikasi ke lingkungan pengujian / pengembangan, suatu proses yang dapat memakan waktu berhari-hari untuk diselesaikan.

Saya sekarang bekerja di lingkungan seperti itu, dan sistem ini telah menghabiskan biaya saya selama seminggu (dan proyek ini hanya memiliki anggaran untuk total waktu 4 minggu sebelum uang habis) hanya untuk mendapatkan versi awal dari perubahan yang diinstal (dan kemudian mereka membuat kesalahan yang menyebabkan sebagian file tidak diambil oleh server aplikasi, jadi kami melihat beberapa hari lagi penundaan). Setiap perubahan kecil sekarang (misalkan kita menemukan sesuatu dalam pengujian yang perlu diperbaiki, seperti kondisi kesalahan yang terlewat) dapat menyebabkan penundaan satu hari atau lebih.

Dalam kondisi seperti itu Anda mencoba untuk memastikan sebanyak mungkin bahwa tidak ada kesalahan apa pun bahkan sebelum mencoba untuk mendapatkan kode Anda dikompilasi. Rasanya hampir seperti saya kembali ke pemrograman mainframe, di mana kami memiliki 5 menit waktu CPU per bulan tersedia untuk semua pekerjaan kompilasi dan pengujian.

jwenting
sumber
1
Wah, itu situasi dari neraka. Saya ingat hari-hari mainframe. Kami melakukan banyak "pemeriksaan meja" kode. Sungguh menakjubkan betapa banyak yang dilakukan dengan cara itu, seperti simulasi penerbangan ke bulan tanpa akhir.
Mike Dunlavey
3

Saya dapat dengan mudah mengingat kapan pembuatan membutuhkan waktu lama. Beberapa pendekatan mitigasi:

  • Bangun sistem dengan menggabungkan perpustakaan atau dll. Dengan begitu, ketika Anda memodifikasi beberapa kode, satu-satunya bagian yang perlu dikompilasi ulang adalah bagian Anda.
  • Jumlah poin dalam kode yang perlu Anda edit untuk mengimplementasikan fitur tidak hanya mempengaruhi berapa banyak pengeditan yang harus Anda lakukan, tetapi frekuensi yang Anda masukkan ke bug, memperkuat loop kompilasi-debug-edit-kompilasi. Apa pun yang mengurangi redundansi kode, seperti KERING, membantu.
  • Jika Anda berada di debugger, dan dapat mengedit, mengkompilasi ulang, dan melanjutkan tanpa meninggalkan debugger, itu sangat membantu.
Mike Dunlavey
sumber
2

10+ menit untuk kompilasi? Serius?

Apakah Anda menggunakan IDE yang membuat bangunan tambahan (misalnya Eclipse)? Jika tidak, Anda mungkin harus, itu akan melakukan kompilasi dasar dalam hitungan detik, bukan menit.

Atau apakah Anda berbicara tentang hal-hal integrasi, di mana Anda perlu membangun seluruh aplikasi untuk menguji perubahan Anda? Jika demikian, lihat tes yang lebih kecil untuk memastikan bug utama keluar dari kode Anda sebelum harus melakukan pengembangan penuh.

TrueDub
sumber
5
10 menit kecil. Saya telah bekerja untuk sebuah proyek yang membutuhkan waktu satu jam untuk mengkompilasi dan menautkan dari awal pada mesin single-core, PCHs dan semuanya. Tentu saja, kecuali untuk rilis rilis otomatis, tidak seorang pun akan membangunnya hanya pada satu inti prosesor, tetapi tetap saja ... Jika Anda harus mengubah sesuatu di header yang disertakan di mana-mana (manipulasi string, penanganan kesalahan), Anda dapat menjadi gila.
sbi
2
Digunakan untuk bekerja (tahun lalu) pada sistem yang membutuhkan, untuk membangun yang lengkap, 48 jam untuk dikompilasi. Tentu saja pembangunan penuh baru dimulai pada hari Jumat malam, mudah-mudahan dilakukan ketika kami kembali ke kantor pada hari Senin. Kami malah membangun modul kecil sesuai kebutuhan (katakanlah satu DLL).
jwenting
2
-1 untuk semua komentar di atas jika saya dapat memberi +1 ke TrueDub. Ya, jika Anda mengkompilasi ulang semuanya maka itu bisa memakan waktu yang sangat lama. Namun, jika ada pemikiran sama sekali diberikan kepada manajemen ketergantungan maka 10 jam seluruh proyek rekompilasi dapat memiliki kompilasi tambahan dalam waktu kurang dari satu menit menjadi norma. Anda semua harus malu pada diri Anda sendiri membuang-buang waktu majikan Anda menunggu kompilasi Anda ketika menerapkan sedikit kecerdasan akan menghemat banyak waktu.
Dunk
2
Dan jika Anda bekerja di sebuah toko kecil yang kebetulan duduk di proyek beberapa-MLoC, maka itu berarti bahwa sebagian besar kode sudah tua, dimulai satu dekade lalu sebagai beberapa proyek kecil, di mana kecepatan kompilasi tidak pernah menjadi masalah, dan manajemen ketergantungan sangat buruk. Jadi, apakah Anda akan memberitahu perusahaan seperti itu untuk membuang semua ini dan menghabiskan satu dekade lagi untuk menulisnya kembali?
sbi
2
@Dunk: Itu adalah perusahaan kecil, dengan kurang dari selusin pengembang mengerjakan proyek multi-MLoC. Itu sangat berbeda dari ratusan pengembang yang melakukannya: Anda tidak dapat menulis ulang apa pun dari awal, karena Anda perlu bertahun-tahun untuk melakukannya. Seperti saya membenci ide itu, investasi dalam kompilasi didistribusikan secara ekonomi layak, menulis ulang tidak. Oh, dan saya mewarisi antarmuka itu. :-xSaya tidak ada di sana satu dekade yang lalu, ketika mereka dipikirkan. (Saya mengubah banyak kode untuk menggunakan TMP, untuk menemukan lebih banyak kesalahan saat kompilasi, dan lebih sedikit di lapangan.)
sbi
2

Pertama, mengapa begitu lama untuk dikompilasi?

  • Apakah lingkungan Anda (IDE, buatan, apa pun) mendukung build tambahan? Pastikan Anda hanya mengkompilasi ulang perubahan, bukan semuanya.
  • Jika Anda memiliki mesin multi-core, IDE Anda dapat mendukung kompilasi paralel. Saya tahu benar bahwa Visual Studio melakukan itu. Rupanya begitu juga gcc. Jadi dapatkan mesin yang lebih baik, dan aktifkan kompilasi paralel.
  • Pertimbangkan untuk menggunakan tajuk yang dikompilasi sebelumnya.
  • Jika Anda mencoba semua itu, dan kompilasi masih lambat, tinjau kode Anda. Cari dependensi yang tidak perlu. Apakah Anda menyertakan tajuk yang deklarasi penerusannya memadai? Pertimbangkan untuk menggunakan idiom PIMPL untuk mengurangi ketergantungan pada tajuk.

Jika setelah semua ini, waktu pembuatan Anda masih lambat, kemudian hancurkan masalahnya: buat banyak proyek uji kecil dan kerjakan masing-masing secara individual. Pastikan Anda memiliki sistem build malam otomatis yang melakukan checkout baru, membangun semuanya, dan menjalankan semua tes unit secara otomatis.

Akhirnya, jika Anda masih membutuhkan waktu lama untuk menguji perubahan Anda, maka pikirkan lebih dalam. Pastikan untuk melakukan perbedaan dalam sistem kontrol versi Anda dan tinjau dengan cermat semua perubahan sebelum pengujian. Singkatnya, ini sangat mirip dengan pengembangan sistem tertanam, di mana waktu penyelesaian untuk sebuah tes panjang, dan kemampuan Anda untuk memeriksa keadaan sistem terbatas.

Ini membawa saya ke pemikiran lain: instrumen kode Anda untuk menggunakan logging. Dengan cara ini Anda mungkin dapat melihat apa masalahnya tanpa membangun kembali dan menjalankan kembali selusin kali.

Dima
sumber
2
Saya tidak yakin apakah GCC mendukung kompilasi paralel sebanyak fakta bahwa pembuatan atau alat serupa akan memulai beberapa salinan GCC jika Anda juga menceritakannya.
Zachary K
1
+1 untuk PIMPL. Saya bekerja pada sebuah proyek di mana waktu build tidak terkendali. Dalam proyek itu, saya tidak peduli berapa banyak header lain yang dimasukkan dalam setiap header. Pada proyek saya berikutnya, saya membuat titik untuk meminimalkan ini dengan menggunakan PIMPL secara ekstensif. Waktu membangun terus menjadi besar meskipun proyek kedua mungkin dua kali ukuran yang pertama.
Jason B
1

Anda mungkin membutuhkan pendekatan multi-cabang:

1) Sistem pembangunan yang lebih cepat. Sebanyak core / ram / disk cepat yang Anda mampu. Untuk proyek C ++ yang lebih besar, Anda akan menemukan bahwa disk sering kali merupakan pembatas, jadi pastikan Anda memiliki yang cepat.

2) Lebih banyak modularisasi proyek. Hancurkan barang sehingga perubahan tidak dapat dengan mudah menyebabkan kompilasi ulang semuanya. Sejujurnya, dorong barang-barang dasar sebanyak mungkin ke file dll / sehingga terpisah sehingga bagian dari proyek dapat sepenuhnya dipisahkan dari yang lain.

3) Build tambahan / build build / caching yang sesuai dengan lingkungan Anda. Pada beberapa sistem, distcc (gedung terdistribusi) dan ccache (caching dari barang yang dibuat sebagian) dapat menghemat banyak waktu kompilasi.

4) Pastikan bangunan Anda dapat diparalelkan dengan baik. Dalam lingkungan makefile khususnya, tidak sulit untuk masuk ke situasi di mana Anda secara tidak sengaja membuat Makefile sehingga Anda tidak dapat melakukan pembangunan paralel.

Michael Kohne
sumber
0

Pencatatan yang ekstensif dan validasi internal telah membantu untuk waktu penyelesaian yang lama. Setelah build Anda selesai, sekali jalankan dapat mengungkapkan serangkaian besar kemungkinan masalah sekaligus.

Ketika berhadapan dengan algoritma atau pembukuan yang agak rumit, akan sangat membantu jika menyertakan versi yang sangat sederhana secara paralel dengan versi 'nyata'. Dalam proses apa pun, Anda memiliki data referensi berguna yang disertakan.

Joris Geer
sumber
0

Apa yang dikatakan @sbi dan @Michael Kohne.

Habiskan waktu dan energi untuk proses pembangunan itu sendiri. Sekali waktu kami memiliki produk yang megah dan matang yang membutuhkan waktu lebih dari satu jam untuk membangun penuh. Banyak waktu dan energi dihabiskan untuk memperbaiki apa yang diklaim dependensi build, dan kemudian, memperbaiki / mengurangi apa sebenarnya mereka. Waktu pembuatan turun menjadi ~ 30 menit.

Mengubah alat bangun menjatuhkan lebih banyak. Untuk proyek multi-bagian, 'scon' dapat melakukan semua kompilasi sebelum melakukan tautan apa pun. 'make' menggunakan banyak makefile mengerjakan satu proyek tunggal sebelum kompilasi proyek itu, kemudian melanjutkan.

Itu membawa kita ke titik bahwa semua perintah kompilasi individu dapat dilakukan secara paralel. 'distcc' pada mesin lambat, buat / scons -j8 pada mesin multicore. Itu membawa membangun penuh ke beberapa menit.

Dengan cara berbeda, buat proses pembangunan malam otomatis. Dengan cara itu jika sesuatu yang bermasalah dilakukan ke repositori sumber Anda, orang pertama yang tiba di tempat kerja, melihat dan memperbaiki masalah, dapat mencegah banyak orang dari (kembali) melakukan beberapa pembangunan gagal.

Rick Berge
sumber