Trung  Nguyen

Trung Nguyen

1658592000

Fleet: Một Công Cụ Xây Dựng để Cải Thiện Rust's Cargo

Theo Khảo sát Rust năm 2021 , thời gian biên dịch dài của Rust vẫn là một mối quan tâm lớn đối với các nhà phát triển và là một lĩnh vực cần cải thiện hơn nữa. Đặc biệt khi nói đến các dự án lớn hoặc thùng có nhiều phụ thuộc, việc Rust tập trung vào hiệu suất thời gian chạy hơn hiệu suất thời gian biên dịch trở nên khá nghiêm trọng, ngay cả trong các bản dựng gỡ lỗi. Điều này ảnh hưởng tiêu cực đến trải nghiệm của nhà phát triển và là lý do tại sao một số nhà phát triển vẫn không muốn dùng thử Rust.

Trong mọi trường hợp, thời gian xây dựng của Rust sẽ tiếp tục chậm hơn trong tương lai gần, đặc biệt là đối với các dự án lớn hơn. Mặc dù có một số tinh chỉnh mà người ta có thể thực hiện để cải thiện tình trạng này, nhưng việc thiết lập chúng và cập nhật những phát triển mới, như cờ và các tùy chọn cấu hình để cải thiện thời gian xây dựng, rất cồng kềnh.

Trong bài viết này, chúng ta sẽ khám phá Fleet , một công cụ xây dựng về cơ bản là giải pháp một công cụ để cải thiện thời gian xây dựng Rust của bạn, cho cả phát triển cục bộ và cho các đường ống CI / CD.

Bắt đầu với Fleet?

Trọng tâm của Fleet là dễ sử dụng. Fleet không nhất thiết nhằm mục đích phát minh lại bánh xe và đại tu hoàn toàn hoặc tái cấu trúc cách thức hoạt động của Rust Build, mà thay vào đó, nó kết hợp các công cụ xây dựng hiện có, điều chỉnh tối ưu hóa cùng nhau thành một công cụ trực quan, có thể định cấu hình giúp tăng tốc các bản dựng. Nó hoạt động trên Linux, Windows và Mac OS.

Thật không may, tại thời điểm viết bài, Fleet vẫn đang trong giai đoạn thử nghiệm và chỉ hỗ trợ hàng đêm rustc. Tuy nhiên, nó đang được tích cực phát triển và việc chuyển nó sang stablechuỗi công cụ nằm trong danh sách ngắn các cải tiến sắp tới. Điều đó nói rằng, nếu bạn không cảm thấy thoải mái khi sử dụng Fleet ngay lập tức hoặc các thiết lập dự án hiện tại của bạn không tương thích với Fleet, thì có một số tin tốt. Bạn có thể thực hiện hầu hết các tối ưu hóa theo cách thủ công. Ở phần sau của bài viết này, chúng ta sẽ xem qua chúng một cách nhanh chóng, chia sẻ một số tài nguyên mà bạn có thể tìm hiểu thêm về chúng.

Đầu tiên, hãy bắt đầu bằng cách học cách cài đặt Fleet và sử dụng nó trong một dự án.

Cài đặt và sử dụng Fleet

Để cài đặt Fleet, bạn cần cài đặt Rust trên máy của mình. Sau khi đã xử lý xong, chỉ cần mở terminal của bạn và thực thi tập lệnh cài đặt tương ứng:

Đối với Linux:

curl -L get.fleet.rs | sh

Cho cửa sổ:

iwr -useb windows.fleet.rs | iex

Sau khi hoàn tất, bạn có thể thiết lập Hạm đội với một trong bốn đối số dòng lệnh:

  • -h / --help: In thông tin trợ giúp
  • -V, / --version: Thông tin phiên bản in
  • build: Xây dựng dự án Hạm đội
  • run: Chạy một dự án Hạm đội

Bạn có thể xem các đối số bổ sung, tùy chọn cho runvà trong tài liệubuild của Hạm đội . Những thứ này hơi giống với Cargo, nhưng nó không phải là sự thay thế 1: 1 , vì vậy hãy đảm bảo kiểm tra các tùy chọn cấu hình khác nhau nếu bạn có nhu cầu cụ thể về dự án của mình.

Nếu bạn định chuẩn thời gian xây dựng có và không có Hạm đội, hãy đảm bảo chạy các bản dựng sạch và lưu ý bộ nhớ đệm và tải trước. Mặc dù Fleet tuyên bố là nhanh hơn Cargo năm lần trên một số bản dựng, nhưng quy mô của hiệu suất thực tế đạt được cho dự án của bạn về tốc độ biên dịch sẽ phụ thuộc vào nhiều yếu tố khác nhau, bao gồm mã bạn đang cố gắng biên dịch và các phụ thuộc của nó như cũng như phần cứng của bạn, SSD so với WSL (Hệ thống Windows cho Linux).

Trong mọi trường hợp, nếu bạn hiện cảm thấy dự án của mình xây dựng rất chậm, hãy cài đặt Fleet và thử xem nó có cải thiện được tình hình hay không. Về mặt thiết lập, Fleet hoàn toàn không mất thời gian.

Ngoài cải tiến phát triển địa phương, một mục tiêu quan trọng khác của Hạm đội là cải thiện đường ống CI / CD. Nếu bạn quan tâm đến việc dùng thử Fleet cho các bản dựng tự động của mình, hãy nhớ xem tài liệu của họ về cách thiết lập nó với GitHub dành cho Linux và Windows .

Tối ưu hóa

Tại thời điểm viết bài này, Fleet tập trung vào bốn cách tối ưu hóa khác nhau: Ramdisk, tối ưu hóa bản dựng thông qua cài đặt, Sccache và một trình liên kết tùy chỉnh. Bạn có thể tìm thấy một mô tả ngắn trong vé GitHub này , nhưng có khả năng danh sách này sẽ thay đổi theo thời gian, đặc biệt là khi Fleet chuyển đến stablevà được phát triển thêm.

