Dù .NET Core nổi tiếng với hiệu năng cao và khả năng mở rộng tốt, nhưng các vấn đề tiềm ẩn vẫn có thể làm giảm hiệu suất ứng dụng nếu không được phát hiện và xử lý kịp thời. Dưới đây là những nguyên nhân phổ biến và giải pháp tương ứng:​


1. Truy vấn cơ sở dữ liệu kém hiệu quả

  • Vấn đề: Sử dụng lazy loading quá mức, gặp lỗi N+1 trong Entity Framework, thiếu chỉ mục trên các cột thường xuyên truy vấn.​
  • Hậu quả: Thời gian truy vấn tăng, số lượng truy vấn không cần thiết, dẫn đến độ trễ cao.​
  • Giải pháp:
    • Sử dụng eager loading với .Include() để tải dữ liệu liên quan trong một truy vấn.
    • Chỉ truy vấn các trường cần thiết bằng .Select().
    • Đảm bảo các cột được lọc hoặc join có chỉ mục phù hợp.​

2. Tuần tự hóa JSON không tối ưu

  • Vấn đề: Sử dụng các thư viện tuần tự hóa mặc định không hiệu quả với payload lớn, thực hiện tuần tự hóa/giải tuần tự hóa không cần thiết.​
  • Hậu quả: Tăng sử dụng CPU và bộ nhớ.​
  • Giải pháp:
    • Sử dụng System.Text.Json thay vì Newtonsoft.Json để cải thiện hiệu suất.
    • Sử dụng DTOs để chỉ gửi dữ liệu cần thiết.​

3. Bỏ qua lập trình bất đồng bộ

  • Vấn đề: Sử dụng các lệnh đồng bộ trong ứng dụng chủ yếu bất đồng bộ, quên sử dụng asyncawait cho các thao tác I/O.​
  • Hậu quả: Thiếu tài nguyên luồng trong các tình huống đồng thời cao, tăng thời gian phản hồi.​
  • Giải pháp:
    • Đảm bảo tất cả các thao tác I/O đều bất đồng bộ.
    • Sử dụng công cụ như Async Fixer để xác định mã đồng bộ không tối ưu.​

4. Cấu hình Dependency Injection (DI) không phù hợp

  • Vấn đề: Đăng ký dịch vụ với vòng đời không đúng, tiêm các phụ thuộc không cần thiết.​
  • Hậu quả: Rò rỉ bộ nhớ do các đối tượng scoped hoặc transient tồn tại lâu, tăng sử dụng CPU do tạo đối tượng dư thừa.​
  • Giải pháp:
    • Sử dụng vòng đời phù hợp: Singleton cho dịch vụ dùng chung, Scoped cho dịch vụ theo yêu cầu, Transient cho dịch vụ nhẹ, ngắn hạn.
    • Kiểm tra và loại bỏ các phụ thuộc không cần thiết.​

5. Bỏ qua nén phản hồi

  • Vấn đề: Gửi phản hồi API lớn mà không nén, lãng phí băng thông.​
  • Hậu quả: Thời gian phản hồi chậm, đặc biệt trên mạng di động.​
  • Giải pháp:
    • Kích hoạt middleware nén phản hồi: csharpSao chépChỉnh sửabuilder.Services.AddResponseCompression(); app.UseResponseCompression();

6. Chiến lược caching kém

  • Vấn đề: Thiếu hoặc sử dụng caching không hiệu quả, lạm dụng caching trong bộ nhớ mà không có chính sách loại bỏ.​
  • Hậu quả: Xử lý lại các yêu cầu giống nhau, áp lực bộ nhớ, có thể dẫn đến sự cố.​
  • Giải pháp:
    • Triển khai caching trong bộ nhớ cho dữ liệu truy cập thường xuyên: csharpSao chépChỉnh sửavar cachedData = memoryCache.GetOrCreate("key", entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5); return FetchData(); });
    • Sử dụng caching phân tán (ví dụ: Redis) để mở rộng trên nhiều máy chủ.​

7. Ghi log quá mức

  • Vấn đề: Ghi log chi tiết trong môi trường sản xuất, ghi log đồng bộ.​
  • Hậu quả: Tăng độ trễ I/O và chi phí lưu trữ.​
  • Giải pháp:
    • Sử dụng các công cụ ghi log có cấu trúc như Serilog hoặc NLog.
    • Cấu hình mức độ log phù hợp cho từng môi trường.​

8. Middleware không hiệu quả

  • Vấn đề: Quá nhiều middleware, middleware thực hiện công việc không cần thiết cho mỗi yêu cầu.​
  • Hậu quả: Tăng độ trễ yêu cầu.​
  • Giải pháp:
    • Tối ưu thứ tự middleware, đặt middleware thường dùng (ví dụ: xác thực) lên trước.
    • Tránh middleware dư thừa bằng cách hợp nhất chức năng khi có thể.​

9. Bỏ qua profiling và kiểm tra hiệu năng

  • Vấn đề: Thiếu thông tin về các điểm nghẽn hiệu năng, vấn đề chỉ được phát hiện khi đã triển khai.​
  • Hậu quả: Hành vi ứng dụng không thể đoán

Link gốc: https://dotnetfullstackdev.medium.com/hidden-performance-killers-in-your-net-core-application-can-we-mute-them-with-our-skills-490a453638ac