Tối Ưu Hiệu Suất

Leo thang từ khách hàng về việc chậm chạp là một trong những khoảnh khắc căng thẳng nhất trong một dự án outsourcing. Ứng dụng cảm thấy ổn trong staging, nhưng dưới traffic thực, thời gian phản hồi API tăng gấp ba và người dùng đang phàn nàn. Các performance agent của Sun Agent Kit phân tích ứng dụng của bạn một cách có hệ thống — xác định N+1 query, index bị thiếu, blocking I/O, và memory leak — sau đó sinh ra các bản sửa cụ thể, có mục tiêu mà codebase của bạn cần, không phải danh sách chung chung “hãy cân nhắc caching.”

Tổng Quan

Mục tiêu: Chẩn đoán nguyên nhân gốc rễ của regression hiệu suất, triển khai bản sửa có mục tiêu, và xác nhận cải tiến
Thời gian: 30–60 phút (so với 4–12 giờ profiling thủ công và thử sai)
Agent sử dụng: debugger, scout, implementer, tester
Lệnh: /sk:debug, /sk:scout, /sk:cook, /sk:test

Yêu Cầu Trước Khi Bắt Đầu

  • Sun Agent Kit đã được cài đặt và xác thực (hướng dẫn cài đặt)
  • Quyền truy cập vào application log hoặc file log với slow request trace
  • Truy cập cơ sở dữ liệu để phân tích query (read-only credential là đủ)
  • Một kịch bản có thể tái tạo — URL path, payload, và tốc độ request xấp xỉ gây ra chậm
  • Tùy chọn: APM data export (Datadog, New Relic, hoặc application-level timing log)

Quy Trình Từng Bước

Bước 1: Profile ứng dụng và xác định bottleneck

Bắt đầu bằng cách cung cấp cho agent triệu chứng — một URL endpoint chậm hoặc một đoạn log — và để nó xác định nguồn gốc.

/sk:debug "API endpoint GET /api/products is returning in 3-8 seconds. Normal was 200ms. Traffic increased 3x last week."

Điều gì xảy ra: Agent thực hiện:

  1. Phân tích mô tả triệu chứng và xác định endpoint bị ảnh hưởng cùng baseline mong đợi
  2. Truy vết đường dẫn request từ controller qua service đến database query
  3. Phân tích pattern query để tìm N+1 query, index bị thiếu, và result set không giới hạn
  4. Kiểm tra caching layer và xác định synchronous I/O trong hot path
  5. Tạo phân tích nguyên nhân gốc rễ với các phát hiện được ưu tiên

Bước 2: Scout toàn bộ codebase để tìm các vấn đề hiệu suất khác

Mở rộng phạm vi tìm kiếm để phát hiện các vấn đề tiềm ẩn trước khi chúng trở thành leo thang tiếp theo.

/sk:scout "N+1 query, SELECT *, missing pagination, synchronous I/O, no cache, unbounded loop"

Điều gì xảy ra: Agent thực hiện:

  1. Quét codebase để tìm các anti-pattern hiệu suất phổ biến
  2. Ưu tiên các phát hiện theo tác động (HIGH cho N+1 trong hot path, LOW cho admin view)
  3. Tạo roadmap sửa lỗi lưu vào plans/reports/

Bước 3: Sửa N+1 query bằng eager loading

Agent viết lại các query bị ảnh hưởng để dùng join hoặc eager loading, phù hợp với idiom ORM đã có trong codebase của bạn.

/sk:cook "Fix N+1 queries in ProductController, OrderController, and UserController — use eager loading per the ORM conventions in this project"

Điều gì xảy ra: Agent thực hiện:

  1. Phát hiện ORM đang dùng (Eloquent, Prisma, TypeORM, v.v.) và áp dụng eager loading theo idiom
  2. Viết lại query để include các model liên quan trong một lần gọi database
  3. Thêm pagination ở những nơi result không bị giới hạn
  4. Chạy test để xác minh không có regression

Bước 4: Thêm database index cho các cột traffic cao

Agent đọc migration history của bạn, xác định các index bị thiếu trên foreign key và các cột được filter thường xuyên, và sinh các file migration.

/sk:cook "Add missing database indexes for performance — analyze the schema and generate migrations"

Điều gì xảy ra: Agent thực hiện:

  1. Phân tích schema để tìm foreign key, cột trong mệnh đề WHERE, và cột ORDER BY không có index
  2. Sinh file migration với định nghĩa index phù hợp
  3. Ước tính tác động của mỗi index lên các pattern query phổ biến

Bước 5: Triển khai caching layer

