Kecepatan kompilasi Java vs kecepatan kompilasi Scala

101

Saya telah memprogram di Scala untuk sementara waktu dan saya menyukainya tetapi satu hal yang membuat saya kesal adalah waktu yang dibutuhkan untuk mengkompilasi program. Sepertinya hal kecil tetapi dengan Java saya bisa membuat perubahan kecil pada program saya, klik tombol run di netbeans, dan BOOM, itu berjalan, dan seiring waktu kompilasi dalam skala sepertinya memakan banyak waktu. Saya mendengar bahwa dengan banyak proyek besar, bahasa skrip menjadi sangat penting karena waktu yang dibutuhkan untuk kompilasi, kebutuhan yang tidak saya lihat muncul ketika saya menggunakan Java.

Tapi saya berasal dari Java yang saya mengerti, lebih cepat daripada bahasa terkompilasi lainnya, dan cepat karena alasan saya beralih ke Scala (Ini bahasa yang sangat sederhana).

Jadi saya ingin bertanya, dapatkah saya membuat kompilasi Scala lebih cepat dan akankah scalac secepat javac.

pengguna405163
sumber
Sepertinya beberapa pengguna setuju dengan Anda;) twitter.com/etorreborre/status/21286172202
VonC
Go mengkompilasi lebih cepat dari Java. Jauh lebih cepat, yaitu mengatakan sesuatu.
Daniel C. Sobral
Ahaha, dalam kasus saya dibutuhkan beberapa menit untuk kompilasi scalac rata-rata dengan beberapa LOC yang banyak, fsc sedikit lebih cepat.
Jeriho

Jawaban:

57

Kompilator Scala lebih canggih daripada Java, menyediakan inferensi tipe, konversi implisit, dan sistem tipe yang jauh lebih bertenaga. Fitur-fitur ini tidak datang secara gratis, jadi saya tidak berharap scalac bisa secepat javac. Ini mencerminkan trade-off antara pemrogram yang melakukan pekerjaan dan kompiler yang melakukan pekerjaan.

Meskipun demikian, waktu kompilasi telah meningkat secara nyata dari Scala 2.7 ke Scala 2.8, dan saya berharap peningkatan akan berlanjut sekarang setelah debu telah menetap di 2.8. Halaman ini mendokumentasikan beberapa upaya dan ide yang sedang berlangsung untuk meningkatkan kinerja penyusun Scala.

Martin Odersky memberikan lebih banyak detail dalam jawabannya.

Aaron Novstrup
sumber
1
Bukankah lebih dari halaman ini ( lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded )?
VonC
Saya telah beralih dari netbeans ke ant + jedit (saya tahu saya tahu, semut untuk manusia gua, tapi saya akan berkembang sesuai waktu saya sendiri) sehingga saya dapat menggunakan fsc. Tapi saya bertanya-tanya, bagaimana kecepatan kompilasi Clojure dibandingkan dengan Scala? Tampaknya memiliki banyak fitur di Scala tetapi saya membayangkan sintaksnya jauh lebih mudah untuk diurai.
pengguna405163
1
Kami agak keluar dari topik di sini, tetapi kompiler Clojure sangat cepat (jauh lebih cepat daripada javac pada sumber yang setara). Anda benar bahwa itu adalah bahasa yang sangat sederhana, dan tidak memiliki sistem tipe statis apa pun, yang cukup membantu.
Daniel Spiewak
458

Ada dua aspek (kurangnya) kecepatan untuk kompilator Scala.

  1. Overhead awal yang lebih besar

    • Scalac sendiri terdiri dari BANYAK kelas yang harus dimuat dan dikompilasi jit

    • Scalac harus mencari classpath untuk semua file dan paket root. Bergantung pada ukuran classpath Anda, ini dapat memakan waktu satu hingga tiga detik tambahan.

    Secara keseluruhan, perkirakan overhead startup dari scalac 4-8 detik, lebih lama jika Anda menjalankannya pertama kali sehingga cache disk tidak terisi.

    Jawaban Scala untuk overhead startup adalah dengan menggunakan fsc atau melakukan pembangunan berkelanjutan dengan sbt. IntelliJ perlu dikonfigurasi untuk menggunakan salah satu opsi, jika tidak, overhead-nya bahkan untuk file kecil terlalu besar.

  2. Kecepatan kompilasi lebih lambat. Scalac mengelola sekitar 500 hingga 1000 baris / detik. Javac mengelola sekitar 10 kali lipatnya. Ada beberapa alasan untuk ini.

    • Jenis inferensi mahal, khususnya jika melibatkan pencarian implisit.

    • Scalac harus melakukan pemeriksaan tipe dua kali; sekali menurut aturan Scala dan kedua kalinya setelah penghapusan menurut aturan Java.

    • Selain pemeriksaan tipe, ada sekitar 15 langkah transformasi dari Scala ke Java, yang semuanya membutuhkan waktu.

    • Scala biasanya menghasilkan lebih banyak kelas per ukuran file yang diberikan daripada Java, khususnya jika idiom fungsional banyak digunakan. Pembuatan bytecode dan penulisan kelas membutuhkan waktu.

    Di sisi lain, program Scala 1000 baris mungkin sesuai dengan program Java 2-3K baris, jadi beberapa kecepatan yang lebih lambat saat dihitung dalam baris per detik harus diimbangi dengan lebih banyak fungsi per baris.

    Kami sedang mengerjakan peningkatan kecepatan (misalnya dengan membuat file kelas secara paralel), tetapi orang tidak dapat mengharapkan keajaiban di bagian depan ini. Scalac tidak akan pernah secepat javac. Saya yakin solusinya akan terletak pada server kompilasi seperti fsc dalam hubungannya dengan analisis ketergantungan yang baik sehingga hanya kumpulan file minimal yang harus dikompilasi ulang. Kami sedang mengerjakannya juga.