Hãy xem xét từng cách tối ưu hóa khác nhau và xem chúng thực sự làm gì. Sau đây sẽ không phải là một mô tả bao quát, mà là một cái nhìn tổng quan hời hợt về các kỹ thuật khác nhau với một số mẹo và tài nguyên về cách sử dụng chúng. Ở cuối bài viết này, cũng có một liên kết đến một bài báo tuyệt vời mô tả cách cải thiện thời gian biên dịch trong Rust theo cách thủ công.

Ramdisk

Ramdisk, hay Ramdrive, về cơ bản chỉ là một khối RAM được sử dụng như thể nó là một đĩa cứng để cải thiện tốc độ và trong một số trường hợp, gây ít căng thẳng hơn cho đĩa cứng.

Ý tưởng của việc tối ưu hóa này là đặt /targetthư mục của bản dựng của bạn vào đĩa Ram để tăng tốc quá trình xây dựng. Nếu bạn đã có SSD, điều này sẽ chỉ cải thiện một chút thời gian xây dựng. Tuy nhiên, nếu bạn sử dụng WSL (Hệ thống con của Windows dành cho Linux) hoặc đĩa cứng không phải SSD, Ramdisk có khả năng cải thiện hiệu suất một cách đáng kể.

Có rất nhiều hướng dẫn về cách tạo đĩa Ram cho các hệ điều hành khác nhau, nhưng để bắt đầu, bạn có thể sử dụng hai bài viết sau trên Mac OSLinux .

Xây dựng cấu hình

Fleet điều khiển cấu hình bản dựng bằng cách sử dụng các tùy chọn và cờ trình biên dịch để tăng hiệu suất.

Một ví dụ về điều này đang tăng lên codegen-units. Điều này về cơ bản làm tăng tính song song trong LLVM khi biên dịch mã của bạn, nhưng nó đi kèm với chi phí tiềm năng về hiệu suất thời gian chạy.

Đây thường không phải là vấn đề đối với các bản dựng gỡ lỗi, nơi mà kinh nghiệm của nhà phát triển và các bản dựng nhanh hơn rất quan trọng, nhưng chắc chắn đối với các bản dựng phát hành. Bạn có thể đọc thêm về cờ này trong tài liệu .

Cài đặt codegen-unitstheo cách thủ công khá dễ dàng, chỉ cần thêm nó rustflagsvào ~/.cargo/config.toml:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "codegen-units=256"]

Tuy nhiên, như đã đề cập ở trên, bạn chắc chắn nên ghi đè điều này trở lại 1cho các bản dựng phát hành.

Một tùy chọn khác là giảm mức tối ưu hóa cho các bản dựng gỡ lỗi của bạn. Mặc dù điều này có nghĩa là hiệu suất thời gian chạy sẽ bị ảnh hưởng, trình biên dịch có ít công việc phải làm hơn, đây thường là những gì bạn muốn lặp lại trên cơ sở mã của mình. Tuy nhiên, có thể có ngoại lệ cho điều này; bạn có thể đọc thêm về các cấp độ tối ưu hóa trong tài liệu .

Để đặt mức tối ưu hóa thành cài đặt thấp nhất có thể, hãy thêm mã bên dưới vào ~/.cargo/config.tomltệp của bạn:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "opt-level=0"]

Một lần nữa, hãy đảm bảo chỉ đặt điều này cho các bản dựng gỡ lỗi chứ không phải cho các bản dựng phát hành. Bạn sẽ không muốn có mã hoàn toàn chưa được tối ưu hóa trong tệp nhị phân sản xuất của mình.

Đối với các mức tối ưu hóa thấp hơn, như đã đề cập, bạn có thể thử thêm share-genericscờ, cho phép chia sẻ các chỉ số chung giữa nhiều thùng trong dự án của bạn, có khả năng tiết kiệm trình biên dịch khỏi thực hiện công việc trùng lặp.

Ví dụ: đối với Linux, bạn có thể thêm cái này vào ~/.cargo/config.toml:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-Z", "share-generics=y"]

Sccache

Cách tối ưu hóa tiếp theo là sử dụng sccache của Mozilla . Sccache là một công cụ biên dịch bộ nhớ đệm, có nghĩa là nó cố gắng lưu vào bộ đệm các kết quả biên dịch, ví dụ, trên các dự án hoặc thùng, lưu trữ chúng trên đĩa, cục bộ hoặc trong bộ nhớ đám mây.

Điều này đặc biệt hữu ích nếu bạn có một số dự án với nhiều phụ thuộc và đôi khi lớn. Lưu vào bộ đệm kết quả của việc biên dịch các dự án khác nhau này có thể ngăn trình biên dịch trùng lặp công việc.

Đặc biệt trong bối cảnh đường ống CI / CD, nơi mà các bản dựng thường được thực thi trong bối cảnh một phiên bản hoặc vùng chứa mới được tạo ra mà không có bất kỳ bộ nhớ cache hiện tại cục bộ nào, sccache được hỗ trợ bởi đám mây có thể cải thiện đáng kể thời gian xây dựng. Mỗi khi bản dựng chạy, bộ nhớ đệm được cập nhật và có thể được sử dụng lại bởi các bản dựng tiếp theo.

Fleet đưa sccache vào các bản dựng của mình một cách liền mạch, nhưng thực hiện việc này theo cách thủ công cũng không đặc biệt khó khăn. Chỉ cần làm theo hướng dẫn cài đặt và sử dụng sccache.

Trình liên kết tùy chỉnh

Cuối cùng, Fleet cũng định cấu hình và sử dụng trình liên kết tùy chỉnh để cải thiện hiệu suất xây dựng. Đặc biệt đối với các dự án lớn có cây phụ thuộc sâu, trình biên dịch dành nhiều thời gian để liên kết. Trong những trường hợp này, việc sử dụng trình liên kết nhanh nhất có thể có thể cải thiện đáng kể thời gian biên dịch.

