Giới thiệu về RCU
- Hệ điều hành là một trong những chương trình nhạy cảm nhất về hiệu năng mà chúng ta sử dụng hằng ngày.
- Hệ điều hành luôn có thể nhanh hơn nữa, và các nhà phát triển kernel cùng driver không ngừng tối ưu hóa mã.
- Hệ điều hành đòi hỏi khả năng đồng thời ở quy mô lớn, lên lịch cho các tiến trình và luồng trong không gian người dùng, đồng thời có các luồng riêng và trình xử lý ngắt tương tác với phần cứng.
Cách RCU hoạt động
- Khi cần thay đổi một cách nguyên tử dữ liệu được đọc thường xuyên nhưng hiếm khi ghi (ví dụ: các thiết bị USB hiện đang được kết nối), người ta sử dụng chiến lược RCU (Read, Copy, Update).
- Đọc dữ liệu, sao chép rồi sửa đổi, sau đó cập nhật con trỏ sang phiên bản mới một cách nguyên tử.
- Cách này dễ dùng và không có độ trễ chờ, nhưng có thể gây rò rỉ bộ nhớ.
Giải quyết vấn đề rò rỉ bộ nhớ
- Để tránh rò rỉ bộ nhớ, thay vì xóa dữ liệu cũ ngay trong hàm cập nhật, có thể trì hoãn việc xóa cho đến khi không còn reader nào đang đọc.
- Trong khi reader đang đọc dữ liệu, writer sẽ chờ trước khi xóa dữ liệu, nhờ đó có thể quản lý bộ nhớ an toàn.
Ứng dụng thực tế của RCU
- RCU được dùng hàng chục nghìn lần trong Linux, và cũng được dùng trong thư viện C++ Folly của Facebook cũng như
crossbeam-epoch của Rust.
- RCU được thúc đẩy bởi các yêu cầu về hiệu năng và độ trễ trong đồng bộ hóa, đồng thời cung cấp một cách quản lý bộ nhớ tương tự garbage collection.
Những hiểu lầm về garbage collection
- Quan niệm phổ biến rằng garbage collection chậm hơn quản lý bộ nhớ thủ công nhanh chóng sụp đổ khi xem xét kỹ các chi tiết.
- Hàm
free() không hề miễn phí, và bộ cấp phát bộ nhớ phải duy trì rất nhiều trạng thái nội bộ.
- Garbage collector hiện đại cung cấp các tối ưu như di chuyển và phân thế hệ, nhờ đó đạt thông lượng cao và hiệu năng cache tốt.
Ảo giác về sự kiểm soát
- Các nhà phát triển đôi khi muốn xây dựng hệ thống thời gian thực, nhưng trên thực tế họ không có quyền kiểm soát hoàn hảo đối với việc quản lý bộ nhớ.
- Hệ điều hành chỉ có thể suy đoán ý định của nhà phát triển đối với việc cấp phát bộ nhớ, và đôi khi một thao tác truy cập con trỏ đơn giản có thể biến thành I/O đĩa.
Kết luận
- Không phải mọi phần mềm đều hưởng lợi từ garbage collection, nhưng đây là một công cụ hữu ích, và ngay cả các lập trình viên hệ thống cũng không nên còn e ngại nó nữa.
Ý kiến của GN⁺
- RCU là một kỹ thuật hiệu quả để tăng mức độ đồng thời trong khi vẫn duy trì tính nhất quán dữ liệu trong môi trường đa luồng. Đây là một yếu tố cực kỳ quan trọng trong điện toán hiệu năng cao hoặc các hệ thống thời gian thực.
- Ví dụ về RCU trong việc phá vỡ những quan niệm cố hữu về garbage collection mang đến cho các nhà phát triển một góc nhìn mới về quản lý bộ nhớ. Điều này càng đúng hơn trong lĩnh vực lập trình hệ thống, nơi việc quản lý bộ nhớ đặc biệt quan trọng.
- Những dự án khác cung cấp chức năng tương tự RCU có thể kể đến Java ConcurrentLinkedQueue hay .NET ConcurrentBag, và chúng cũng cung cấp các cấu trúc dữ liệu lock-free.
- Khi áp dụng công nghệ RCU, cần cân nhắc các yêu cầu của hệ thống và mục tiêu hiệu năng, đồng thời hiểu rõ lợi ích thu được cũng như các chi phí tiềm ẩn khi sử dụng kỹ thuật này.
- Bài viết này có thể giúp các nhà phát triển hiểu sâu hơn về quản lý bộ nhớ và tính đồng thời, xem xét lại những giả định hiện có và khám phá các giải pháp mới.
1 bình luận
Ý kiến Hacker News
Có đề xuất xem qua các kỹ thuật garbage collection (GC) song song mang tính đột phá cho MPL và MaPLe
disentanglementdựa trên garbage collection song song có hiệu quả được chứng minhViệc dùng RCU làm động lực cho garbage collection khá thú vị
Một số hiểu lầm phổ biến về quản lý bộ nhớ
Trường hợp sử dụng RCU khá thuyết phục, nhưng trải nghiệm với garbage collection trong các tình huống khác thì không tốt
free()sẽ trả bộ nhớ lại cho OSKhi dùng garbage collection, các lần cấp phát mới diễn ra từ RAM thay vì từ cache
Garbage collection truy vết tốt đã vượt qua quản lý bộ nhớ thủ công về throughput từ lâu
Một trong những thứ kết hợp tốt với garbage collection là async/await
Sau phần tạo động lực từ RCU, việc chuyển sang thảo luận về garbage collection nói chung có phần bất ngờ
Khi phát triển phần mềm thường cân nhắc hai trường hợp
Việc chuyển từ RCU sang garbage collection truy vết thông thường trong bài viết có vẻ là một chiến lược khá khéo
malloc/freeVới system programmer, việc xác định khi nào một đối tượng có thể được garbage collect là điều khó khăn
Các công cụ quản lý vòng đời trong Rust và C++ giúp tự động hóa việc giải phóng bộ nhớ, nhưng không làm đơn giản hóa độ phức tạp của vấn đề