Performance Testing Rails Applications
1. Mở đầu Đối với 1 dự án thì việc đảm bảo những yêu cầu khách hàng là rất quan trọng nhưng vấn đề đảm bảo performance khi lượng người truy cập tăng lên hay lượng database records tăng lên cũng quan trọng không kém. Ngoài RSpec test hôm nay mình xin giới thiệu thêm 1 công cụ để test performance ...
1. Mở đầu
Đối với 1 dự án thì việc đảm bảo những yêu cầu khách hàng là rất quan trọng nhưng vấn đề đảm bảo performance khi lượng người truy cập tăng lên hay lượng database records tăng lên cũng quan trọng không kém.
Ngoài RSpec test hôm nay mình xin giới thiệu thêm 1 công cụ để test performance cho rails application.
rails-perftest là 1 gem được thiết kế để test xem vấn đề về memory (sử dụng nhiều bộ nhớ) và tốc độ (sử dụng nhiều CPU) đến từ đâu và có 1 bức tranh toàn cảnh của toàn bộ vấn đề.
2. Cài đặt
gem 'rails-perftest' gem 'ruby-prof'
và tất nhiên là bundle install
3. Cách sử dụng
Test home_page
rails generate performance_test homepage
lệnh này sẽ tạo ra file homepage_test.rb trong thư mục test/performance
require 'test_helper' require 'rails/performance_test_help' class HomepageTest < ActionDispatch::PerformanceTest # Refer to the documentation for all available options # self.profile_options = { runs: 5, metrics: [:wall_time, :memory], # output: 'tmp/performance', formats: [:flat] } test "homepage" do get '/' end end
Hãy giả sư như ta có 1 app như sau
# routes.rb root to: 'home#dashboard' resources :posts # home_controller.rb class HomeController < ApplicationController def dashboard @users = User.last_ten.includes(:avatars) @posts = Post.all_today end end # posts_controller.rb class PostsController < ApplicationController def create @post = Post.create(params[:post]) redirect_to(@post) end end # post.rb class Post < ActiveRecord::Base before_save :recalculate_costly_stats def slow_method # I fire gallzilion queries sleeping all around end private def recalculate_costly_stats # CPU heavy calculations end end
Test controller HomeController#dashboard và PostsController#create
require 'test_helper' require 'rails/performance_test_help' class PostPerformanceTest < ActionDispatch::PerformanceTest def setup # Application requires logged-in user login_as(:lifo) end test "homepage" do get '/dashboard' end test "creating new post" do post '/posts', post: { body: 'lifo is fooling you' } end end
test model
require 'test_helper' require 'rails/performance_test_help' class PostModelTest < ActionDispatch::PerformanceTest test "creation" do Post.create body: 'still fooling you', cost: '100' end test "slow method" do # Using posts(:awesome) fixture posts(:awesome).slow_method end end
4. Kiểm định kết quả
rake test:benchmark hoặc để test riêng 1 file bin/rake test:benchmark TEST=test/performance/homepage_test.rb
Kết quả như sau:
BrowsingTest#test_homepage (58 ms warmup) process_time: 63 ms memory: 832.13 KB objects: 7,882
Wall Time là thời gian thực tế chạy test, nó ảnh hưởng bởi tốc độ của code đã viết và cả bởi trạng thái CPU (Sẽ tùy vào từng tình huống mà ra kết quả khác nhau) Process Time là thời gian mà CPU phải xứ lý code và không phụ thuộc vào trạng thái CPU. Có thể nói đây là thông số để đo tốc độ code CPU Time tương tự như Process Time nhưng chính xác hơn 1 chút User Time là thời gian CPU hoạt động trong chế độ user-mode, không bị ảnh hưởng bới tiến trình khác, không tính thời gian bị blocked. Memory lượng bộ nhớ được sử dụng Objects số object được tạo ra GC Runs số lần GC được gọi (Garbage collection, số lần bộ dọn bộ nhớ của hệ thống được goi) GC Time thời gian bỏ ra để GC "dọn dẹp" bộ nhớ khi không còn sử dụng.
Như vậy từ thông số trên ta sẽ tính được trong 1s. Server sẽ xử lý được bao nhiêu request, tiêu hao mất bao nhiêu bộ nhớ... Từ đó tính được số người dùng server phục vụ được, và cấu hình phần cứng yêu cầu khoảng bao nhiêu.
Kết quả trên được đo bằng CPU 2core. RAM 4GB. 1s CPU xử lý được 1000/63 ~= 15 request. Bộ nhớ tiêu hao: 832.13 *15 ~= 13 MB/s
Như vậy muốn đáp ứng cho khảng 20 request/s. Thì cần nâng CPU lên 1.3 lần hoặc refactor code cho process_time < 48ms
5. Tổng kết
Như vậy, với việc sử dụng gem rails-perftest chúng ta sẽ tìm ra controller nào đang có tốc độ xử lý chậm nhất, tiêu hao nhiều bộ nhớ nhất...Nếu tìm hiểu kỹ hơn chúng ta có thể tìm ra phần code nào trong model, views... gây ra performance kém và sửa. Dưới đây là link tham khảo https://github.com/rails/rails-perftest https://www.youtube.com/watch?v=eojUBB_8V_4