Tốc độ biên dịch Java so với tốc độ biên dịch Scala


101

Tôi đã lập trình bằng Scala một thời gian và tôi thích nó nhưng có một điều tôi khó chịu là thời gian biên dịch chương trình mất nhiều thời gian. Nó có vẻ như là một việc nhỏ nhưng với Java, tôi có thể thực hiện những thay đổi nhỏ đối với chương trình của mình, nhấp vào nút chạy trong netbeans và BOOM, nó đang chạy và theo thời gian biên dịch trong scala dường như tiêu tốn rất nhiều thời gian. Tôi nghe nói rằng với nhiều dự án lớn, ngôn ngữ kịch bản trở nên rất quan trọng vì mất thời gian biên dịch, một nhu cầu mà tôi không thấy phát sinh khi tôi sử dụng Java.

Nhưng tôi đến từ Java, theo tôi hiểu, nó nhanh hơn bất kỳ ngôn ngữ biên dịch nào khác và nhanh hơn vì lý do tôi chuyển sang Scala (Đó là một ngôn ngữ rất đơn giản).

Vì vậy, tôi muốn hỏi, liệu tôi có thể làm cho Scala biên dịch nhanh hơn và scalac sẽ nhanh như javac.


Có vẻ như một số người dùng đồng ý với bạn;) twitter.com/etorreborre/status/21286172202
VonC

Biên dịch nhanh hơn Java. Nhanh hơn, đang nói điều gì đó.
Daniel C. Sobral

Ahaha, trong trường hợp của tôi, phải mất vài phút để biên dịch scalac trung bình với vài trăm LOC, fsc nhanh hơn một chút.
Jeriho,

Câu trả lời:


57

Trình biên dịch Scala phức tạp hơn Java, cung cấp suy luận kiểu, chuyển đổi ngầm định và hệ thống kiểu mạnh hơn nhiều. Các tính năng này không miễn phí, vì vậy tôi sẽ không mong đợi scalac sẽ nhanh như javac. Điều này phản ánh sự cân bằng giữa lập trình viên thực hiện công việc và trình biên dịch thực hiện công việc.

Điều đó nói rằng, thời gian biên dịch đã được cải thiện đáng kể từ Scala 2.7 đến Scala 2.8 và tôi hy vọng những cải tiến sẽ tiếp tục ngay bây giờ khi bụi đã giải quyết vào 2.8. Trang này ghi lại một số nỗ lực và ý tưởng đang diễn ra để cải thiện hiệu suất của trình biên dịch Scala.

Martin Odersky cung cấp nhiều chi tiết hơn trong câu trả lời của mình.


1
Không phải trang này nhiều hơn ( lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded )?
VonC

Tôi đã chuyển từ netbeans sang ant + jedit (tôi biết tôi biết, kiến ​​là dành cho những người thượng đẳng, nhưng tôi sẽ phát triển theo thời gian của riêng mình) để tôi có thể sử dụng fsc. Nhưng tôi đã tự hỏi, làm thế nào để tốc độ biên dịch của Clojure so với Scala? Nó có vẻ có nhiều tính năng trong Scala nhưng tôi tưởng tượng cú pháp dễ phân tích cú pháp hơn nhiều.
user405163,

1
Chúng tôi hơi lạc đề ở đây, nhưng trình biên dịch của Clojure rất nhanh (nhanh hơn nhiều so với javac trên các nguồn tương đương). Bạn nói đúng rằng nó là một ngôn ngữ thực sự đơn giản và nó không có bất kỳ loại hệ thống kiểu tĩnh nào, điều này giúp ích khá nhiều.
Daniel Spiewak

458

