Computer >> Máy Tính >  >> Lập trình >> Ruby

Đường ray nhanh chóng:Tối ưu hóa hiệu suất xem của bạn

Trong bài đăng này, chúng tôi sẽ xem xét các phương pháp đã thử và đúng để cải thiện hiệu suất chế độ xem Rails. Cụ thể, tôi sẽ tập trung vào hiệu quả của cơ sở dữ liệu, thao tác xem và bộ nhớ đệm.

Tôi nghĩ rằng cụm từ "tối ưu hóa quá sớm là gốc rễ của mọi điều xấu xa" đã được đưa ra khỏi ngữ cảnh một chút. Tôi thường nghe các nhà phát triển sử dụng điều này trong quá trình đánh giá mã khi các kỹ thuật tối ưu hóa đơn giản được chỉ ra. Bạn biết câu nói nổi tiếng, "Tôi sẽ làm cho nó hoạt động và sau đó tối ưu hóa nó" - sau đó kiểm tra nó - sau đó gỡ lỗi nó - rồi kiểm tra lại, v.v.!

Rất may, có một số kỹ thuật tối ưu hóa và hiệu suất đơn giản và hiệu quả mà bạn có thể sử dụng ngay từ khi bắt đầu viết mã.

👋 Nếu bạn thích bài viết này, hãy xem các bài viết khác về hiệu suất của Ruby (trên Rails) trong danh sách kiểm tra giám sát hiệu suất Ruby của chúng tôi.

Trong suốt bài đăng, chúng tôi sẽ gắn bó với một ứng dụng Rails cơ bản, cải tiến ứng dụng đó và so sánh kết quả.

Ứng dụng Rails cơ bản có các mô hình sau:

  • Người (có nhiều địa chỉ)

    • tên:string
    • vote_count:số nguyên
  • Hồ sơ (thuộc về Người)

    • địa chỉ:string

Đây là mô hình Người của chúng tôi trông như thế nào:

# == Schema Information
#
# Table name: people
#
#  id          :integer          not null, primary key
#  name        :string
#  votes_count :integer
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#
 
class Person < ApplicationRecord
  # Relationships
  has_many :profiles
 
  # Validations
  validates_presence_of :name
  validates_uniqueness_of :name
 
  def vote!
    update votes_count: votes_count + 1
  end
end

Đây là mã cho mô hình Hồ sơ của chúng tôi:

# == Schema Information
#
# Table name: profiles
#
#  id         :integer          not null, primary key
#  address    :text
#  person_id  :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
 
class Profile < ApplicationRecord
  # Relationships
  belongs_to :person
 
  # Validations
  validates_presence_of :address
end
 

Ngoài ra còn có một tệp hạt giống cho 1000 người. Chúng ta có thể làm điều này một cách dễ dàng bằng cách sử dụng Faker gem.

Bây giờ chúng ta sẽ tạo một hành động có tên là "home" trong ApplicationController.

def home
  @people = Person.all
end

Mã cho home.html.erb của chúng tôi như sau:

<ul>
  <% @people.each do |person| %>
    <li id="<%= person.id %>"><%= render person %></li>
  <% end %>
</ul>

Hãy chạy thử và đo lường hiệu suất của trang của chúng ta theo điều này.

Trang đó đã mất một con số khổng lồ 1066,7ms để tải. Không tốt! Đây là những gì chúng tôi sẽ hướng tới để giảm bớt.

Truy vấn cơ sở dữ liệu

Bước đầu tiên để xây dựng một ứng dụng hiệu quả là tối đa hóa việc sử dụng tài nguyên. Hầu hết các ứng dụng Rails kết xuất một thứ gì đó từ cơ sở dữ liệu lên các khung nhìn, vì vậy trước tiên hãy cố gắng tối ưu hóa các lệnh gọi cơ sở dữ liệu!

Với mục đích của phần trình diễn này, tôi sẽ sử dụng cơ sở dữ liệu MySQL.

Hãy xem cách tải ban đầu 1066ms đó bị phá vỡ như thế nào.

414.7 để thực thi 'controller / application_controller # home'

