Algorithm Speed — Đừng chỉ code, hãy biết code chạy nhanh thế nào (Pragmatic Programmer #39)
Bài viết là một phần trong series cảm nhận về từng topic của cuốn sách "The Pragmatic Programmer" (20th Anniversary Edition) — cuốn sách gối đầu giường của biết bao lập trình viên trên thế giới.
Ảnh: Stanislav Kondratiev — Pexels
Mở đầu
Chào mấy bạn, lại là mình đây! Hôm nay mình tiếp tục series đọc "The Pragmatic Programmer" và cảm thấy cực kỳ hứng thú với Topic 39: Algorithm Speed.
Nghe cái tên thì có vẻ hàn lâm — "tốc độ thuật toán" — nhưng thực ra đây là một trong những topic thực tế nhất mà bất kỳ lập trình viên nào cũng cần nắm, dù bạn làm web, mobile, hay embedded. Bởi vì cuối cùng, code của bạn có chạy nhanh hay không, có đáp ứng được khi lượng dữ liệu tăng lên hay không, tất cả đều xoay quanh cái gọi là Big O notation.
Trong bài này, mình sẽ kể lại cảm nhận của mình về topic này, những điểm hay ho mà mình học được, và cách áp dụng nó vào công việc thực tế nha.
Ảnh: Simon Petereit — Pexels
Algorithm Speed — Tốc độ thuật toán
Topic 39 nằm trong Chapter 7: "While You Are Coding", và như cái tên gợi ý, nó nhắc nhở chúng ta rằng: trong lúc code, đừng quên ước lượng tốc độ của những gì mình đang viết.
Cuốn sách đưa ra một ví dụ kinh điển: giả sử bạn có một routine xử lý 100 records mất 1 giây. Khi lên 1.000 records, nó sẽ chạy thế nào?
- O(1) — Constant: Vẫn 1 giây. Bất chấp dữ liệu bao nhiêu.
- O(log n) — Logarithmic: ~3 giây. Tăng rất chậm.
- O(n) — Linear: 10 giây. Tỷ lệ thuận.
- O(n log n): ~33 giây. Phổ biến với các thuật toán sort tốt.
- O(n²) — Quadratic: 100 giây (gần 2 phút). Vòng lặp lồng nhau.
- O(n³) — Cubic: 1.000 giây (~17 phút).
- O(2ⁿ) — Exponential: 2^1000 giây — thiên văn!
Nghe quen không mấy bạn? Cái bảng này chắc ai học CS cũng từng thấy. Nhưng cái hay của Pragmatic Programmer là họ không chỉ dạy lý thuyết, mà còn chỉ cách ước lượng nhanh bằng common sense.
Thay vì ngồi tính toán phức tạp, bạn chỉ cần hỏi mấy câu đơn giản:
- Đoạn code này có vòng lặp lồng nhau không? → O(n²) hoặc hơn.
- Có chia đôi dữ liệu mỗi lần không? → O(log n) (binary search, balanced tree).
- Có duyệt qua từng phần tử một lần không? → O(n).
- Có kết hợp cả hai không? → O(n log n).
Tác giả còn khuyến khích: hãy tập ước lượng thường xuyên, như một bài tập cho não. Khi bạn đã quen, bạn sẽ "ngửi" được mùi code chậm chỉ bằng cách đọc qua, mà không cần chạy benchmark phức tạp.
Ảnh: Kindel Media — Pexels
Cảm nhận của mình
Mình thấy Topic 39 này đặc biệt hay vì một lý do: nó nhắc nhở mình rằng không phải lúc nào cũng cần tối ưu ngay từ đầu, nhưng phải luôn biết thứ gì đang chạy chậm và thứ gì sẽ không scale được.
Hồi mới đi làm, mình từng viết một cái API trả về danh sách sản phẩm. Lúc đó chỉ có vài trăm sản phẩm, chạy ngon lành. Ai dè mấy tháng sau lên tới 50.000, API bắt đầu chậm như rùa. Mình mò vô xem, té ra cái đoạn xử lý sort vs filter bị lồng vòng lặp vào nhau — O(n*m) và thậm chí còn tệ hơn. Nếu ngay từ đầu mình chịu khó ước lượng: "dữ liệu sẽ tăng thế nào trong 6 tháng tới? Thuật toán này có scale không?" thì đỡ đau đầu biết mấy.
Điểm mình tâm đắc nhất trong topic này là câu: "Estimate the order of your algorithms. Practice it. It's a skill that will serve you well."
Không phải ai cũng có cơ hội học thuật toán bài bản, và không phải dự án nào cũng cần bạn tối ưu từng dòng code. Nhưng biết cách ước lượng — đó là siêu năng lực của một pragmatic programmer.
Một điểm nữa: cuốn sách không khuyến khích tối ưu sớm (premature optimization) — cái đó đã có Topic khác nói rồi. Nhưng nó cũng không bảo bạn "kệ mẹ speed đi, code cho xong đã". Nó dạy bạn một lối đi giữa: biết trước cái gì sẽ đau đầu, để tránh ngay từ đầu.
Kết
Tóm lại, Topic 39 "Algorithm Speed" là một chủng loại bài học mà dân dev nào cũng nên đọc ít nhất một lần. Nó không quá dài, không đao to búa lớn, nhưng cực kỳ thực tế.
Bài học rút ra của mình hôm nay:
- Học thuộc lòng bảng Big O — ít nhất là các cấp độ cơ bản.
- Trong lúc code, dừng lại một chút và tự hỏi: "Đoạn này O gì?"
- Tập ước lượng mỗi ngày — dần dần bạn sẽ "nhìn" được tốc độ code.
- Không cần tối ưu sớm, nhưng đừng vô tình viết O(n³) khi chỉ cần O(n).
Hẹn mấy bạn ở bài sau với Topic 40: Refactoring. Đây cũng là chủ đề cực kỳ thú vị mà mình nghĩ ai code lâu năm cũng sẽ có nhiều chuyện để kể. 👋