Danh sách dưới đây bao gồm trình liên kết chính xác để sử dụng cho từng hệ điều hành:

  • Linux: clang + lldtuy nhiên, Linux có thể sẽ  sớm sử dụng khuôn
  • Các cửa sổ:rust-lld.exe
  • Hệ điều hành Mac:zld

Việc cấu hình một trình liên kết tùy chỉnh không đặc biệt khó. Về cơ bản, nó hoàn thành việc cài đặt trình liên kết và sau đó định cấu hình Cargo để sử dụng nó. Ví dụ: sử dụng zldtrên Mac OS có thể được triển khai bằng cách thêm cấu hình sau vào ~/.cargo/config:

[target.x86_64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=<path to zld>"]

Trên Linux, lld hoặc mold, là lựa chọn tốt nhất cho Rust. Fleet chưa sử dụng molddo vấn đề giấy phép , nhưng bạn có thể sử dụng nó trong bản dựng của mình cục bộ bằng cách chỉ cần làm theo các bước dành cho Rust trong tài liệu khuôn .

Sau phần tổng quan ngắn này, một tài nguyên tuyệt vời khác để cải thiện thời gian xây dựng của bạn nếu bạn không muốn sử dụng Fleet vào thời điểm này là bài đăng trên blog của Matthias Endler về chủ đề này.

Sự kết luận

Hạm đội có tiềm năng lớn, đặc biệt là đối với các nhà phát triển không thích loanh quanh với việc xây dựng đường ống hoặc xây dựng quy trình nói chung. Nó cung cấp một gói tối ưu hóa đa nền tảng và đa môi trường mạnh mẽ, đa năng cho tốc độ xây dựng, vì vậy rất đáng để thử nếu bạn đang gặp khó khăn với thời gian xây dựng.

Ngoài ra, chúng tôi đã đề cập đến một số tối ưu hóa mà Fleet thực hiện ở chế độ nền và cách những điều đó sẽ giúp giảm bớt khó khăn về tốc độ biên dịch của bạn nếu bạn sẵn sàng bỏ ra một ít thời gian để tìm ra những gì chúng làm và cách giới thiệu chúng trong thành lập.

Điều đó nói rằng, thông thường, lý do đằng sau thời gian xây dựng chậm là do một dự án phụ thuộc vào rất nhiều hoặc thùng lớn.

Quản lý tốt các phụ thuộc của bạn và với tư duy tối giản, nghĩa là chỉ giới thiệu phiên bản tối thiểu của bất kỳ thứ gì bạn cần hoặc xây dựng chức năng cần thiết từ đầu thay vì thêm một thùng hiện có, sẽ không chỉ giữ cho thời gian xây dựng của bạn thấp mà còn giảm độ phức tạp và tăng khả năng bảo trì mã của bạn.

Nguồn: https://blog.logrocket.com/introductioning-fleet-improving-rusts-cargo/

#rust #cargo 

What is GEEK

Buddha Community

Fleet: Một Công Cụ Xây Dựng để Cải Thiện Rust's Cargo
Trung  Nguyen

Trung Nguyen

1658592000

Fleet: Một Công Cụ Xây Dựng để Cải Thiện Rust's Cargo

Theo Khảo sát Rust năm 2021 , thời gian biên dịch dài của Rust vẫn là một mối quan tâm lớn đối với các nhà phát triển và là một lĩnh vực cần cải thiện hơn nữa. Đặc biệt khi nói đến các dự án lớn hoặc thùng có nhiều phụ thuộc, việc Rust tập trung vào hiệu suất thời gian chạy hơn hiệu suất thời gian biên dịch trở nên khá nghiêm trọng, ngay cả trong các bản dựng gỡ lỗi. Điều này ảnh hưởng tiêu cực đến trải nghiệm của nhà phát triển và là lý do tại sao một số nhà phát triển vẫn không muốn dùng thử Rust.

Trong mọi trường hợp, thời gian xây dựng của Rust sẽ tiếp tục chậm hơn trong tương lai gần, đặc biệt là đối với các dự án lớn hơn. Mặc dù có một số tinh chỉnh mà người ta có thể thực hiện để cải thiện tình trạng này, nhưng việc thiết lập chúng và cập nhật những phát triển mới, như cờ và các tùy chọn cấu hình để cải thiện thời gian xây dựng, rất cồng kềnh.

Trong bài viết này, chúng ta sẽ khám phá Fleet , một công cụ xây dựng về cơ bản là giải pháp một công cụ để cải thiện thời gian xây dựng Rust của bạn, cho cả phát triển cục bộ và cho các đường ống CI / CD.

Bắt đầu với Fleet?

Trọng tâm của Fleet là dễ sử dụng. Fleet không nhất thiết nhằm mục đích phát minh lại bánh xe và đại tu hoàn toàn hoặc tái cấu trúc cách thức hoạt động của Rust Build, mà thay vào đó, nó kết hợp các công cụ xây dựng hiện có, điều chỉnh tối ưu hóa cùng nhau thành một công cụ trực quan, có thể định cấu hình giúp tăng tốc các bản dựng. Nó hoạt động trên Linux, Windows và Mac OS.

Thật không may, tại thời điểm viết bài, Fleet vẫn đang trong giai đoạn thử nghiệm và chỉ hỗ trợ hàng đêm rustc. Tuy nhiên, nó đang được tích cực phát triển và việc chuyển nó sang stablechuỗi công cụ nằm trong danh sách ngắn các cải tiến sắp tới. Điều đó nói rằng, nếu bạn không cảm thấy thoải mái khi sử dụng Fleet ngay lập tức hoặc các thiết lập dự án hiện tại của bạn không tương thích với Fleet, thì có một số tin tốt. Bạn có thể thực hiện hầu hết các tối ưu hóa theo cách thủ công. Ở phần sau của bài viết này, chúng ta sẽ xem qua chúng một cách nhanh chóng, chia sẻ một số tài nguyên mà bạn có thể tìm hiểu thêm về chúng.

Đầu tiên, hãy bắt đầu bằng cách học cách cài đặt Fleet và sử dụng nó trong một dự án.

Cài đặt và sử dụng Fleet

Để cài đặt Fleet, bạn cần cài đặt Rust trên máy của mình. Sau khi đã xử lý xong, chỉ cần mở terminal của bạn và thực thi tập lệnh cài đặt tương ứng:

Đối với Linux:

curl -L get.fleet.rs | sh

Cho cửa sổ:

iwr -useb windows.fleet.rs | iex

Sau khi hoàn tất, bạn có thể thiết lập Hạm đội với một trong bốn đối số dòng lệnh:

  • -h / --help: In thông tin trợ giúp
  • -V, / --version: Thông tin phiên bản in
  • build: Xây dựng dự án Hạm đội
  • run: Chạy một dự án Hạm đội

Bạn có thể xem các đối số bổ sung, tùy chọn cho runvà trong tài liệubuild của Hạm đội . Những thứ này hơi giống với Cargo, nhưng nó không phải là sự thay thế 1: 1 , vì vậy hãy đảm bảo kiểm tra các tùy chọn cấu hình khác nhau nếu bạn có nhu cầu cụ thể về dự án của mình.

Nếu bạn định chuẩn thời gian xây dựng có và không có Hạm đội, hãy đảm bảo chạy các bản dựng sạch và lưu ý bộ nhớ đệm và tải trước. Mặc dù Fleet tuyên bố là nhanh hơn Cargo năm lần trên một số bản dựng, nhưng quy mô của hiệu suất thực tế đạt được cho dự án của bạn về tốc độ biên dịch sẽ phụ thuộc vào nhiều yếu tố khác nhau, bao gồm mã bạn đang cố gắng biên dịch và các phụ thuộc của nó như cũng như phần cứng của bạn, SSD so với WSL (Hệ thống Windows cho Linux).

Trong mọi trường hợp, nếu bạn hiện cảm thấy dự án của mình xây dựng rất chậm, hãy cài đặt Fleet và thử xem nó có cải thiện được tình hình hay không. Về mặt thiết lập, Fleet hoàn toàn không mất thời gian.

Ngoài cải tiến phát triển địa phương, một mục tiêu quan trọng khác của Hạm đội là cải thiện đường ống CI / CD. Nếu bạn quan tâm đến việc dùng thử Fleet cho các bản dựng tự động của mình, hãy nhớ xem tài liệu của họ về cách thiết lập nó với GitHub dành cho Linux và Windows .

Tối ưu hóa

Tại thời điểm viết bài này, Fleet tập trung vào bốn cách tối ưu hóa khác nhau: Ramdisk, tối ưu hóa bản dựng thông qua cài đặt, Sccache và một trình liên kết tùy chỉnh. Bạn có thể tìm thấy một mô tả ngắn trong vé GitHub này , nhưng có khả năng danh sách này sẽ thay đổi theo thời gian, đặc biệt là khi Fleet chuyển đến stablevà được phát triển thêm.

Hãy xem xét từng cách tối ưu hóa khác nhau và xem chúng thực sự làm gì. Sau đây sẽ không phải là một mô tả bao quát, mà là một cái nhìn tổng quan hời hợt về các kỹ thuật khác nhau với một số mẹo và tài nguyên về cách sử dụng chúng. Ở cuối bài viết này, cũng có một liên kết đến một bài báo tuyệt vời mô tả cách cải thiện thời gian biên dịch trong Rust theo cách thủ công.

Ramdisk

Ramdisk, hay Ramdrive, về cơ bản chỉ là một khối RAM được sử dụng như thể nó là một đĩa cứng để cải thiện tốc độ và trong một số trường hợp, gây ít căng thẳng hơn cho đĩa cứng.

Ý tưởng của việc tối ưu hóa này là đặt /targetthư mục của bản dựng của bạn vào đĩa Ram để tăng tốc quá trình xây dựng. Nếu bạn đã có SSD, điều này sẽ chỉ cải thiện một chút thời gian xây dựng. Tuy nhiên, nếu bạn sử dụng WSL (Hệ thống con của Windows dành cho Linux) hoặc đĩa cứng không phải SSD, Ramdisk có khả năng cải thiện hiệu suất một cách đáng kể.

Có rất nhiều hướng dẫn về cách tạo đĩa Ram cho các hệ điều hành khác nhau, nhưng để bắt đầu, bạn có thể sử dụng hai bài viết sau trên Mac OSLinux .

Xây dựng cấu hình

Fleet điều khiển cấu hình bản dựng bằng cách sử dụng các tùy chọn và cờ trình biên dịch để tăng hiệu suất.

Một ví dụ về điều này đang tăng lên codegen-units. Điều này về cơ bản làm tăng tính song song trong LLVM khi biên dịch mã của bạn, nhưng nó đi kèm với chi phí tiềm năng về hiệu suất thời gian chạy.

Đây thường không phải là vấn đề đối với các bản dựng gỡ lỗi, nơi mà kinh nghiệm của nhà phát triển và các bản dựng nhanh hơn rất quan trọng, nhưng chắc chắn đối với các bản dựng phát hành. Bạn có thể đọc thêm về cờ này trong tài liệu .

Cài đặt codegen-unitstheo cách thủ công khá dễ dàng, chỉ cần thêm nó rustflagsvào ~/.cargo/config.toml:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "codegen-units=256"]