...
(0.1ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 996]]
Rendered people/_person.html.erb (1.5ms)
(0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 997]]
Rendered people/_person.html.erb (2.3ms)
(0.1ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 998]]
Rendered people/_person.html.erb (2.1ms)
(0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 999]]
Rendered people/_person.html.erb (2.3ms)
(0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 1000]]
Rendered people/_person.html.erb (2.0ms)
Rendered application/home.html.erb within layouts/application (890.5ms)

Completed 200 OK in 1066ms (Views: 890.5ms | ActiveRecord: 175.4ms)

519.2 và 132.8 để hiển thị "ứng dụng / home.html.erb" và "people / _ person.html.erb" partials.

Bạn có nhận thấy điều gì kỳ lạ không?

Chúng tôi đã thực hiện một lệnh gọi cơ sở dữ liệu trong bộ điều khiển, nhưng mỗi phần cũng thực hiện lệnh gọi cơ sở dữ liệu của riêng nó! Xin giới thiệu, vấn đề truy vấn N + 1.

1. N + 1 Truy vấn

Đây là một kỹ thuật tối ưu hóa rất phổ biến và đơn giản — nhưng nó xứng đáng được đề cập đầu tiên vì lỗi này rất phổ biến.

Hãy xem "people / _ person.html.erb" làm gì:

<ul>
  <li>
    Name: <%= person.name %>
  </li>
  <li>
    Addresses:
      <ul>
        <% person.profiles.each do |profile| %>
          <li><%= profile.address %></li>
        <% end %>
      </ul>
  </li>
</ul>
 
<%= button_to "Vote #{person.votes_count}", vote_person_path(person) %>

Về cơ bản, nó truy vấn cơ sở dữ liệu cho hồ sơ của người đó và hiển thị từng người một. Vì vậy, nó thực hiện N truy vấn (trong đó N là số người) và 1 truy vấn mà chúng tôi đã thực hiện trong bộ điều khiển — do đó, N + 1.

Để tối ưu hóa điều này, hãy sử dụng các tham gia cơ sở dữ liệu MySQL và Rails ActiveRecord bao gồm các chức năng.

Hãy thay đổi bộ điều khiển để phù hợp với những điều sau:

def home
  @people = Person.all.includes(:profiles)
end

Tất cả mọi người được tải bằng 1 truy vấn MySQL và tất cả các truy vấn tương ứng của họ được tải trong một truy vấn khác. Đưa N + 1 xuống chỉ 2 truy vấn.

Hãy xem điều này làm tăng hiệu suất như thế nào!

Chúng tôi chỉ mất 936ms để tải trang. Bạn có thể thấy bên dưới rằng hành động "application_controller # home" thực hiện 2 truy vấn MySQL.

Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.2ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.3ms)
Rendered people/_person.html.erb (0.2ms)

Rendered application/home.html.erb within layouts/application (936.0ms)
Completed 200 OK in 936ms (Views: 927.1ms | ActiveRecord: 9.3ms)

2. Chỉ tải những gì bạn sẽ sử dụng

Đây là giao diện của trang chủ.

Bạn có thể thấy chúng tôi chỉ cần địa chỉ, không cần gì khác. Nhưng trong phần "_ person.html.erb", chúng tôi tải đối tượng hồ sơ. Hãy xem cách chúng tôi có thể thực hiện thay đổi đó.

<li>
  Addresses:
  <ul>
    <% person.profiles.pluck(:address).each do |address| %>
      <li><%= address %></li>
    <% end %>
  </ul>
</li>

Để có cái nhìn sâu sắc hơn về N + 1 truy vấn, hãy đọc hiệu suất ActiveRecord:N + 1 truy vấn phản vật chất.

Mẹo:Bạn có thể tạo một phạm vi cho điều này và thêm nó vào tệp "models / profile.rb". Các truy vấn cơ sở dữ liệu thô trong tệp dạng xem của bạn không được sử dụng nhiều.

3. Di chuyển tất cả lệnh gọi cơ sở dữ liệu đến bộ điều khiển

Giả sử, trong tương lai của ứng dụng đáng tin cậy này, bạn muốn hiển thị tổng số người dùng trên trang chủ.

Giản dị! Hãy thực hiện cuộc gọi trong giao diện giống như sau:

# of People: <%= @people.count %>

Được rồi, đơn giản vậy thôi.

