2012-04-20 40 views
18

Tôi có ứng dụng Rails 3.2.2 mà tôi đang tìm cách chạy bằng JRuby 1.6.7 (chế độ 1.9.2).Hiệu suất JRuby

Tôi có một ứng dụng mẫu chạy trong MRI ruby ​​1.9.3 và yêu cầu điển hình đang trở lại trong ~ 40ms: Hoàn thành 200 OK trong 36ms (Lượt xem: 27.5ms | ActiveRecord: 8.2ms)

Dưới JRuby sử dụng cùng một yêu cầu là bất cứ nơi nào từ 3 đến 20 lần chậm hơn tùy thuộc vào trang. Đối với cùng một thao tác như trên cần ~ 180ms: Đã hoàn thành 200 OK trong 180ms (Lượt xem: 153.0ms | ActiveRecord: 24.0ms)

Đây có phải là sự khác biệt về hiệu năng bình thường không? Tôi đã đọc rằng JRuby gần như bằng nhau về tốc độ với MRI. Các kết quả giữ trên máy Mac của tôi và một máy chủ Windows (nơi không may nó sẽ cần phải chạy). Đóng gói nó với Warbler chạy dưới Tomcat cũng chậm.

Thời gian trên là từ ứng dụng đường ray cơ bản được tạo để thử nghiệm JRuby. Trên ứng dụng phức tạp hơn, thời gian còn xa nhau hơn. Trên ứng dụng đó có nhiều mã ruby ​​đang chạy trên một số trang. Có vẻ như trang càng nhiều ruby ​​phụ thuộc vào sự khác biệt hiệu suất mà tôi quan sát càng lớn. Tôi đã không thực hiện điều chỉnh JRuby, vì tôi không biết bắt đầu từ đâu.

Vì vậy, câu hỏi của tôi là: điều này có bình thường không? Tôi có thể làm gì để điều chỉnh JRuby?

Trả lời

18
Is this a normal performance difference? 
I have read that JRuby is roughly equal on speed with MRI. 

Không, điều đó không bình thường. Khi JVM đã khởi động, các yêu cầu Rails theo JRuby thường có hiệu suất cao hơn đáng kể so với MRI, cả về tốc độ thực thi thô và thu gom rác.

Có vẻ như ứng dụng của bạn bị định cấu hình sai. Điều đầu tiên cần kiểm tra là cấu hình của Rails - hãy đảm bảo rằng Rails không ở chế độ phát triển và rằng config.threadsafe! được bật trong môi trường sản xuất của bạn. Chế độ Threadafe sẽ dẫn đến chỉ có một bản sao được chia sẻ của Rails được tải vào bộ nhớ khi ứng dụng của bạn đang chạy.

Ngoài ra, hãy kiểm tra xem cấu hình cơ sở dữ liệu của bạn có đang tận dụng kết nối tổng hợp hay không, ví dụ: pool: 20 trong database.yml.

Cuối cùng, hãy kiểm tra cài đặt JVM và JRuby của bạn - cả hai đều có khả năng điều chỉnh cao. Bạn cần đảm bảo rằng có đủ bộ nhớ được cấp phát cho JVM khi khởi động, và sau đó đủ bộ nhớ cho hoạt động trơn tru bình thường của ứng dụng của bạn; nếu không thì JVM sẽ liên tục bị buộc phải thu gom rác sớm và thường xuyên, điều này sẽ làm suy giảm đáng kể hiệu suất.

Ví dụ một số cài đặt cho một VPS khiêm tốn specced có thể là một cái gì đó như:

-Xmx500m -Xss1024k -Djruby.memory.max=500m -Djruby.stack.max=1024k

... nhưng không sao chép các thiết lập này một cách mù quáng! Bạn sẽ phải thử nghiệm và tìm ra những gì tốt cho bạn đối với các tài nguyên bộ nhớ có sẵn trên máy chủ của bạn.

Điều đó nói rằng, trong khi JRuby có thể sẽ tiêu thụ ít bộ nhớ hơn tổng số nhiều quy trình Rails theo MRI, bạn chắc chắn sẽ cần phân bổ thêm một chút trước cho một quy trình JVM.Hãy rộng lượng để JRuby, và JRuby sẽ thưởng cho bạn cho lòng tốt của bạn :-)

Bạn có thể đọc thêm về điều chỉnh JRuby và JVM ở đây: https://github.com/jruby/jruby/wiki/PerformanceTuning

Cập nhật

Bạn không cần phải thiết lập config.threadsafe! trong Rails 4.0 trở lên; nó là threadsafe theo mặc định.

+0

Chạy ở chế độ 'sản xuất', so với chế độ phát triển mang lại phản hồi nhanh hơn gấp 5-6 lần. Ít nhất đó là trong trường hợp của tôi. Cảm ơn vì đã chú ý điều đó. – Aleks

3

Nâng cấp lên jruby 1.6.8 hoặc jruby 1.7.x với JAVA 7!

Hiệu suất tuyệt vời.

Chúng tôi đã gặp sự cố tương tự và tốc độ cực nhanh của nó ngay bây giờ (chỉ cần chuyển đổi phiên bản).

+2

Tôi có cùng màn trình diễn tồi. Đã thử java 7 & Jruby 1.7, một ứng dụng đường ray mới là chậm hơn so với một dự án hiện tại mạnh mẽ với MRI. Erg. – m4tm4t

4

Tôi nhìn thấy hành vi tương tự, nhưng hãy nhớ rằng JRuby cần thời gian lâu hơn để làm ấm. Tôi thực sự hơi lạc quan rằng JRuby cuối cùng sẽ bắt kịp.

Có thể thực hiện điều này 'khởi động' nhanh hơn bằng cách đặt một vài tùy chọn. Ruby - trình biên dịch> Java bytecode có thể được dạy để JIT biên dịch tất cả các phương pháp trên gọi đầu tiên bằng cách thiết lập var env sau:

export JRUBY_OPTS="-J-Djruby.jit.threshold=1 -J-Djruby.jit.max=16384"

Đối với tôi, sau khi làm mới một trang Rails một vài lần, nó vẫn còn 2 -3x chậm hơn so với MRI Ruby, nhưng ít nhất 3x nhanh hơn trước. Cũng cần nhớ rằng thời gian chạy java là JIT biên dịch bytecode java thành mã máy theo cách tương tự, nhưng JIT này sẽ không khởi động cho đến khi một phương thức được gọi 10.000x khi sử dụng thời gian chạy của máy chủ. Đây có thể là configured as well.

export JRUBY_OPTS="-J-Djruby.jit.threshold=10 -J-Djruby.jit.max=16384 -J-XX:CompileThreshold=10" -J-XX:ReservedCodeCacheSize=128M"

Với tùy chọn này, JRuby on Rails cho về hiệu suất tương tự hoặc tốt hơn MRI.

Xin lưu ý rằng các tùy chọn này chỉ dành cho điểm chuẩn thiếu kiên nhẫn! Trong thực tế, nó luôn luôn là một ý tưởng tồi để chạy trình biên dịch JIT này một cách tích cực; Bạn đang lãng phí thời gian và bộ nhớ có giá trị trong việc biên dịch mã JIT mà chỉ có thể chạy một vài lần. Nó cho thấy, tuy nhiên, làm thế nào cuối cùng JRuby hiệu suất có thể được tốt hơn so với bạn mong đợi dựa trên chạy ban đầu.

Hãy cho tôi biết liệu tính năng này có phù hợp với bạn hay không.