Tuy nhiên, như đã đề cập ở trên, bạn chắc chắn nên ghi đè điều này trở lại 1cho các bản dựng phát hành.

Một tùy chọn khác là giảm mức tối ưu hóa cho các bản dựng gỡ lỗi của bạn. Mặc dù điều này có nghĩa là hiệu suất thời gian chạy sẽ bị ảnh hưởng, trình biên dịch có ít công việc phải làm hơn, đây thường là những gì bạn muốn lặp lại trên cơ sở mã của mình. Tuy nhiên, có thể có ngoại lệ cho điều này; bạn có thể đọc thêm về các cấp độ tối ưu hóa trong tài liệu .

Để đặt mức tối ưu hóa thành cài đặt thấp nhất có thể, hãy thêm mã bên dưới vào ~/.cargo/config.tomltệp của bạn:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "opt-level=0"]

Một lần nữa, hãy đảm bảo chỉ đặt điều này cho các bản dựng gỡ lỗi chứ không phải cho các bản dựng phát hành. Bạn sẽ không muốn có mã hoàn toàn chưa được tối ưu hóa trong tệp nhị phân sản xuất của mình.

Đối với các mức tối ưu hóa thấp hơn, như đã đề cập, bạn có thể thử thêm share-genericscờ, cho phép chia sẻ các chỉ số chung giữa nhiều thùng trong dự án của bạn, có khả năng tiết kiệm trình biên dịch khỏi thực hiện công việc trùng lặp.