Có một yêu cầu khác — bạn cần tạo một phần tử giao diện người dùng hiển thị tiến trình trang. Bây giờ, hãy chia số người trên trang cho tổng số.

Progress: <%= index / @people.count %>

Rất tiếc, đồng nghiệp của bạn không biết rằng bạn đã thực hiện truy vấn này và họ tiến hành thực hiện lại nhiều lần trong các chế độ xem.

Bộ điều khiển của bạn trông giống như thế này:

def home
  @people = Person.all.includes(:profiles)
  @people_count = @people.count
end

Sẽ dễ dàng hơn nếu sử dụng lại các biến đã được tính toán.

Mặc dù điều này không góp phần cải thiện trực tiếp tốc độ tải trang, nhưng nó ngăn chặn nhiều lệnh gọi đến cơ sở dữ liệu từ các trang xem khác nhau và giúp bạn chuẩn bị cho các tối ưu hóa mà bạn có thể thực hiện sau này, chẳng hạn như bộ nhớ đệm.

4. Đánh số trang ở bất cứ đâu bạn có thể!

Giống như chỉ tải những gì bạn cần, nó cũng giúp chỉ hiển thị những gì bạn cần! Với phân trang, các khung nhìn hiển thị một phần thông tin và giữ phần còn lại để tải theo yêu cầu. Điều này cắt bỏ rất nhiều mili giây! Các viên ngọc will_paginate và kaminari thực hiện việc này cho bạn trong vài phút.

Một điều khó chịu mà điều này gây ra là người dùng phải liên tục nhấp vào "Trang tiếp theo". Vì vậy, bạn cũng có thể xem "Cuộn vô hạn" để mang đến cho người dùng của mình trải nghiệm tốt hơn nhiều.

Tránh tải lại HTML

Trong một ứng dụng Rails truyền thống, việc hiển thị chế độ xem HTML mất rất nhiều thời gian. May mắn thay, bạn có thể thực hiện các biện pháp để giảm thiểu điều này.

1. Turbolinks

Điều này được gói gọn trong ứng dụng Rails tiêu chuẩn của bạn. Turbolinks là một thư viện JavaScript hoạt động ở mọi nơi (ngay cả khi không có Rails, như trên các trang tĩnh) và giảm chất lượng một cách duyên dáng trên các trình duyệt không được hỗ trợ.

Nó chuyển đổi mọi liên kết thành một yêu cầu AJAX và thay thế toàn bộ phần nội dung của trang thông qua JS. Điều này cải thiện đáng kể hiệu suất vì nó không phải tải lại CSS, JS và hình ảnh.

Tuy nhiên, khi viết JS tùy chỉnh, bạn sẽ phải thận trọng hơn khi viết "Turbolinks safe JS". Đọc thêm về điều này tại đây.

2. Sử dụng các yêu cầu AJAX

Tương tự như Turbolinks, bạn cũng có thể chuyển đổi một số liên kết và nút của mình thành các yêu cầu AJAX. Sự khác biệt ở đây là bạn có thể kiểm soát những gì HTML được thay thế thay vì thay thế toàn bộ phần nội dung như Turbolinks làm.

Hãy xem AJAX hoạt động!

Trong ứng dụng mẫu, có nút "Bỏ phiếu" cho mỗi người dùng. Hãy đo xem mất bao lâu để thực hiện hành động đó.

Started POST "/people/1/vote" for 127.0.0.1 at 2020-01-21 14:50:49 +0530
Processing by PeopleController#vote as HTML
  Person Load (0.3ms)  SELECT  "people".* FROM "people" WHERE "people"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  Person Exists (4.5ms)  SELECT  1 AS one FROM "people" WHERE "people"."name" = ? AND ("people"."id" != ?) LIMIT ?  [["name", "Deon Waelchi"], ["id", 1], ["LIMIT", 1]]
  SQL (1.0ms)  UPDATE "people" SET "votes_count" = ?, "updated_at" = ? WHERE "people"."id" = ?  [["votes_count", 1], ["updated_at", "2020-01-21 09:20:49.941928"], ["id", 1]]

Redirected to https://localhost:3000/
Completed 302 Found in 24ms (ActiveRecord: 7.5ms)