Thêm Redis caching vào các endpoint traffic cao nhất, với TTL phù hợp và cache invalidation hook.

/sk:cook "Add Redis caching to GET /api/products and GET /api/categories — 5 minute TTL, invalidate on product or category write"

Điều gì xảy ra: Agent thực hiện:

  1. Kiểm tra cấu hình Redis trong môi trường dự án
  2. Áp dụng cache-aside pattern cho các endpoint được chỉ định với cache key được tham số hóa
  3. Thêm cache invalidation hook trên các write operation (create, update, delete)
  4. Viết test cho cache hit, cache miss, và invalidation scenario

Bước 6: Xác nhận cải tiến

Chạy bộ test và xác minh các tối ưu hóa hoạt động đúng.

/sk:test "run all tests and verify no regressions from performance optimizations"

Điều gì xảy ra: Agent chạy bộ test đầy đủ bao gồm test cache và query mới, và báo cáo bất kỳ lỗi nào.

Ví Dụ Hoàn Chỉnh: Thời Gian Phản Hồi API Tăng Sau Traffic Spike

Tình huống

API danh mục sản phẩm của một khách hàng e-commerce Nhật Bản hoạt động tốt trong giai đoạn pilot — vài trăm người dùng đã đăng ký, thời gian phản hồi nhanh. Lần ra mắt chính thức mang lại hàng nghìn người dùng trong 48 giờ. Đến ngày thứ hai, PM của khách hàng có mặt trên Slack của bạn: “Trang sản phẩm mất 5–8 giây để tải. Một số request bị timeout hoàn toàn. Vui lòng sửa ngay lập tức.” Team của bạn chưa bao giờ thấy môi trường production dưới load thực. Bạn không có APM tooling được cấu hình.

Chuỗi lệnh sử dụng

# 1. Chẩn đoán — cung cấp triệu chứng cho agent
/sk:debug "Product catalog API (GET /api/v1/products) degraded from 200ms to 5-8s after launch. Timeouts occurring under load. No APM data available."

# 2. Performance audit đầy đủ để tìm tất cả vấn đề liên quan
/sk:scout "N+1 query, missing index, missing pagination, synchronous I/O, no cache, unbounded loop"

# 3. Sửa các vấn đề có tác động cao nhất trước
/sk:cook "Fix N+1 queries in product catalog — use eager loading per ORM conventions"
/sk:cook "Add database indexes on foreign keys and frequently filtered columns"

# 4. Thêm caching layer
/sk:cook "Add Redis caching to product list and product detail endpoints — tag-based invalidation on product write events"

# 5. Thêm pagination để ngăn chặn result set không giới hạn
/sk:cook "Add cursor-based pagination to GET /api/v1/products — default page size 20, max 100"

# 6. Chạy test toàn bộ
/sk:test "run full test suite after performance optimizations"

Kết quả

Trong vài giờ sau khi leo thang, API trở về thời gian phản hồi nhanh dưới load. Khách hàng nhận được một báo cáo giải thích các nguyên nhân gốc rễ cụ thể và các thay đổi đã thực hiện. PM phản hồi: “Cảm ơn vì phản hồi nhanh. Vui lòng thêm monitoring để chúng tôi phát hiện sớm hơn lần sau.” Đó là cuộc trò chuyện về scope mở rộng, không phải khủng hoảng.

So Sánh Thời Gian

Tác vụThủ côngVới Sun Agent Kit
Đọc code để tìm query chậm60 phútvài phút
Xác định pattern N+1 thủ công45 phútvài phút
Nghiên cứu và viết index migration30 phútvài phút
Thiết kế và triển khai cache layer90 phútvài phút
Viết cache invalidation logic30 phútvài phút
Viết báo cáo hiệu suất cho khách hàng30 phútvài phút
Tổng cộng~5 giờdưới 30 phút

Bảng Mục Tiêu Hiệu Suất

Dùng các mục tiêu này làm acceptance criteria khi đóng ticket hiệu suất:

Loại Endpointp50 chấp nhận đượcp95 chấp nhận đượcp99 tối đa
List (có pagination, có cache)< 100ms< 200ms< 500ms
List (có pagination, không cache)< 300ms< 600ms< 1,000ms
Detail (một record)< 80ms< 150ms< 300ms
Write (create/update)< 200ms< 400ms< 800ms
Search (full-text)< 500ms< 1,000ms< 2,000ms
Report / aggregation< 2,000ms< 5,000ms< 10,000ms

Thực Hành Tốt Nhất

1. Luôn đo trước khi tối ưu — lấy con số baseline ✅