Có hai khía cạnh đối với tốc độ (thiếu) của trình biên dịch Scala.

  1. Chi phí khởi động lớn hơn

    • Bản thân Scalac bao gồm rất nhiều lớp phải được tải và biên dịch jit

    • Scalac phải tìm kiếm classpath cho tất cả các gói và tệp gốc. Tùy thuộc vào kích thước của classpath của bạn, quá trình này có thể mất thêm một đến ba giây.

    Nhìn chung, dự kiến ​​chi phí khởi động của scalac là 4-8 giây, lâu hơn nếu bạn chạy nó lần đầu tiên để ổ đĩa đệm không bị lấp đầy.

    Câu trả lời của Scala cho chi phí khởi động là sử dụng fsc hoặc xây dựng liên tục với sbt. IntelliJ cần được định cấu hình để sử dụng một trong hai tùy chọn, nếu không chi phí của nó ngay cả đối với các tệp nhỏ cũng lớn một cách bất hợp lý.

  2. Tốc độ biên dịch chậm hơn. Scalac quản lý khoảng 500 đến 1000 dòng / giây. Javac quản lý khoảng 10 lần điều đó. Cái này có một vài nguyên nhân.

    • Suy luận kiểu rất tốn kém, đặc biệt nếu nó liên quan đến tìm kiếm ngầm.

    • Scalac phải kiểm tra kiểu hai lần; một lần theo quy tắc của Scala và lần thứ hai sau khi xóa theo quy tắc của Java.

    • Bên cạnh việc kiểm tra kiểu, có khoảng 15 bước chuyển đổi để chuyển từ Scala sang Java, tất cả đều mất thời gian.

    • Scala thường tạo ra nhiều lớp hơn cho mỗi kích thước tệp nhất định so với Java, đặc biệt nếu các thành ngữ chức năng được sử dụng nhiều. Việc tạo bytecode và viết lớp mất nhiều thời gian.

    Mặt khác, chương trình Scala 1000 dòng có thể tương ứng với chương trình Java 2-3K dòng, vì vậy một số tốc độ chậm hơn khi được tính bằng dòng trên giây phải cân bằng với nhiều chức năng hơn trên mỗi dòng.

    Chúng tôi đang làm việc để cải thiện tốc độ (ví dụ: bằng cách tạo các tệp lớp song song), nhưng người ta không thể mong đợi điều kỳ diệu ở mặt này. Scalac sẽ không bao giờ nhanh như javac. Tôi tin rằng giải pháp sẽ nằm ở các máy chủ biên dịch như fsc kết hợp với phân tích phụ thuộc tốt để chỉ có một bộ tệp tối thiểu phải được biên dịch lại. Chúng tôi cũng đang làm việc về điều đó.


1
Về chi phí khởi động do tải lớp: việc biên dịch trước thời hạn sang mã gốc bằng GCJ hoặc Mono có trợ giúp không?
Ốc cơ học

15
Điều gì sẽ xảy ra nếu Scala được viết lại bằng C ++? : o)
marcus

Sẽ có lợi ích khi sử dụng lệnh bytecode gọi là động lực học?
Rob Grant

40

Bạn nên biết rằng quá trình biên dịch Scala cần ít nhất một thứ tự lớn hơn Java để biên dịch. Lý do cho điều này là như sau:

  1. Quy ước đặt tên (một tệp XY.scalatệp không cần phải chứa một lớp được gọi XYvà có thể chứa nhiều lớp cấp cao nhất). Do đó, trình biên dịch có thể phải tìm kiếm nhiều tệp nguồn hơn để tìm một định danh lớp / đặc điểm / đối tượng nhất định.
  2. Implicits - việc sử dụng nhiều hàm implicits có nghĩa là trình biên dịch cần tìm kiếm bất kỳ chuyển đổi ngầm nào trong phạm vi cho một phương pháp nhất định và xếp hạng chúng để tìm ra phương pháp "đúng". ( tức là trình biên dịch có miền tìm kiếm được gia tăng hàng loạt khi định vị một phương thức. )
  3. Hệ thống kiểu - hệ thống kiểu scala phức tạp hơn Java và do đó tốn nhiều thời gian CPU hơn.
  4. Suy luận kiểu - kiểu suy luận tốn kém về mặt tính toán và là một công việc javackhông cần phải làm gì cả
  5. scalacbao gồm trình mô phỏng 8 bit của một trạm chiến đấu được trang bị đầy đủ và hoạt động, có thể xem được bằng cách sử dụng tổ hợp phím ma thuật CTRL-ALT-F12 trong giai đoạn biên dịch GenICode .