Started GET "/" for 127.0.0.1 at 2020-01-21 14:50:49 +0530
Processing by ApplicationController#home as HTML
  Rendering application/home.html.erb within layouts/application

  Rendered people/_person.html.erb (2.4ms)
   (0.3ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 30]]
  Rendered people/_person.html.erb (2.2ms)
  ...

  Rendered application/home.html.erb within layouts/application (159.8ms)
Completed 200 OK in 190ms (Views: 179.0ms | ActiveRecord: 6.8ms)

Điều đó mất cùng một khoảng thời gian như tải lại trang, cộng thêm một chút cho phần biểu quyết thực tế.

Hãy biến nó thành một yêu cầu AJAX. Bây giờ, "people / _ person.html.erb" của chúng ta trông giống như sau:

<%= button_to "Vote #{person.votes_count}", vote_person_path(person), remote: true %>

Hành động trình điều khiển của chúng tôi trả về một phản hồi JS, trông giống như sau:

$("#<%= @person.id %>").html("<%= j render(partial: 'person', locals: {person: @person}) %>");

Như bạn có thể thấy, chúng tôi chỉ thay thế nội dung chúng tôi cần. Chúng tôi cung cấp một ID HTML để gắn vào một div và thay thế nó. Tất nhiên, chúng tôi có thể tối ưu hóa hơn nữa điều này bằng cách chỉ thay thế nội dung nút, nhưng với mục đích của bài đăng này, hãy thay thế toàn bộ một phần.

Kết quả?

Started POST "/people/1/vote" for 127.0.0.1 at 2020-01-21 14:52:56 +0530
Processing by PeopleController#vote as JS

  Person Load (0.2ms)  SELECT  "people".* FROM "people" WHERE "people"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  Person Exists (0.3ms)  SELECT  1 AS one FROM "people" WHERE "people"."name" = ? AND ("people"."id" != ?) LIMIT ?  [["name", "Deon Waelchi"], ["id", 1], ["LIMIT", 1]]
  SQL (0.4ms)  UPDATE "people" SET "votes_count" = ?, "updated_at" = ? WHERE "people"."id" = ?  [["votes_count", 2], ["updated_at", "2020-01-21 09:22:56.532281"], ["id", 1]]
   (1.6ms)  commit transaction
  Rendering people/vote.js.erb
   (0.2ms)  SELECT "profiles"."address" FROM "profiles" WHERE "profiles"."person_id" = ?  [["person_id", 1]]

  Rendered people/_person.html.erb (3.2ms)
  Rendered people/vote.js.erb (6.3ms)
Completed 200 OK in 31ms (Views: 14.6ms | ActiveRecord: 2.9ms)

30 mili giây! Đó là nó! Điều đó tuyệt vời như thế nào?

ProTip:Nếu bạn không muốn lộn xộn với một loạt các ID và lớp HTML để tìm ra khi nào / cái gì cần thay thế, hãy xem xét sử dụng đá quý render_async. Nó thực hiện rất nhiều công việc nâng vật nặng ra khỏi hộp.

3. Sử dụng Websockets

Một trong những điều tuyệt vời về tải lại HTML là nó giúp bạn luôn có nội dung mới từ máy chủ. Với yêu cầu AJAX, bạn chỉ thấy nội dung mới nhất cho đoạn mã nhỏ.

WebSockets là một phần công nghệ tuyệt vời cho phép máy chủ của bạn đẩy các bản cập nhật đến máy khách, thay vì máy khách yêu cầu thông tin mới.

Điều này có thể hữu ích khi bạn cần xây dựng các trang web động. Hãy tưởng tượng bạn cần hiển thị điểm số của một trò chơi trên trang web của mình. Để tìm nạp nội dung mới, bạn có thể,

  • Yêu cầu người dùng của bạn tải lại toàn bộ trang
  • Cung cấp nút tải lại chỉ làm mới điểm số
  • Sử dụng JavaScript để tiếp tục thăm dò phần phụ trợ mỗi giây
    • Điều này sẽ tiếp tục ping đến máy chủ ngay cả khi không có thay đổi về dữ liệu
    • Mỗi máy khách sẽ thực hiện cuộc gọi mỗi giây - dễ dàng ghi đè máy chủ
  • Sử dụng WebSockets!