Ví dụ: đối với Linux, bạn có thể thêm cái này vào ~/.cargo/config.toml:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-Z", "share-generics=y"]

Sccache

Cách tối ưu hóa tiếp theo là sử dụng sccache của Mozilla . Sccache là một công cụ biên dịch bộ nhớ đệm, có nghĩa là nó cố gắng lưu vào bộ đệm các kết quả biên dịch, ví dụ, trên các dự án hoặc thùng, lưu trữ chúng trên đĩa, cục bộ hoặc trong bộ nhớ đám mây.

Điều này đặc biệt hữu ích nếu bạn có một số dự án với nhiều phụ thuộc và đôi khi lớn. Lưu vào bộ đệm kết quả của việc biên dịch các dự án khác nhau này có thể ngăn trình biên dịch trùng lặp công việc.

Đặc biệt trong bối cảnh đường ống CI / CD, nơi mà các bản dựng thường được thực thi trong bối cảnh một phiên bản hoặc vùng chứa mới được tạo ra mà không có bất kỳ bộ nhớ cache hiện tại cục bộ nào, sccache được hỗ trợ bởi đám mây có thể cải thiện đáng kể thời gian xây dựng. Mỗi khi bản dựng chạy, bộ nhớ đệm được cập nhật và có thể được sử dụng lại bởi các bản dựng tiếp theo.

Fleet đưa sccache vào các bản dựng của mình một cách liền mạch, nhưng thực hiện việc này theo cách thủ công cũng không đặc biệt khó khăn. Chỉ cần làm theo hướng dẫn cài đặt và sử dụng sccache.

Trình liên kết tùy chỉnh

Cuối cùng, Fleet cũng định cấu hình và sử dụng trình liên kết tùy chỉnh để cải thiện hiệu suất xây dựng. Đặc biệt đối với các dự án lớn có cây phụ thuộc sâu, trình biên dịch dành nhiều thời gian để liên kết. Trong những trường hợp này, việc sử dụng trình liên kết nhanh nhất có thể có thể cải thiện đáng kể thời gian biên dịch.

Danh sách dưới đây bao gồm trình liên kết chính xác để sử dụng cho từng hệ điều hành:

  • Linux: clang + lldtuy nhiên, Linux có thể sẽ  sớm sử dụng khuôn
  • Các cửa sổ:rust-lld.exe
  • Hệ điều hành Mac:zld

Việc cấu hình một trình liên kết tùy chỉnh không đặc biệt khó. Về cơ bản, nó hoàn thành việc cài đặt trình liên kết và sau đó định cấu hình Cargo để sử dụng nó. Ví dụ: sử dụng zldtrên Mac OS có thể được triển khai bằng cách thêm cấu hình sau vào ~/.cargo/config:

[target.x86_64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=<path to zld>"]

Trên Linux, lld hoặc mold, là lựa chọn tốt nhất cho Rust. Fleet chưa sử dụng molddo vấn đề giấy phép , nhưng bạn có thể sử dụng nó trong bản dựng của mình cục bộ bằng cách chỉ cần làm theo các bước dành cho Rust trong tài liệu khuôn .

Sau phần tổng quan ngắn này, một tài nguyên tuyệt vời khác để cải thiện thời gian xây dựng của bạn nếu bạn không muốn sử dụng Fleet vào thời điểm này là bài đăng trên blog của Matthias Endler về chủ đề này.

Sự kết luận

Hạm đội có tiềm năng lớn, đặc biệt là đối với các nhà phát triển không thích loanh quanh với việc xây dựng đường ống hoặc xây dựng quy trình nói chung. Nó cung cấp một gói tối ưu hóa đa nền tảng và đa môi trường mạnh mẽ, đa năng cho tốc độ xây dựng, vì vậy rất đáng để thử nếu bạn đang gặp khó khăn với thời gian xây dựng.

Ngoài ra, chúng tôi đã đề cập đến một số tối ưu hóa mà Fleet thực hiện ở chế độ nền và cách những điều đó sẽ giúp giảm bớt khó khăn về tốc độ biên dịch của bạn nếu bạn sẵn sàng bỏ ra một ít thời gian để tìm ra những gì chúng làm và cách giới thiệu chúng trong thành lập.

Điều đó nói rằng, thông thường, lý do đằng sau thời gian xây dựng chậm là do một dự án phụ thuộc vào rất nhiều hoặc thùng lớn.

Quản lý tốt các phụ thuộc của bạn và với tư duy tối giản, nghĩa là chỉ giới thiệu phiên bản tối thiểu của bất kỳ thứ gì bạn cần hoặc xây dựng chức năng cần thiết từ đầu thay vì thêm một thùng hiện có, sẽ không chỉ giữ cho thời gian xây dựng của bạn thấp mà còn giảm độ phức tạp và tăng khả năng bảo trì mã của bạn.

Nguồn: https://blog.logrocket.com/introductioning-fleet-improving-rusts-cargo/

#rust #cargo 

Serde Rust: Serialization Framework for Rust

Serde

*Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.*

You may be looking for:

Serde in action

Click to show Cargo.toml. Run this code in the playground.

[dependencies]

# The core APIs, including the Serialize and Deserialize traits. Always
# required when using Serde. The "derive" feature is only required when
# using #[derive(Serialize, Deserialize)] to make Serde work with structs
# and enums defined in your crate.
serde = { version = "1.0", features = ["derive"] }

# Each data format lives in its own crate; the sample code below uses JSON
# but you may be using a different one.
serde_json = "1.0"

 

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 1, y: 2 };

    // Convert the Point to a JSON string.
    let serialized = serde_json::to_string(&point).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a Point.
    let deserialized: Point = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = Point { x: 1, y: 2 }
    println!("deserialized = {:?}", deserialized);
}

