4 điểm bởi GN⁺ 2024-03-31 | 1 bình luận | Chia sẻ qua WhatsApp

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

 
GN⁺ 2024-03-31
Ý 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

    • Đã giành giải bài báo xuất sắc tại POPL 2024 và giải ACM SIGPLAN 2023
    • Các đề xuất chính như sau:
      • disentanglement dựa trên garbage collection song song có hiệu quả được chứng minh
      • Điều khiển độ hạt tự động có hiệu quả được chứng minh
  • Việc dùng RCU làm động lực cho garbage collection khá thú vị

    • Việc chuyển trách nhiệm giải phóng bộ nhớ từ worker ghi sang worker đọc cuối cùng là có ý nghĩa
    • Cũng có thể cần cân nhắc chuyển việc giải phóng bộ nhớ sang một tiến trình batch chuyên dụng thay vì để worker đọc xử lý nhằm cải thiện hiệu năng
  • Một số hiểu lầm phổ biến về quản lý bộ nhớ

    • Tin rằng lập trình viên biết thời gian tạm dừng tối ưu cho việc quản lý bộ nhớ
    • Trong game và chương trình giao dịch crypto, lập trình viên có thể thực sự biết thời gian tạm dừng tối ưu
  • 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

    • Điều này được đọc như một lập luận rằng các giải pháp quản lý bộ nhớ tùy biến có thể mang lại hiệu năng tốt nhất
    • Có thảo luận về sự hiểu lầm rằng lời gọi free() sẽ trả bộ nhớ lại cho OS
  • Khi dùng garbage collection, các lần cấp phát mới diễn ra từ RAM thay vì từ cache

    • Điều này có thể ảnh hưởng lớn đến hiệu năng
    • Có đưa ra ví dụ benchmark trong ngôn ngữ Julia
  • Garbage collection truy vết tốt đã vượt qua quản lý bộ nhớ thủ công về throughput từ lâu

    • Gần đây, độ trễ cũng đã ở mức chấp nhận được với phần lớn ứng dụng
    • Mức sử dụng bộ nhớ mới là yếu tố cần cân nhắc chính
  • Một trong những thứ kết hợp tốt với garbage collection là async/await

    • Trong Rust, việc dùng async/await kết hợp với quản lý bộ nhớ gây ra vấn đề
  • 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

    • Với hot path thì dùng allocator tùy biến, còn các phần khác thì garbage collection lại tiện lợi
  • 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

    • Quản lý bộ nhớ thủ công không chỉ đơn giản là gọi malloc/free
  • Vớ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 đề