Với WebSockets, máy chủ có quyền kiểm soát thời điểm đẩy dữ liệu đến tất cả các máy khách (hoặc thậm chí một tập hợp con). Vì máy chủ biết khi nào dữ liệu thay đổi, nó chỉ có thể đẩy dữ liệu khi có thay đổi!

Rails 5 đã phát hành ActionCable, cho phép bạn quản lý tất cả mọi thứ trên WebSockets. Nó cung cấp một khung JS để máy khách đăng ký vào máy chủ và một khung phụ trợ để máy chủ xuất bản các thay đổi. Với cáp hành động, bạn có thể chọn bất kỳ dịch vụ WebSocket nào mà bạn chọn. Đó có thể là Faye, một dịch vụ ổ cắm web tự quản lý hoặc Pusher một dịch vụ đăng ký.

Cá nhân tôi chọn đăng ký cho việc này, vì nó làm giảm số lượng thứ bạn cần quản lý.

Được rồi, quay lại WebSockets. Sau khi bạn thiết lập xong ActionCable, chế độ xem của bạn sẽ không thể nghe đầu vào JSON từ máy chủ. Khi nó nhận được nó, các hành động hook mà bạn đã viết sẽ thay thế nội dung HTML tương ứng.

Tài liệu Rails và Pusher có các hướng dẫn tuyệt vời về cách xây dựng với WebSockets. Chúng là những thứ phải đọc!

Bộ nhớ đệm

Phần lớn thời gian tải được sử dụng hết trong các chế độ xem hiển thị. Điều này bao gồm tải tất cả CSS, JS và hình ảnh, hiển thị HTML từ các tệp ERB và hơn thế nữa.

Một cách để giảm một phần thời gian tải là xác định các phần của ứng dụng của bạn mà bạn biết sẽ ở trạng thái tĩnh trong một khoảng thời gian nào đó hoặc cho đến khi một sự kiện xảy ra.

Trong ví dụ của chúng tôi, rõ ràng là cho đến khi ai đó bỏ phiếu, trang chủ về cơ bản sẽ giống nhau đối với tất cả mọi người (hiện tại không có tùy chọn để người dùng chỉnh sửa địa chỉ của họ). Hãy cố gắng lưu vào bộ nhớ cache toàn bộ trang "home.html.erb" cho đến khi một sự kiện (bỏ phiếu) xảy ra.

Hãy sử dụng đá quý Dalli. Điều này sử dụng Memcached để nhanh chóng lưu trữ và truy xuất các đoạn thông tin. Memcached không có kiểu dữ liệu để lưu trữ, cho phép bạn lưu trữ về cơ bản bất kỳ thứ gì bạn thích.

1. Lượt xem trong bộ nhớ đệm

Thời gian tải cho 2000 bản ghi mà không có bộ nhớ đệm, là 3500ms!

Hãy lưu mọi thứ vào bộ nhớ cache trong "home.html.erb". Thật đơn giản,

<% cache do %>
  <ul>
    <% @people.each do |person| %>
      <li id="<%= person.id %>"><%= render person %></li>
    <% end %>
  </ul>
<% end %>

Tiếp theo, cài đặt đá quý Dalli và thay đổi kho lưu trữ bộ nhớ cache trong "development.rb" thành:

config.cache_store = :dalli_store

Sau đó, nếu bạn đang sử dụng Mac hoặc Linux, chỉ cần khởi động dịch vụ Memcached như sau:

memcached -vv

Bây giờ hãy tải lại !!

Điều đó mất khoảng 537ms! Đó là sự cải thiện gấp 7 lần về tốc độ!

Bạn cũng sẽ thấy rằng có ít truy vấn MySQL hơn vì toàn bộ HTML đã được lưu trữ trong Memcached và được đọc lại từ đó mà không cần ping đến cơ sở dữ liệu của bạn.

Nếu bạn truy cập nhật ký ứng dụng của mình, bạn cũng sẽ thấy rằng toàn bộ trang này đã được đọc từ bộ nhớ đệm.