Getting help

Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the #rust-questions or #rust-beginners channels of the unofficial community Discord (invite: https://discord.gg/rust-lang-community), the #rust-usage or #beginners channels of the official Rust Project Discord (invite: https://discord.gg/rust-lang), or the #general stream in Zulip. For asynchronous, consider the [rust] tag on StackOverflow, the /r/rust subreddit which has a pinned weekly easy questions post, or the Rust Discourse forum. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time.

Download Details:
Author: serde-rs
Source Code: https://github.com/serde-rs/serde
License: View license

#rust  #rustlang 

Awesome  Rust

Awesome Rust

1654894080

Serde JSON: JSON Support for Serde Framework

Serde JSON

Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.

[dependencies]
serde_json = "1.0"

You may be looking for:

JSON is a ubiquitous open-standard format that uses human-readable text to transmit data objects consisting of key-value pairs.

{
    "name": "John Doe",
    "age": 43,
    "address": {
        "street": "10 Downing Street",
        "city": "London"
    },
    "phones": [
        "+44 1234567",
        "+44 2345678"
    ]
}

There are three common ways that you might find yourself needing to work with JSON data in Rust.

  • As text data. An unprocessed string of JSON data that you receive on an HTTP endpoint, read from a file, or prepare to send to a remote server.
  • As an untyped or loosely typed representation. Maybe you want to check that some JSON data is valid before passing it on, but without knowing the structure of what it contains. Or you want to do very basic manipulations like insert a key in a particular spot.
  • As a strongly typed Rust data structure. When you expect all or most of your data to conform to a particular structure and want to get real work done without JSON's loosey-goosey nature tripping you up.

Serde JSON provides efficient, flexible, safe ways of converting data between each of these representations.

Operating on untyped JSON values

Any valid JSON data can be manipulated in the following recursive enum representation. This data structure is serde_json::Value.

enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

A string of JSON data can be parsed into a serde_json::Value by the serde_json::from_str function. There is also from_slice for parsing from a byte slice &[u8] and from_reader for parsing from any io::Read like a File or a TCP stream.

use serde_json::{Result, Value};

fn untyped_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into serde_json::Value.
    let v: Value = serde_json::from_str(data)?;

    // Access parts of the data by indexing with square brackets.
    println!("Please call {} at the number {}", v["name"], v["phones"][0]);

    Ok(())
}

The result of square bracket indexing like v["name"] is a borrow of the data at that index, so the type is &Value. A JSON map can be indexed with string keys, while a JSON array can be indexed with integer keys. If the type of the data is not right for the type with which it is being indexed, or if a map does not contain the key being indexed, or if the index into a vector is out of bounds, the returned element is Value::Null.

When a Value is printed, it is printed as a JSON string. So in the code above, the output looks like Please call "John Doe" at the number "+44 1234567". The quotation marks appear because v["name"] is a &Value containing a JSON string and its JSON representation is "John Doe". Printing as a plain string without quotation marks involves converting from a JSON string to a Rust string with as_str() or avoiding the use of Value as described in the following section.

The Value representation is sufficient for very basic tasks but can be tedious to work with for anything more significant. Error handling is verbose to implement correctly, for example imagine trying to detect the presence of unrecognized fields in the input data. The compiler is powerless to help you when you make a mistake, for example imagine typoing v["name"] as v["nmae"] in one of the dozens of places it is used in your code.

Parsing JSON as strongly typed data structures

Serde provides a powerful way of mapping JSON data into Rust data structures largely automatically.

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

