Một bài viết gần đây thách thức hiệu quả của lockless queue đã châm ngòi cho cuộc tranh luận gay gắt trong cộng đồng lập trình, với các nhà phát triển đặt câu hỏi về cả những tuyên bố hiệu suất và các giả định thiết kế cơ bản được trình bày bởi tác giả.
Bài viết gốc lập luận rằng hầu hết các triển khai lockless queue đều có lỗi cơ bản và chậm, đề xuất một cấu trúc dữ liệu bag thay thế hoàn toàn từ bỏ đảm bảo thứ tự. Tuy nhiên, khẳng định này đã gặp phải sự phản đối mạnh mẽ từ các nhà phát triển có kinh nghiệm, những người chỉ ra dữ liệu hiệu suất thực tế mâu thuẫn với những tuyên bố này.
Các Con Số Hiệu Suất Kể Một Câu Chuyện Khác
Các thành viên cộng đồng nhanh chóng thách thức khẳng định lockless queue chậm bằng dữ liệu benchmark cụ thể. Các nhà phát triển làm việc với hệ sinh thái lockless queue của Rust báo cáo rằng các triển khai nhanh nhất có thể xử lý hơn 30 triệu phần tử mỗi giây, tương đương với chỉ 33 nanosecond mỗi phần tử. Ngay cả các triển khai chậm hơn cũng đạt khoảng 100 nanosecond mỗi phần tử, điều mà nhiều người coi là khá nhanh cho các hoạt động đồng thời.
Cuộc tranh luận trở nên gay gắt hơn khi tác giả gốc bảo vệ quan điểm của họ bằng cách trích dẫn benchmark của riêng họ cho thấy thời gian xử lý trung bình 250 nanosecond với contention nặng. Các nhà phê bình lập luận rằng điều này đại diện cho một triển khai cụ thể trong điều kiện cực đoan thay vì một sự buộc tội chung về công nghệ lockless queue.
So sánh hiệu suất Lockless Queue
- Các triển khai nhanh nhất: 30+ triệu phần tử/giây (33ns mỗi phần tử)
- Các triển khai chậm hơn: 5-10 triệu phần tử/giây (100ns mỗi phần tử)
- Benchmark của tác giả với mức độ tranh chấp cao: ~4 triệu phần tử/giây (250ns mỗi phần tử)
Tranh Cãi Về Định Nghĩa Queue
Một phần đáng kể của cuộc thảo luận tập trung vào việc thực sự cái gì cấu thành một queue trong môi trường đa luồng. Bài viết gốc tuyên bố rằng multi-consumer queue phá vỡ thứ tự toàn cục và do đó không phải là queue thực sự. Các thành viên cộng đồng mạnh mẽ không đồng ý với định nghĩa hẹp này, chỉ ra rằng các queue thực tế hiếm khi duy trì thứ tự xử lý toàn cục nghiêm ngặt.
Một nhà phát triển đã sử dụng phép so sánh về tòa thị chính với nhiều quầy phục vụ để minh họa quan điểm. Trong khi mọi người nhận vé theo thứ tự, họ có thể được phục vụ bởi các quầy khác nhau với tốc độ khác nhau, có khả năng hoàn thành dịch vụ không theo trình tự ban đầu. Điều này phản ánh cách multi-consumer queue hoạt động trong thực tế và phục vụ các trường hợp sử dụng hợp lệ.
Thách Thức Triển Khai Và Sự Đánh Đổi
Giải pháp thay thế bag được đề xuất đã gây hoài nghi từ các nhà phát triển quen thuộc với cấu trúc dữ liệu đồng thời. Các nhà phê bình lưu ý rằng triển khai bag vẫn yêu cầu các hoạt động atomic trên bitmask, điều này có thể tạo ra các nút thắt contention riêng của chúng. Thách thức cơ bản vẫn còn: bất kỳ cấu trúc dữ liệu chia sẻ nào được truy cập bởi nhiều luồng đều phải điều phối truy cập bằng cách nào đó.
Một số người bình luận nhấn mạnh rằng các biến thể queue khác nhau phục vụ các mục đích khác nhau. MPSC (multiple-producer, single-consumer) queue được sử dụng rộng rãi trong task scheduler, trong khi SPSC (single-producer, single-consumer) queue hoạt động tốt cho các pipeline xử lý tùy chỉnh. Sự lựa chọn phụ thuộc vào yêu cầu trường hợp sử dụng cụ thể thay vì đặc tính hiệu suất phổ quát.
Những cái nhanh nhất dễ dàng thực hiện ít nhất 30 triệu phần tử/giây trong hầu hết các cấu hình. Những cái chậm nhất khoảng 5-10. Vậy nên cái nhanh nhất đang thực hiện 33ns mỗi phần tử và cái chậm nhất là 100ns.
Các loại Queue và trường hợp sử dụng
- SPSC (Single-Producer Single-Consumer): Các pipeline xử lý tùy chỉnh
- MPSC (Multiple-Producer Single-Consumer): Bộ lập lịch tác vụ ( tokio , rayon )
- SPMC (Single-Producer Multiple-Consumer): Các trường hợp sử dụng hạn chế
- MPMC (Multiple-Producer Multiple-Consumer): Lập lịch tác vụ tổng quát
Ý Nghĩa Thực Tiễn Cho Các Nhà Phát Triển
Cuộc tranh luận tiết lộ những cân nhắc quan trọng cho các nhà phát triển khi chọn cấu trúc dữ liệu đồng thời. Trong khi bài viết gốc đưa ra những điểm hợp lý về đảm bảo thứ tự, phản hồi của cộng đồng nhấn mạnh rằng nhiều ứng dụng không yêu cầu thứ tự toàn cục nghiêm ngặt. Các tính năng như công bằng, tránh starvation, và hành vi có thể dự đoán thường quan trọng hơn tính nhất quán tuần tự hoàn hảo.
Cuộc thảo luận cũng làm nổi bật nguy hiểm của việc đưa ra những tuyên bố hiệu suất rộng rãi mà không có benchmark toàn diện qua các kịch bản và triển khai khác nhau. Những gì hoạt động tốt dưới một tập hợp điều kiện có thể gặp khó khăn dưới điều kiện khác, làm cho ngữ cảnh trở nên quan trọng cho các quyết định thiết kế.
Cuộc tranh cãi cuối cùng nhấn mạnh sự phức tạp của lập trình đồng thời và tầm quan trọng của việc hiểu cả các thuộc tính lý thuyết và đặc tính hiệu suất thực tế của các phương pháp khác nhau trước khi đưa ra quyết định kiến trúc.
Tham khảo: Your MPSC/SPMC/MPMC queue is not a queue