Ứng dụng Rails của bạn có chậm không?
Khi nó mất giây để tải cái gì đó se phải là view đơn giản, bạn có một vấn đề đáng đào sâu.
Bạn có thể có quá nhiều lời gọi cơ sở dữ liệu hoặc một số phương thức chậm. Hoặc có thể là vòng lặp tăng tốc ai đó đặt trong mã và quên mất.
Bạn có thể tìm thấy nhiều công cụ giúp bạn tìm ra điều gì làm chậm ứng dụng của bạn. Vài tuần trước, tôi nói về rbtrace. Gem rpm của New Relic cũng đã giúp tôi tăng tốc ứng dụng.
Nhưng công cụ yêu thích của tôi để khám phá vấn đề hiệu năng làm nhiều hơn thế. Mặc định, nó chỉ cho bạn thấy mã của bạn đang làm gì. Nhưng khi bạn thêm plugin vào nó, nó trở nên mạnh mẽ hơn. Nó giúp bạn thấy vấn đề hiệu năng ứng dụng, trực quan. Và điều đó có thể giúp bạn tìm và sửa ứng dụng chậm, nhanh hơn.
Profiler Rails yêu thích của tôi
Công cụ hiệu năng Rails yêu thích của tôi gọi là rack-mini-profiler. Khi bạn thêm gem đó vào ứng dụng, bạn nhận được một chỉ báo nhỏ trên mỗi trang. Nó trông như thế này:

Nếu bạn nhấp vào hộp đó, nó mở rộng và bạn có thể thấy mọi thứ tuyệt vời. Câu lệnh SQL nào được chạy, mất bao lâu để render partial, và hơn thế nữa:

MiniProfiler cho bạn một nhắc nhở liên tục về mỗi trang mất bao lâu để tải. Điều đó giúp bạn học thêm về cách ứng dụng của bạn đang thực hiện. bạn sẽ xây dựng cảm giác trực giác về trang nào chậm, trang nào nhanh. Bạn sẽ bắt đầu nhận ra khi một trang mất thời gian đáng ngạc nhiên để render. Và bạn có thể bắt đầu sửa nó ngay lập tức, trong khi nó vẫn còn trong đầu bạn.
MiniProfiler có thể làm hơn thế. Nhưng trước, bạn sẽ phải cài gem flamegraph.
Khi bạn làm điều đó, bạn sẽ mở khóa một cách mới để thấy hiệu năng ứng dụng của bạn.
Flamegraph: đúng như tên gọi
Một flamegraph trông như thế này:

Rõ ràng tên gọi đến từ đâu, phải không?
Sau khi bạn cài gem rack-mini-profiler và gem flamegraph, bạn có thể thấy flamegraph cho bất kỳ request nào của bạn. Chỉ cần thêm pp=flamegraph làm tham số HTTP, trông sẽ như thế này:
https://www.example.com/restaurants?pp=flamegraph
Flamegraph sẽ bật lên, và bạn có thể zoom in/out, cuộn quanh, và cố gắng tìm điều thú vị để khám phá.
Mỗi "layer" trong flamegraph là một dòng trong stack trace:

Và trục ngang là thời gian. Vì vậy bên trái xa của biểu đồ là khi request bắt đầu, và bên phải xa là khi request kết thúc.
Vậy, nó trông chắc chắn cool. Nhưng bạn có thể làm gì với flamegraph?
Cách dùng flamegraph
Bởi vì trục X biểu diễn thời gian, bạn có thể thực sự có bức tranh rõ ràng về nơi ứng dụng của bạn bị kẹt. Các layer rộng nhất mất nhiều thời gian nhất để chạy. Chúng là khu vực đầu tiên bạn nên nhìn vào, vì tăng tốc chúng có thể có tác động lớn nhất.
Ứng dụng của bạn mất bao nhiêu thời gian render view? Trong controller action? Chạm database? Render partial?
Tất cả những điều đó rất dễ thấy, trực quan:

Có một điều hữu ích khác flamegraph có thể chỉ cho bạn:
Bạn có thấy một đống spike đều có chiều cao gần như giống nhau, như thế này không?

Điều đó thường có nghĩa là bạn có một loại truy vấn N+1. Bạn thiếu includes ở đâu đó, hoặc đang làm một đống cuộc gọi API. Nếu bạn thêm includes, bạn sẽ nhận được flamegraph trông hơn như thế này:

Truy vấn N+1 SQL khá dễ thấy với hầu hết công cụ hiệu năng: bạn chỉ tìm lời gọi SQL trông giống nhau. Nhưng vấn đề N+1 không phải SQL, như chạm API quá nhiều lần, khó nhận ra hơn nhiều. Đặc biệt nếu logging của bạn không tốt.
Với flamegraph, tuy nhiên, những vấn đề đó dễ thấy hơn nhiều.
Điều không nên chú ý
Flamegraph có thể overwhelming. Chúng cho bạn rất nhiều thông tin, và bạn gần như bị ép phải nhận tất cả cùng lúc. Vậy bạn có thể bỏ qua gì?
Thường thì bạn có thể bỏ qua layer dưới cùng và trên cùng của biểu đồ. Thay vào đó, tôi bắt đầu khám phá quanh giữa biểu đồ, hoặc có thể 3/4 đường đến đỉnh. Đó là nơi mã của tôi thường hang out.
Đỉnh biểu đồ thường liên quan ActiveRecord hoặc IO, và đáy là mã framework Rails, nên hợp lý rằng mã của bạn sẽ ở đâu đó về phía giữa.
Bạn đã dùng flamegraph bao giờ? Chúng là cách tuyệt vời để tìm nơi tốt nhất để tối ưu. Vậy hãy thử! Thêm gem rack-mini-profiler và flamegraph vào Gemfile. Bạn sẽ ngạc nhiên về bao nhiêu insight thêm bạn nhận được vào mã của bạn.