Martin Odersky
sumber
1
Tentang overhead startup karena pemuatan kelas: akankah kompilasi sebelumnya ke kode native menggunakan GCJ atau Mono membantu?
Siput mekanik
15
Bagaimana jika Scala ditulis ulang dalam C ++? : o)
marcus
Apakah ada keuntungan menggunakan instruksi bytecode yang dipanggil?
Rob Grant
40

Anda harus menyadari bahwa kompilasi Scala membutuhkan setidaknya urutan besarnya lebih lama daripada Java untuk dikompilasi. Alasannya adalah sebagai berikut:

  1. Konvensi penamaan (file XY.scalafile tidak perlu berisi kelas yang dipanggil XYdan mungkin berisi beberapa kelas tingkat atas). Oleh karena itu, kompilator mungkin harus mencari lebih banyak file sumber untuk menemukan pengenal kelas / sifat / objek tertentu.
  2. Implikasi - penggunaan implisit yang berat berarti kompilator perlu mencari konversi implisit dalam cakupan apa pun untuk metode tertentu dan memberi peringkat untuk menemukan metode yang "benar". ( yaitu, kompilator memiliki domain pencarian yang meningkat secara besar-besaran saat mencari metode. )
  3. Sistem tipe - sistem tipe skala jauh lebih rumit daripada Java dan karenanya membutuhkan lebih banyak waktu CPU.
  4. Jenis inferensi - jenis inferensi mahal secara komputasi dan pekerjaan yang javactidak perlu dilakukan sama sekali
  5. scalactermasuk simulator 8-bit dari stasiun pertempuran bersenjata lengkap dan operasional, dapat dilihat menggunakan kombinasi tombol ajaib CTRL-ALT-F12 selama fase kompilasi GenICode .
oxbow_lakes
sumber
3
@obox_lakes, tidak suka nitpick, tetapi Java memang perlu melakukan inferensi tipe untuk metode berparameter int a<T>(T a) {}dan kemudian a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Elazar Leibovich
13
@ Elazar - ya, saya tahu. Tapi terus terang menggelikan, di samping scala, untuk menyebut ini "tipe inferensi"!
oxbow_lakes
19

Cara terbaik untuk melakukan Scala adalah dengan IDEA dan SBT. Siapkan proyek SBT dasar (yang akan dilakukan untuk Anda, jika Anda suka) dan jalankan dalam mode kompilasi otomatis (perintah~compile ) dan ketika Anda menyimpan proyek Anda, SBT akan mengkompilasinya ulang.

Anda juga dapat menggunakan plug-in SBT untuk IDEA dan melampirkan tindakan SBT ke setiap Run Configurations Anda. Plug-in SBT juga memberi Anda konsol SBT interaktif dalam IDEA.

Either way (SBT berjalan secara eksternal atau SBT plug-in), SBT tetap berjalan dan dengan demikian semua kelas yang digunakan dalam membangun proyek Anda mendapatkan "pemanasan" dan JIT-ed dan overhead start-up dihilangkan. Selain itu, SBT hanya mengkompilasi file sumber yang membutuhkannya. Sejauh ini, ini adalah cara paling efisien untuk membangun program Scala.

Randall Schulz
sumber
9

Revisi terbaru Scala-IDE (Eclipse) jauh lebih baik dalam mengelola kompilasi inkremental.

Lihat " Apa sistem pembuatan Scala terbaik? " Untuk selengkapnya.


Solusi lainnya adalah dengan mengintegrasikan fsc - Fast offline compiler untuk bahasa Scala 2 - (seperti yang diilustrasikan dalam posting blog ini ) sebagai builder di IDE Anda.

teks alt

Tapi tidak secara langsung di Eclipse, seperti yang disebutkan Daniel Spiewak di komentar:

Anda tidak boleh menggunakan FSC dalam Eclipse secara langsung, hanya karena Eclipse sudah menggunakan FSC di bawah permukaan.
FSC pada dasarnya adalah lapisan tipis di atas compiler residen yang merupakan mekanisme yang digunakan oleh Eclipse untuk menyusun proyek Scala.


Akhirnya, seperti yang diingatkan Jackson Davis di komentar:

sbt (Simple build Tool) juga menyertakan semacam kompilasi "inkremental" (melalui eksekusi yang dipicu ), meskipun itu tidak sempurna , dan kompilasi inkremental yang ditingkatkan sedang dikerjakan untuk versi 0.9 sbt mendatang.

VonC
sumber
2
sbt juga dapat melakukan kompilasi tambahan
Jackson Davis
@ Jackson: eksekusi yang dipicu, benar! Saya telah memasukkannya dalam jawaban saya.
VonC
2
Anda tidak boleh menggunakan FSC dalam Eclipse secara langsung, hanya karena Eclipse sudah menggunakan FSC di bawah permukaan. FSC pada dasarnya adalah lapisan tipis di atas compiler penduduk yang justru mekanisme yang digunakan oleh Eclipse untuk mengkompilasi proyek Scala.
Daniel Spiewak
1
FSC adalah singkatan dari Fast Scala Compiler - bukan Fast Java Compiler
Ben McCann
@BenMcCann: Ups. Baik. Saya telah memperbaiki jawabannya.
VonC
6

Gunakan fsc - ini adalah kompilator scala cepat yang berfungsi sebagai tugas latar belakang dan tidak perlu memuat sepanjang waktu. Itu dapat menggunakan kembali contoh kompilator sebelumnya.

Saya tidak yakin apakah plugin scala Netbeans mendukung fsc (dokumentasi mengatakan demikian), tetapi saya tidak dapat membuatnya berfungsi. Coba versi malam plugin.

Denis Tulskiy
sumber
1
Plugin IntelliJ IDEA Scala juga memiliki opsi untuk menggunakan fsc
Aaron Novstrup
1
@anovstrup: ya, tetapi terkadang macet.
Denis Tulskiy
4

Anda dapat menggunakan plugin JRebel yang gratis untuk Scala. Jadi, Anda dapat "mengembangkan di debugger" dan JRebel akan selalu memuat ulang kelas yang diubah saat itu juga.

Saya membaca beberapa pernyataan di suatu tempat oleh Martin Odersky sendiri di mana dia mengatakan bahwa pencarian implikasinya (kompilator harus memastikan tidak ada lebih dari satu implisit tunggal untuk konversi yang sama untuk mengesampingkan ambiguitas) dapat membuat kompiler sibuk. Jadi mungkin ide yang bagus untuk menangani implikasinya dengan hati-hati.

Jika tidak harus 100% Scala, tetapi juga sesuatu yang serupa, Anda dapat mencoba Kotlin .

- Oliver

OlliP
sumber
2

Saya yakin ini akan ditolak, tetapi perubahan yang sangat cepat tidak selalu kondusif bagi kualitas atau produktivitas.

Luangkan waktu untuk berpikir lebih hati-hati dan mengeksekusi lebih sedikit siklus mikro pengembangan. Kode Scala yang baik lebih padat dan lebih penting (yaitu, bebas dari detail dan kompleksitas yang tidak terduga). Itu menuntut lebih banyak pemikiran dan itu membutuhkan waktu (setidaknya pada awalnya). Anda dapat berkembang dengan baik dengan lebih sedikit siklus kode / pengujian / debug yang secara individual sedikit lebih lama dan tetap meningkatkan produktivitas dan kualitas pekerjaan Anda.

Singkatnya: Carilah pola kerja optimal yang lebih cocok untuk Scala.

Randall Schulz
sumber
3
Saya setuju bahwa tidak penting memiliki siklus balik yang cepat. Tapi tidak sakit, bukan?
Elazar Leibovich
27
Saya tidak akan menolak, tetapi mengatakan bahwa Anda harus menyesuaikan pola kerja Anda dengan batasan alat Anda (kecepatan lambat kompilator) daripada mencoba meningkatkan alat bukanlah argumen yang baik. Terutama kemampuan untuk melakukan siklus tes cepat sangat berharga (meskipun itu tidak menggantikan kebutuhan untuk melakukan pemikiran mendalam, jenis yang mungkin paling baik dilakukan jauh dari keyboard, namun melengkapinya dengan baik).
Thilo
9
Saya pikir sebagian besar produktivitas saya sebenarnya hilang karena berpikir berlebihan sebelum berlari. Saya sering menemukan diri saya melihat beberapa persamaan untuk waktu yang lama mencoba untuk menemukan potensi jebakan yang menunggu saya, sambil berpikir, "Jalankan saja!" di belakang kepalaku. Dan tentu saja, ketika saya menjalankan program ini, saya belajar lebih banyak daripada yang mungkin saya dapatkan dengan satu atau dua jam meditasi. Meditasi itu bagus, tetapi saya merasa saya memiliki penggunaan kompilasi / meditasi tambahan yang sangat optimal dengan java.
user405163
2
Ini juga mirip dengan menyarankan Shakespeare tidak boleh menggunakan pemeriksa ejaan, melainkan berpikir lebih keras tentang apa yang ingin dia katakan. Pemeriksa ejaan otomatis membantu mengatasi masalah yang sama sekali berbeda.
Thilo