Agent yêu cầu mô tả triệu chứng trước khi sinh bất kỳ bản sửa nào. Nếu bạn bỏ qua profiling và nhảy vào “thêm Redis khắp nơi,” bạn có thể cache nhầm thứ và che đi vấn đề thực sự. Yêu cầu một số liệu cụ thể: “3.200ms trung bình trên GET /api/products dưới 50 người dùng đồng thời” là chẩn đoán; “cảm thấy chậm” thì không phải.

2. Sửa N+1 query trước khi thêm caching ✅

Cache một query chậm không phải là giải pháp — đó là che giấu vấn đề. Một N+1 kích hoạt hàng trăm query mỗi request vẫn sẽ kích hoạt chúng mỗi lần cache miss, và trong workload write nặng, cache sẽ miss liên tục. Sửa query trước, sau đó thêm caching để giảm tải database hơn nữa.

3. Đừng cache database write để tăng tốc thời gian phản hồi ❌

Thật hấp dẫn khi “cache” một write operation bằng cách trả về thành công ngay lập tức và xử lý bất đồng bộ. Đây là pattern message queue, không phải cache — và triển khai sai tạo ra data loss. Nếu bạn cần xử lý async, dùng /sk:cook "add job queue" để scaffold tích hợp queue đúng cách, không phải ad-hoc in-memory cache.

4. Đừng đặt một TTL duy nhất cho tất cả dữ liệu cached ❌

Tên sản phẩm thay đổi không thường xuyên — TTL 10 phút là ổn. Giỏ hàng của người dùng thay đổi mỗi lần tương tác — cache nó 10 phút gây ra bug lost-cart. Agent mặc định TTL bảo thủ theo loại entity; xem xét và điều chỉnh chúng dựa trên tần suất write của bạn trước khi deploy.

Xử Lý Sự Cố

Vấn đề: Sau khi thêm index, query không nhanh hơn

Giải pháp: Chạy EXPLAIN ANALYZE trên query chậm để xác nhận index đang được dùng. Postgres và MySQL đôi khi bỏ qua index mới nếu statistics bị cũ. Chạy ANALYZE products; (Postgres) hoặc ANALYZE TABLE products; (MySQL) để cập nhật statistics. Nếu query planner vẫn bỏ qua index, agent có thể giúp thiết kế lại index để phù hợp tốt hơn với mệnh đề WHERE và ORDER BY của query.

Vấn đề: Redis caching hoạt động trong development nhưng gây ra stale data trong production

Giải pháp: Nguyên nhân phổ biến nhất là thiếu cache invalidation trên các write path bạn chưa tính đến. Chạy /sk:scout "find all write operations on the products table" để tìm tất cả những chỗ ghi vào bảng — mỗi chỗ đều cần cache invalidation hook. Agent sẽ liệt kê những cái bị bỏ sót.

Vấn đề: Load test cho thấy error rate cao ngay cả sau khi sửa

Giải pháp: Error rate cao dưới load thường chỉ ra connection pool exhaustion, không phải tốc độ query. Kiểm tra kích thước database connection pool (DB_POOL_SIZE trong .env). Một misconfiguration phổ biến là để pool ở mặc định 5 connection trên server xử lý 100+ request đồng thời. Đặt nó thành (2 × CPU cores) + number of disks làm điểm khởi đầu.

Vấn đề: Hiệu suất tốt dưới load test nhưng chậm với người dùng thực

Giải pháp: Load test dùng cùng endpoint và payload không nắm bắt được sự biến đổi của thế giới thực. Chạy /sk:debug "slow for specific users" và kiểm tra xem sự chậm có tương quan với những người dùng có dataset lớn (nhiều order, nhiều sản phẩm trong giỏ hàng). Giải pháp thường là thêm user_id index hoặc giới hạn phạm vi query đang vô tình load dữ liệu cross-user.

Bước Tiếp Theo

  • Đánh Giá Code — Phát hiện performance anti-pattern trong code review trước khi lên production
  • Tái Cấu Trúc Code Cũ — Tái cấu trúc cấu trúc thường giải quyết các vấn đề hiệu suất hệ thống mà bản vá điểm không thể tiếp cận
  • Kiểm Tra Bảo Mật — Chạy song song với công việc hiệu suất để đảm bảo tối ưu không đưa vào regression bảo mật

Điểm mấu chốt: Leo thang hiệu suất cảm thấy cấp bách vì chúng thực sự cấp bách — và con đường nhanh nhất từ API chậm trở lại thời gian phản hồi nhanh là profiling có hệ thống theo sau là các bản sửa có mục tiêu, không phải đoán mò và hy vọng.