Trình biên dịch java đã xử lý phân chia công việc của mình trên bộ vi xử lý có sẵn, ngay cả khi chỉ có biên soạn một tập tin duy nhất. Do đó, chạy các cá thể trình biên dịch riêng biệt song song với bản thân bạn sẽ không mang lại hiệu suất cao mà bạn mong đợi.
Để chứng minh điều này, tôi đã tạo chương trình java lớn (1 triệu dòng, 10.000 phương pháp) trong một tệp có tên là Main1.java
. Sau đó, tạo các bản sao bổ sung là Main2.java
đến Main8.java
. Biên dịch thời gian được tính như sau:
một tệp biên dịch:
time javac Main1.java & --> (real) 11.6 sec
Xem tập tin duy nhất này biên dịch trong top
tiết lộ việc sử dụng bộ xử lý chủ yếu trong khoảng 200-400% (chỉ sử dụng nhiều CPU, 100% mỗi CPU) , với mức tăng đột biến trong phạm vi 700% (mức tối đa trên máy này là 800% vì có 8 bộ xử lý).
Tiếp theo, hai tập tin cùng một lúc:
time javac Main1.java & --> (real) 14.5 sec
time javac Main2.java & --> (real) 14.8 sec
Vì vậy, nó chỉ mất 14,8 giây để biên dịch hai, khi nó mất 11,6 giây để biên dịch một. Đó chắc chắn là phi tuyến tính. Rõ ràng là bằng cách nhìn vào top
trong khi chúng được chạy lại, mỗi trình biên dịch java chỉ tận dụng tối đa bốn CPU cùng một lúc (với số lần tăng đột biến cao hơn). Bởi vì điều này, hai trình biên dịch chạy trên tám CPU chủ yếu là song song với nhau.
Tiếp theo, bốn tập tin cùng một lúc:
time javac Main1.java & --> (real) 24.2 sec
time javac Main2.java & --> (real) 24.6 sec
time javac Main3.java & --> (real) 25.0 sec
time javac Main4.java & --> (real) 25.0 sec
Được rồi, ở đây chúng tôi đã đâm vào tường. Chúng tôi không còn có thể song song với trình biên dịch nữa. Bốn tập tin mất 25 giây khi hai người mất 14,8. Có một chút tối ưu hóa ở đó nhưng nó chủ yếu là tăng thời gian tuyến tính.
Cuối cùng, Tám cùng một lúc:
time javac Main1.java & --> (real) 51.9 sec
time javac Main2.java & --> (real) 52.3 sec
time javac Main3.java & --> (real) 52.5 sec
time javac Main4.java & --> (real) 53.0 sec
time javac Main5.java & --> (real) 53.4 sec
time javac Main6.java & --> (real) 53.5 sec
time javac Main7.java & --> (real) 53.6 sec
time javac Main8.java & --> (real) 54.6 sec
Đây là thực sự là một chút tồi tệ hơn tuyến tính, như tám mất 54,6 giây trong khi bốn chỉ mất 25,0.Vì vậy, tôi nghĩ rằng takeaway từ tất cả điều này là để có niềm tin rằng trình biên dịch sẽ làm một công việc phong nha cố gắng để tối ưu hóa công việc bạn cung cấp cho nó trên các nguồn tài nguyên CPU có sẵn, và cố gắng thêm song song bổ sung bằng tay sẽ có giới hạn (nếu có) lợi ích.
Edit:
Để tham khảo, có hai mục tôi tìm thấy trong cơ sở dữ liệu lỗi của Oracle liên quan đến việc tăng cường javac để tận dụng nhiều bộ xử lý:
- Bug ID: JDK-6629150 - Việc khiếu nại ban đầu, đây là cuối cùng được đánh dấu là bản sao của:
- Bug ID: JDK-6713663 - Đề xuất độ phân giải và dựa trên "Ngày được giải quyết" có vẻ như hỗ trợ đa bộ xử lý trong javac đã được thêm vào ngày 2008-06-12.
Có thể dễ dàng là I/O-bound, không bị ràng buộc CPU. –
bất kỳ ý tưởng nào về cách xác nhận nếu io của nó bị ràng buộc ... trông giống như vậy vì dữ liệu của chúng tôi rất nhỏ – Bhuvan
Hmmm, 'javac' muốn tệp. Tôi đoán bạn có thể sử dụng một đĩa RAM. Tôi cũng đảm bảo rằng 'Main.java' là ** lớn ** vì vậy bạn thực sự kiểm tra biên dịch so với tải/lưu. Nhưng tất nhiên, câu hỏi thực sự là: Bạn đang cố gắng tối ưu hóa điều gì? Bởi vì nếu đó là toàn bộ quá trình, I/O là một yếu tố quan trọng bạn sẽ không muốn kiểm tra xung quanh. –