fn typed_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into a Person object. This is exactly the
    // same function as the one that produced serde_json::Value above, but
    // now we are asking it for a Person as output.
    let p: Person = serde_json::from_str(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

This is the same serde_json::from_str function as before, but this time we assign the return value to a variable of type Person so Serde will automatically interpret the input data as a Person and produce informative error messages if the layout does not conform to what a Person is expected to look like.

Any type that implements Serde's Deserialize trait can be deserialized this way. This includes built-in Rust standard library types like Vec<T> and HashMap<K, V>, as well as any structs or enums annotated with #[derive(Deserialize)].

Once we have p of type Person, our IDE and the Rust compiler can help us use it correctly like they do for any other Rust code. The IDE can autocomplete field names to prevent typos, which was impossible in the serde_json::Value representation. And the Rust compiler can check that when we write p.phones[0], then p.phones is guaranteed to be a Vec<String> so indexing into it makes sense and produces a String.

The necessary setup for using Serde's derive macros is explained on the Using derive page of the Serde site.

Constructing JSON values

Serde JSON provides a json! macro to build serde_json::Value objects with very natural JSON syntax.

use serde_json::json;

fn main() {
    // The type of `john` is `serde_json::Value`
    let john = json!({
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    });

    println!("first phone number: {}", john["phones"][0]);

    // Convert to a string of JSON and print it out
    println!("{}", john.to_string());
}

The Value::to_string() function converts a serde_json::Value into a String of JSON text.

One neat thing about the json! macro is that variables and expressions can be interpolated directly into the JSON value as you are building it. Serde will check at compile time that the value you are interpolating is able to be represented as JSON.

let full_name = "John Doe";
let age_last_year = 42;

// The type of `john` is `serde_json::Value`
let john = json!({
    "name": full_name,
    "age": age_last_year + 1,
    "phones": [
        format!("+44 {}", random_phone())
    ]
});

This is amazingly convenient, but we have the problem we had before with Value: the IDE and Rust compiler cannot help us if we get it wrong. Serde JSON provides a better way of serializing strongly-typed data structures into JSON text.

Creating JSON by serializing data structures

A data structure can be converted to a JSON string by serde_json::to_string. There is also serde_json::to_vec which serializes to a Vec<u8> and serde_json::to_writer which serializes to any io::Write such as a File or a TCP stream.

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Address {
    street: String,
    city: String,
}

fn print_an_address() -> Result<()> {
    // Some data structure.
    let address = Address {
        street: "10 Downing Street".to_owned(),
        city: "London".to_owned(),
    };

    // Serialize it to a JSON string.
    let j = serde_json::to_string(&address)?;

    // Print, write to a file, or send to an HTTP server.
    println!("{}", j);

    Ok(())
}

Any type that implements Serde's Serialize trait can be serialized this way. This includes built-in Rust standard library types like Vec<T> and HashMap<K, V>, as well as any structs or enums annotated with #[derive(Serialize)].

Performance

It is fast. You should expect in the ballpark of 500 to 1000 megabytes per second deserialization and 600 to 900 megabytes per second serialization, depending on the characteristics of your data. This is competitive with the fastest C and C++ JSON libraries or even 30% faster for many use cases. Benchmarks live in the serde-rs/json-benchmark repo.

Getting help

Serde is one of the most widely used Rust libraries, so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the #rust-questions or #rust-beginners channels of the unofficial community Discord (invite: https://discord.gg/rust-lang-community), the #rust-usage or #beginners channels of the official Rust Project Discord (invite: https://discord.gg/rust-lang), or the #general stream in Zulip. For asynchronous, consider the [rust] tag on StackOverflow, the /r/rust subreddit which has a pinned weekly easy questions post, or the Rust Discourse forum. It's acceptable to file a support issue in this repo, but they tend not to get as many eyes as any of the above and may get closed without a response after some time.

No-std support

As long as there is a memory allocator, it is possible to use serde_json without the rest of the Rust standard library. This is supported on Rust 1.36+. Disable the default "std" feature and enable the "alloc" feature:

[dependencies]
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

For JSON support in Serde without a memory allocator, please see the serde-json-core crate.

Link: https://crates.io/crates/serde_json

#rust  #rustlang  #encode   #json 

许 志强

许 志强

1658586720

Fleet:用于改进 Rust 的 Cargo 的构建工具

根据2021 Rust 调查,Rust 的长编译时间仍然是开发人员的一个大问题,也是需要进一步改进的领域。尤其是当涉及到具有许多依赖项的大型项目或 crate 时,Rust 对运行时性能而非编译时性能的关注变得相当不利,即使在调试构建中也是如此。这会对开发人员的体验产生负面影响,这也是一些开发人员仍然不愿意尝试 Rust 的原因。

无论如何,在可预见的未来,Rust 的构建时间将继续变慢,尤其是对于大型项目。虽然可以进行一些调整来改善这种情况,但设置它们并与新的开发保持同步,例如用于改进构建时间的标志和配置选项,是很麻烦的。

在本文中,我们将探索Fleet,这是一个构建工具,它本质上是一种用于改进 Rust 构建时间的单一工具解决方案,适用于本地开发和 CI/CD 管道。

开始使用舰队?

Fleet 的重点是易用性。Fleet 不一定旨在重新发明轮子并彻底改革或重组 Rust 构建工作的方式,而是将现有的构建工具包装起来,将优化调整到一个可配置的、直观的工具中,以加快构建速度。它适用于 Linux、Windows 和 Mac OS。

不幸的是,在撰写本文时,Fleet 仍处于测试阶段,仅支持 nightly rustc。但是,它正在积极开发中,将其移至stable工具链是即将进行的改进的短名单。也就是说,如果您对立即使用 Fleet 感到不舒服,或者您当前的项目设置与 Fleet 不兼容,那么有一些好消息。您可以手动进行大部分优化。在本文后面,我们将快速浏览它们,分享一些资源,您可以在其中了解更多关于它们的信息。

首先,让我们从学习如何安装 Fleet 并在项目中使用它开始。

安装和使用 Fleet

要安装 Fleet,你需要在你的机器上安装 Rust。完成后,只需打开终端并执行相应的安装脚本:

对于 Linux:

curl -L get.fleet.rs | sh

对于 Windows:

iwr -useb windows.fleet.rs | iex

完成后,您可以使用以下四个命令行参数之一设置 Fleet:

  • -h / --help:打印帮助信息
  • -V, / --version:打印版本信息
  • build: 建立一个舰队项目
  • run: 运行一个 Fleet 项目

您可以在 Fleet docsrun中查看附加的可选参数。这些有点类似于 Cargo,但它不是 1:1 的替代品,因此如果您对项目有特殊需求,请务必查看不同的配置选项。build

如果您计划在有和没有 Fleet 的情况下对构建时间进行基准测试,请务必运行干净的构建并牢记缓存和预加载。虽然 Fleet 声称在某些构建上比 Cargo 快五倍,但您的项目在编译速度方面的实际性能提升的大小将取决于许多不同的因素,包括您尝试编译的代码及其依赖项以及您的硬件、SSD 与 WSL(适用于 Linux 的 Windows 系统)。

无论如何,如果您目前觉得您的项目构建非常缓慢,请安装 Fleet 并尝试一下,看看它是否能改善这种情况。在设置方面,Fleet 完全不需要时间。

除了本地开发改进之外,Fleet 的另一个重要目标是改进 CI/CD 管道。如果您有兴趣尝试 Fleet 进行自动化构建,请务必查看他们的文档,了解如何使用 GitHub for Linux 和 Windows 进行设置

优化

在撰写本文时,Fleet 专注于四种不同的优化:Ramdisk、通过设置优化构建、Sccache 和自定义链接器。你可以在这个GitHub ticket中找到一个简短的描述,但是这个列表很可能会随着时间的推移而改变,尤其是当 Fleet 迁移到stable并进一步开发时。

让我们一个一个地回顾不同的优化,看看它们实际上做了什么。以下不会是详尽的描述,而是对不同技术的肤浅概述,并提供一些关于如何使用它们的技巧和资源。在本文的末尾,还有一篇精彩文章的链接,该链接描述了如何在 Rust 中手动改进编译时间。

内存盘

Ramdisk 或 Ramdrive 本质上只是一块 RAM,它被用作硬盘,以提高速度并在某些情况下减轻硬盘的压力。

这种优化的想法是将/target构建的文件夹放到 Ramdisk 上以加快构建速度。如果您已经拥有 SSD,这只会略微缩短构建时间。但是,如果您使用 WSL(Linux 的 Windows 子系统)或非 SSD 硬盘,Ramdisk 有可能大幅提高性能。

有很多关于如何为不同操作系统创建 Ramdisk 的教程,但作为起点,您可以在Mac OSLinux上使用以下两篇文章。

构建配置

Fleet 通过使用编译器选项和标志来操纵构建配置以提高性能。

这方面的一个例子是增加codegen-units。在编译代码时,这从本质上提高了 LLVM 中的并行性,但它以潜在的运行时性能为代价。

这通常不是调试版本的问题,开发人员的经验和更快的构建很重要,但对于发布版本来说绝对是。您可以在 docs 中阅读有关此标志的更多信息。

手动设置codegen-units相当简单,只需将其添加到rustflags您的~/.cargo/config.toml

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "codegen-units=256"]