3
@obox_lakes, ghét phải nitpick, nhưng Java không cần phải làm kiểu suy luận cho các phương pháp tham số int a<T>(T a) {}và sau đó a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Elazar Leibovich,

13
@Elazar - vâng, tôi biết. Nhưng thật nực cười, bên cạnh scala, gọi đây là "kiểu suy luận"!
oxbow_lakes,


19

Cách tốt nhất để làm Scala là với IDEA và SBT. Thiết lập một dự án SBT sơ cấp (mà nó sẽ làm cho bạn, nếu bạn thích) và chạy nó ở chế độ biên dịch tự động (lệnh ~compile) và khi bạn lưu dự án của mình, SBT sẽ biên dịch lại nó.

Bạn cũng có thể sử dụng trình cắm SBT cho IDEA và đính kèm hành động SBT vào từng Cấu hình Chạy của bạn. Trình cắm SBT cũng cung cấp cho bạn một bảng điều khiển SBT tương tác trong IDEA.

Dù bằng cách nào (SBT chạy bên ngoài hoặc trình cắm thêm SBT), SBT vẫn chạy và do đó tất cả các lớp được sử dụng trong việc xây dựng dự án của bạn được "khởi động" và JIT-ed và chi phí khởi động bị loại bỏ. Ngoài ra, SBT chỉ biên dịch các tệp nguồn cần nó. Đó là cách hiệu quả nhất để xây dựng các chương trình Scala.


9

Các phiên bản mới nhất của Scala-IDE (Eclipse) quản lý quá trình biên dịch gia tăng tốt hơn nhiều.

Xem " Hệ thống xây dựng Scala tốt nhất là gì? " Để biết thêm.


Giải pháp khác là tích hợp fsc - Trình biên dịch ngoại tuyến nhanh cho ngôn ngữ Scala 2 - (như được minh họa trong bài đăng trên blog này ) làm trình tạo trong IDE của bạn.

văn bản thay thế

Nhưng không phải trực tiếp Eclipse, như Daniel Spiewak đề cập trong các bình luận:

Bạn không nên sử dụng FSC trong Eclipse trực tiếp, nếu chỉ vì Eclipse đã sử dụng FSC dưới bề mặt.
FSC về cơ bản là một lớp mỏng trên đầu trình biên dịch thường trú, đây chính xác là cơ chế được Eclipse sử dụng để biên dịch các dự án Scala.


Cuối cùng, như Jackson Davis nhắc tôi trong phần bình luận:

sbt (Công cụ xây dựng đơn giản) cũng bao gồm một số loại biên dịch "gia tăng" (thông qua thực thi được kích hoạt ), mặc dù nó không hoàn hảo và biên dịch gia tăng nâng cao đang được thực hiện cho phiên bản sbt 0.9 sắp tới.


2
SBT cũng có thể làm gia tăng biên dịch
Jackson Davis

@Jackson: đã kích hoạt thực thi, đúng! Tôi đã bao gồm nó trong câu trả lời của tôi.
VonC

2
Bạn không nên sử dụng FSC trong Eclipse trực tiếp, nếu chỉ vì Eclipse đã sử dụng FSC dưới bề mặt. FSC về cơ bản là một lớp mỏng trên đầu trình biên dịch thường trú, đây chính xác là cơ chế được Eclipse sử dụng để biên dịch các dự án Scala.
Daniel Spiewak

1
FSC là viết tắt của Nhanh Scala Compiler - không nhanh Java Compiler
Bến McCann

@BenMcCann: rất tiếc. Đúng. Tôi đã sửa câu trả lời.
VonC

6

Sử dụng fsc - đây là một trình biên dịch scala nhanh, hoạt động như một tác vụ nền và không cần tải mọi lúc. Nó có thể sử dụng lại phiên bản trình biên dịch trước đó.