Tất nhiên, ví dụ này chỉ là làm xước bề mặt của bộ nhớ đệm chế độ xem. Bạn có thể lưu vào bộ nhớ cache kết xuất từng phần và phân bổ nó cho từng đối tượng người (đây được gọi là bộ nhớ đệm phân đoạn) hoặc bạn có thể lưu vào bộ nhớ đệm toàn bộ bộ sưu tập (đây được gọi là bộ nhớ đệm bộ sưu tập). Hơn nữa để có nhiều kết xuất chế độ xem lồng nhau hơn, bạn có thể thực hiện bộ nhớ đệm của Russian Doll.

2. Truy vấn cơ sở dữ liệu bộ nhớ đệm

Một tối ưu hóa khác mà bạn có thể làm để cải thiện tốc độ xem là lưu vào bộ đệm các truy vấn cơ sở dữ liệu phức tạp. Nếu ứng dụng của bạn hiển thị số liệu thống kê và phân tích, rất có thể bạn đang thực hiện một truy vấn cơ sở dữ liệu phức tạp để tính toán từng số liệu. Bạn có thể lưu trữ kết quả đầu ra của nó vào Memcached và sau đó ấn định thời gian chờ cho nó. Điều này có nghĩa là sau thời gian chờ, phép tính sẽ được thực hiện lại và sau đó được lưu trữ vào bộ nhớ đệm.

Ví dụ:giả sử rằng ứng dụng cần hiển thị kích thước của một nhóm người dùng. Đây có thể là một phép tính phức tạp liên quan đến số lượng người đại diện trực tiếp, chuyên gia tư vấn thuê ngoài và hơn thế nữa.

Thay vì lặp đi lặp lại phép tính, bạn có thể lưu vào bộ nhớ cache!

def team_size
  Rails.cache.fetch(:team_size, expires_in: 8.hour) do
    analytics_client = AnalyticsClient.query!(self)
    analytics_client.team_size
  end
end

Bộ nhớ cache này sẽ tự động hết hạn sau 8 giờ. Sau khi điều đó xảy ra, phép tính sẽ được thực hiện lại và giá trị mới nhất sẽ được lưu vào bộ nhớ đệm trong 8 giờ tiếp theo.

3. Chỉ mục cơ sở dữ liệu

Bạn cũng có thể tăng tốc các truy vấn bằng cách sử dụng các chỉ mục. Một truy vấn đơn giản để tìm nạp tất cả địa chỉ của một người,

person.addresses

Truy vấn này yêu cầu bảng Địa chỉ trả về tất cả các địa chỉ mà person_id cột là person.id . Không có chỉ mục, cơ sở dữ liệu phải kiểm tra từng hàng riêng lẻ để kiểm tra xem nó có khớp với person.id không . Tuy nhiên, với các chỉ mục, cơ sở dữ liệu có một danh sách các địa chỉ khớp với một person.id nhất định .

Đây là một tài nguyên tuyệt vời để tìm hiểu thêm về các chỉ mục cơ sở dữ liệu!

Tóm tắt

Trong bài đăng này, chúng tôi đã khám phá cách cải thiện hiệu suất chế độ xem ứng dụng Rails của bạn bằng cách thực hiện các cải tiến đối với việc sử dụng cơ sở dữ liệu, sử dụng các công cụ và dịch vụ của bên thứ ba và hạn chế những gì người dùng nhìn thấy.

Nếu bạn đang tìm cách cải thiện hiệu suất ứng dụng của mình, hãy bắt đầu đơn giản và tiếp tục đo lường khi bạn tiếp tục! Dọn dẹp các truy vấn cơ sở dữ liệu của bạn, sau đó tạo các yêu cầu AJAX bất cứ nơi nào bạn có thể và cuối cùng là lưu vào bộ nhớ cache càng nhiều chế độ xem càng tốt. Sau đó, bạn có thể chuyển sang WebSockets và bộ nhớ đệm cơ sở dữ liệu.

Tuy nhiên, hãy thận trọng — tối ưu hóa là một con dốc trơn trượt. Bạn có thể thấy mình nghiện như tôi!

Tái bút. Để theo dõi hiệu suất của ứng dụng Rails của bạn trong quá trình sản xuất, hãy xem APM của AppSignal - được xây dựng bởi các nhà phát triển Ruby dành cho các nhà phát triển Ruby. 🚀