但是,如上所述,您绝对应该将其重写1为发布版本。

另一种选择是降低调试版本的优化级别。虽然这意味着运行时性能会受到影响,但编译器要做的工作更少,这通常是您在代码库上迭代所需要的。但是,这可能有例外;您可以在文档中阅读有关优化级别的更多信息。

要将优化级别设置为尽可能低的设置,请将以下代码添加到您的~/.cargo/config.toml文件中:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "opt-level=0"]

同样,请确保仅为调试版本设置此选项,而不是为发布版本设置。您不希望在生产二进制文件中有完全未优化的代码。

如前所述,对于较低的优化级别,您可以尝试添加share-generics标志,它可以在项目中的多个 crate 之间共享泛型,从而可能使编译器免于重复工作。

例如,对于 Linux,您可以将其添加到您的~/.cargo/config.toml:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-Z", "share-generics=y"]

高速缓存

下一个优化是使用 Mozilla 的sccache。Sccache 是一个编译器缓存工具,这意味着它尝试缓存编译结果,例如,跨项目或 crate,将它们存储在本地或云存储中的磁盘上。

如果您有几个项目具有许多甚至很大的依赖关系,这将特别有用。缓存这些不同项目的编译结果可以防止编译器重复工作。

特别是在 CI/CD 管道的上下文中,通常在没有任何本地缓存的新生成实例或容器的上下文中执行构建,云支持的 sccache 可以显着缩短构建时间。每次构建运行时,缓存都会更新,并且可以被后续构建重用。

Fleet 将 sccache 无缝地引入其构建中,但手动执行此操作也不是特别困难。只需按照sccache的安装和使用说明进行操作。

自定义链接器

最后,Fleet 还配置和使用自定义链接器来提高构建性能。尤其是对于依赖树很深的大型项目,编译器会花费大量时间链接。在这些情况下,使用尽可能快的链接器可以大大缩短编译时间。

下面的列表包括用于每个操作系统的正确链接器:

  • Linux:clang + lld不过,Linux 可能 很快就会使用霉菌
  • 视窗:rust-lld.exe
  • 苹果系统:zld

配置自定义链接器并不是特别困难。本质上,它归结为安装链接器,然后配置 Cargo 以使用它。例如,zld在 Mac OS 上使用可以通过将以下配置添加到您的来实现~/.cargo/config

[target.x86_64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=<path to zld>"]

在 Linux 上,lld ormold是 Rust 的最佳选择。mold由于许可证问题, Fleet 尚未使用,但您可以在本地构建中使用它,只需按照模具文档中的 Rust 步骤即可。

在这个简短的概述之后,如果您此时不愿意使用 Fleet,那么另一个可以缩短构建时间的绝佳资源是 Matthias Endler关于该主题的博客文章。

结论

Fleet 具有巨大的潜力,特别是对于不喜欢在一般的构建管道或构建过程上大惊小怪的开发人员而言。它为构建速度提供了一个强大的、多平台和多环境优化的一体化包,因此如果您正在为构建时间而苦苦挣扎,那么它非常值得一试。

除此之外,我们还谈到了 Fleet 在后台执行的一些优化,以及如果您愿意花一点时间来弄清楚它们的作用以及如何将它们引入您的设置。

也就是说,很多时候,构建时间缓慢的原因是一个项目依赖于非常多或大的 crate。

以极简主义的心态很好地管理你的依赖关系,这意味着只引入你需要的任何东西的最小版本,或者从头开始构建所需的功能,而不是添加现有的 crate,不仅可以缩短构建时间,还可以降低复杂性并增加代码的可维护性。

资料来源:https ://blog.logrocket.com/introducing-fleet-improving-rusts-cargo/

#rust #cargo 

Fleet: A Build Tool for Improving Rust’s Cargo

According to the 2021 Rust Survey, Rust’s long compile time is still a big concern for developers and an area for further improvement. Especially when it comes to large projects or crates with many dependencies, Rust’s focus on runtime performance over compile time performance becomes rather punishing, even in debug builds. This negatively impacts developer experience and is a reason why some developers are still unwilling to try Rust.

In any case, Rust’s build times will continue to be on the slower side for the foreseeable future, especially for larger projects. While there are some tweaks one can make to improve this situation, setting them up and keeping up-to-date with new developments, like flags and configuration options for improved build times, is cumbersome.

In this article, we’ll explore Fleet, a build tool that is essentially a one-tool-solution for improving your Rust build times, both for local development and for CI/CD pipelines.

See more at: https://blog.logrocket.com/introducing-fleet-improving-rusts-cargo/

#rust #cargo