Tôi không chắc liệu plugin scala Netbeans có hỗ trợ fsc hay không (tài liệu cho biết như vậy), nhưng tôi không thể làm cho nó hoạt động. Hãy thử các bản dựng hàng đêm của plugin.


1
Plugin IntelliJ IDEA Scala cũng có một tùy chọn để sử dụng fsc
Aaron Novstrup

1
@anovstrup: có, nhưng đôi khi nó bị treo.
Denis Tulskiy

4

Bạn có thể sử dụng plugin JRebel miễn phí cho Scala. Vì vậy, bạn có thể "phát triển trong trình gỡ lỗi" và JRebel sẽ luôn tải lại lớp đã thay đổi ngay tại chỗ.

Tôi đã đọc một số tuyên bố ở đâu đó của chính Martin Odersky khi anh ấy nói rằng việc tìm kiếm hàm ý (trình biên dịch phải đảm bảo không có nhiều hơn một hàm ẩn cho cùng một chuyển đổi để loại trừ những điều không rõ ràng) có thể khiến trình biên dịch bận rộn. Vì vậy, nó có thể là một ý tưởng tốt để xử lý các hệ lụy một cách cẩn thận.

Nếu nó không phải là Scala 100%, nhưng cũng có thứ gì đó tương tự, bạn có thể thử Kotlin .

- Oliver


2

Tôi chắc chắn rằng điều này sẽ bị bỏ phiếu thấp, nhưng việc thay đổi quá nhanh không phải lúc nào cũng có lợi cho chất lượng hoặc năng suất.

Hãy dành thời gian để suy nghĩ kỹ hơn và thực hiện ít chu kỳ vi mô phát triển hơn. Mã Scala tốt là dày đặc hơn và cần thiết hơn (tức là không có các chi tiết ngẫu nhiên và phức tạp). Nó đòi hỏi nhiều suy nghĩ hơn và điều đó cần thời gian (ít nhất là lúc đầu). Bạn có thể tiến triển tốt với ít chu kỳ mã / kiểm tra / gỡ lỗi riêng lẻ lâu hơn một chút và vẫn cải thiện năng suất và chất lượng công việc của bạn.

Tóm lại: Tìm kiếm một mô hình làm việc tối ưu phù hợp hơn với Scala.


3
Tôi đồng ý rằng không cần thiết phải có một chu kỳ quay vòng nhanh chóng. Nhưng nó không đau, phải không?
Elazar Leibovich

27
Tôi sẽ không bỏ phiếu, nhưng nói rằng bạn nên điều chỉnh mô hình làm việc của mình theo những hạn chế của công cụ của bạn (tốc độ chậm của trình biên dịch) thay vì cố gắng cải thiện công cụ không phải là một lập luận tốt. Đặc biệt là khả năng làm các chu kỳ kiểm tra nhanh là rất có giá trị (mặc dù nó không thay thế được việc phải thực hiện một số suy nghĩ sâu, loại có lẽ là tốt nhất nên thực hiện khỏi bàn phím, nó bổ sung cho nó một cách độc đáo).
Thilo

9
Tôi nghĩ rằng hầu hết năng suất của tôi thực sự bị mất do suy nghĩ quá nhiều trước khi chạy. Tôi thường xuyên thấy mình đang xem xét một số phương trình trong thời gian dài để cố gắng phát hiện ra cạm bẫy tiềm ẩn nào đang chờ đợi tôi, trong khi tôi đang nghĩ, "Cứ chạy nó đi!" ở phía sau đầu của tôi. Và chắc chắn, khi tôi chạy chương trình, tôi học được nhiều hơn những gì tôi có thể có với một hoặc hai giờ thiền định. Thiền là tốt, nhưng tôi cảm thấy tôi đã sử dụng rất tối ưu việc biên dịch / thiền tăng dần với java.
user405163

2
Điều này cũng tương tự như gợi ý Shakespeare không nên sử dụng công cụ kiểm tra chính tả, thay vào đó hãy suy nghĩ kỹ hơn về những gì anh ta muốn nói. Trình kiểm tra chính tả tự động giúp giải quyết một loạt vấn đề hoàn toàn khác.
Thilo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.