Q

Quản trị viên

Là một lập trình viên yêu công nghệ, thích viết blog để chia sẻ kiến thức, kinh nghiệm lập trình và những điều thú vị trong thế giới tech.

2300 bài viết · Website
Giải thuật 03/09/2026 8 phút

Cùng một hàm constexpr: một chỗ chạy 0,227 ns, chỗ kia 45625 ns — khác nhau ở đâu?

Đánh dấu constexpr là chắc chắn tính sẵn lúc biên dịch, 0 chi phí? Tôi đo và phát hiện chữ đó hứa ít hơn tưởng. Đặt kết quả vào biến constexpr thì nó thành literal đọc 0,227 ns; gọi đúng hàm ấy với đầu vào động thì nó chạy nguyên vòng lặp lúc chạy, 45625 ns. Ngữ cảnh mới quyết định, không phải từ khóa.

Giải thuật 03/09/2026 6 phút

Benchmark của bạn đang nói dối: bốn cách bạn tự lừa mình khi đo tốc độ

Viết một vòng lặp, bọc đồng hồ hai đầu, chia cho số phần tử — nghe là xong. Nhưng cùng một đoạn code, tôi đo được 0 nano-giây (nhanh vô hạn), rồi 0,57, rồi 2,62 ns, tùy vào những cái bẫy mà trình biên dịch giăng sau lưng. Chỉ một cách đo là ra con số thật.

Hệ điều hành 03/09/2026 8 phút

fork một tiến trình 512MB chỉ tốn 28 micro giây — nhưng cái giá không mất, nó chỉ nấp ở lần ghi đầu tiên

fork một tiến trình 512MB chỉ tốn 28µs — nó không sao chép dữ liệu, chỉ chép bảng trang (nhanh hơn nghìn lần). Nhưng chi phí sao chép không mất, nó bị hoãn: ghi vào 64MB heap chung sau fork tốn 20,2ms với 16.419 COW fault, chậm ~200 lần ghi thường. Khi cái gì 'gần như miễn phí', hỏi tiếp chi phí đi đâu.

Giải thuật 03/09/2026 8 phút

Hai vòng lặp giống hệt về số phép — một cái chậm hơn 452 lần

Hai vòng lặp làm đúng cùng số phép load và cộng, cùng O(n) — đếm phép thì tưởng cùng tốc độ. Nhưng đo ra duyệt ngẫu nhiên chậm 452 lần duyệt tuần tự trên mảng 256 MB. Chi phí thật không nằm ở phép cộng mà ở truy cập bộ nhớ: cache và prefetch. Big-O mù hoàn toàn trước điều đó. Tôi đo bằng C.

Giải thuật 03/09/2026 9 phút

Bật hết -O3 -Ofast -march=native cho chắc? Đo ra chỉ một cờ nhanh thật — và nó đổi kết quả

Tưởng cứ -O3 -Ofast -march=native -funroll là nhanh nhất? Tôi đo một workload thật: -O3 bằng -O2, -march không đổi, -funroll chỉ 3%, chỉ -ffast-math nhanh 2,9 lần nhưng đổi kết quả số thực. Không có combo cờ thần — mỗi cờ là một đánh đổi phụ thuộc workload, và cách duy nhất chọn đúng là đo ở đúng máy, đúng cờ, đúng code của bạn.

Giải thuật 03/09/2026 10 phút

push_front vào vector: quả bom O(n) núp trên đường nóng

Cần thêm phần tử ở đầu danh sách? Nhiều người bảo dùng vector cũng được. Tôi đo thử — và vector push_front hóa ra là O(n): mỗi lần thêm gấp đôi thời gian khi số phần tử gấp đôi (1552 → 3375 ns), vì nó phải dịch cả mảng. Một ring buffer chỉ lùi một chỉ số, O(1) (~3 ns), nhanh hơn 1136 lần ở N=100k. Còn std::deque thì push được hai đầu O(1), duyệt chỉ chậm hơn vector 19%.