10 điểm bởi GN⁺ 2024-12-29 | 3 bình luận | Chia sẻ qua WhatsApp

#9512 - Rewrite It in Rust

  • Fish shell đã được viết lại bằng Rust. Không còn mã C++ nào và gần như 100% là Rust thuần
  • Khoảng 2 năm trước, một PR (#9512) đã được mở để chuyển Fish từ C++ sang Rust
  • Fish trước đây cũng từng chuyển từ C sang C++, nhưng lần chuyển sang Rust là một dự án lớn hơn nhiều

Vấn đề với C++

  • Khác biệt về công cụ và trình biên dịch: Công cụ của C++ không tốt, và việc áp dụng các tiêu chuẩn C++ mới khiến mọi thứ trở nên phức tạp với những người đóng gói gói phần mềm và cộng tác viên.
  • An toàn luồng: Việc thực thi lệnh nội bộ của Fish hiện diễn ra theo kiểu tuần tự, và để thêm prompt bất đồng bộ hoặc tính năng hoàn thành không chặn thì cần xử lý song song.
  • Độ phức tạp của ngôn ngữ: Header file, template và xử lý chuỗi của C++ đều phức tạp và không an toàn.
  • Cộng đồng: C++ không thu hút được nhiều người đóng góp.
  • Vấn đề phụ thuộc: Đã có nhiều phiền toái do tính thiếu ổn định và lỗi build của một số thư viện C nhất định (curses).

Lý do chọn Rust

  • Niềm vui và sự hứng thú: Fish là một dự án sở thích, nên cần một ngôn ngữ vui và thú vị. Rust hấp dẫn hơn với người đóng góp.
  • Công cụ tuyệt vời: Có thể cài trình biên dịch đơn giản bằng rustup, và thông báo lỗi rất rõ ràng.
  • Tính tiện dụng: Cung cấp hệ thống use tường minh và các tính năng an toàn như OptionResult
  • Thiết kế ngôn ngữ tốt: Hệ thống con trỏ và option của Rust an toàn hơn C++ rất nhiều
  • Hỗ trợ xử lý song song: SendSync của Rust cho phép xử lý song song an toàn.
  • Quản lý phụ thuộc: Có thể dễ dàng thêm hỗ trợ cho các định dạng bên ngoài như YAML, JSON, v.v.

Hỗ trợ nền tảng

  • Hầu hết các nền tảng chính như macOS, Linux, BSD đều được hỗ trợ, còn hỗ trợ native cho Windows không phải là mục tiêu
  • Fish là một shell lấy UNIX làm trung tâm, tập trung vào API UNIX và ngôn ngữ script hơn là môi trường Windows

Quá trình port

  • Fish được chuyển dần từ C++ sang Rust theo cách "con cá của Theseus". Các thành phần được chuyển từng phần sang Rust, đồng thời thiết lập để C++ và Rust cùng tồn tại
    • Con tàu Theseus (Ship of Theseus): “Nếu thay toàn bộ những tấm ván gỗ của một con tàu bằng ván mới, liệu nó vẫn còn là cùng một con tàu?”
  • Sử dụng FFI: Dùng autocxx để tạo binding giữa C++ và Rust, rồi port từng thành phần một.
  • Port quy mô lớn: Một số phần nhất định (ví dụ như xử lý I/O) được chuyển độc lập để giảm mã FFI phức tạp
  • Cải thiện công cụ: Trong quá trình port, autocxx đã được tùy biến để giải quyết các vấn đề tương tác giữa Rust và C++

Dòng thời gian

  • Tháng 1/2023: Mở PR ban đầu
  • Tháng 1/2024: Loại bỏ hoàn toàn mã C++
  • Tháng 12/2024: Phát hành bản beta Fish 4.0

Xung đột với Rust

  • Vấn đề về tính di động: Cách tiếp cận #[cfg(...)] của Rust kém hiệu quả khi xử lý khác biệt hệ thống ở mức thấp
  • Bản địa hóa: Chuỗi định dạng của Rust được kiểm tra ở thời điểm biên dịch nhưng lại không thể dịch được
  • Thời gian build: Việc dùng LTO và bản build release mặc định có thể khiến thời gian build kéo dài
  • Trong quá trình port đã có một vài sai sót, nhưng phần lớn đều được giải quyết dễ dàng.

Thành tựu chính

  • Loại bỏ curses: Thay thế cơ sở dữ liệu terminfo bằng Rust crate để giải quyết trạng thái toàn cục và các vấn đề build
  • Tệp thực thi đơn: Có thể tạo binary Fish bao gồm mọi phụ thuộc
    • Giúp gói Fish có thể tự cài đặt, để người dùng dễ sử dụng hơn
  • Cải thiện hiệu năng: Tối ưu hóa mức dùng bộ nhớ và giúp việc thêm tính năng mới trở nên dễ dàng hơn

Hạn chế

  • Chưa thể loại bỏ hoàn toàn CMake
  • Ngừng hỗ trợ Cygwin: vì không có target Rust
  • Trên Windows vẫn chỉ có thể chạy qua WSL

Hiện tại và tương lai

  • Fish 4.0 đã được port thành công và hiệu năng được cải thiện.
  • Fish vẫn là một UNIX shell, và việc chuyển sang Rust cho phép bổ sung các tính năng mới.
  • Giờ đây dự án đã có một codebase hoàn toàn chuyển sang Rust, giúp việc bảo trì và thêm tính năng dễ dàng hơn trước. Có thể tận dụng các ưu điểm của Rust để bổ sung tính năng mới
  • Quá trình chuyển đổi lần này đã hoàn tất thành công và tạo ảnh hưởng tích cực cho cả người đóng góp lẫn người dùng

3 bình luận

 
annyeong 2024-12-30

Tôi thích tính dễ dùng của fish, nhưng vì các vấn đề như tính tương thích và hiệu năng nên tôi đang cấu hình zsh sao cho giống fish nhất có thể để dùng. Không biết fish đã thay đổi sẽ như thế nào, khá đáng mong đợi 👀

 
GN⁺ 2024-12-29
Ý kiến Hacker News
  • Chúc mừng đội ngũ Fish; các chi tiết của dự án rất thú vị. Tò mò không biết đây có phải là dự án lớn nhất đã chuyển hoàn toàn từ C++ sang Rust hay không. Điều này có thể là bài học hữu ích cho các dự án khác

    • Fish đã không phát hành như một chương trình lai giữa C++ và Rust, vì giai đoạn kiểm thử cuối cùng chưa hoàn tất
    • Có người không hiểu động lực thêm tính năng C++ vào Rust, nhưng đây có thể trở thành một nghiên cứu tình huống hay
    • Có ý kiến cho rằng sẽ rất tốt nếu có thể viết mã Rust mới trong một codebase C++
  • Điểm bất mãn lớn với Rust là hỗ trợ phát hiện phiên bản. Phát hiện tính năng phù hợp hơn cho bản phân phối, trình duyệt web và trình biên dịch

    • Phát hiện phiên bản/tên gọi là lý do Chrome và IE giả làm Mozilla, và Clang giả làm GCC. Phát hiện tính năng không gây ra những vấn đề đó
  • Một trong các mục tiêu của việc port là loại bỏ CMake, nhưng đã thất bại. Cargo rất tuyệt cho việc build nhưng còn đơn giản với việc cài đặt. Fish có nhiều script và tài liệu nên không phù hợp với trường hợp sử dụng của Cargo

    • Thay vì để Cargo mở rộng cho các trường hợp sử dụng này, có ý kiến muốn một công cụ khác được triển khai hơn
  • Vài năm trước khi chuyển từ bash sang zsh thì đã rất hài lòng, nhưng khi thử fish trên một máy tính mới, zsh lại có cảm giác rườm rà và lỗi thời. Khuyên nên thử dùng fish trong vài tuần

  • Thật đáng tiếc khi không hỗ trợ Cygwin. Hy vọng Rust sẽ hỗ trợ Cygwin như một mục tiêu build

  • Khâm phục nỗ lực của đội ngũ Fish và mong chờ xem dự án sẽ phát triển ra sao

  • Tò mò không biết những người đóng gói bản phân phối sẽ thấy việc đóng gói Rust-fish theo hướng dẫn Debian dễ đến mức nào

  • Chúc mừng đội ngũ Fish; đây là ý kiến cho rằng shell tốt nhất nay còn trở nên tốt hơn. Có đề xuất cập nhật tagline của dự án thành "Finally, a shell for the 00s!"

  • Sau khi chuyển từ zsh sang Fish, việc cấu hình đã đơn giản hơn và Fish hoạt động đúng như kỳ vọng, nên không có ý định đổi lại nữa

  • Macro cfg! được biên dịch thành true/false, vì vậy mã bên trong guard if phải được biên dịch. Nếu biên dịch mà không có my_feature thì có thể sẽ thất bại

  • Fish sử dụng thread cho tự động hoàn thành và tô sáng cú pháp, đồng thời có một dự án dài hạn nhằm bổ sung tính đồng thời vào ngôn ngữ