自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Elixir 和 Rust 是一個很好的組合

譯文 精選
開發(fā) 前端
這篇文章是關于將 Rust 與 Elixir 結合使用,幾分鐘內搞定并運行。

一、?問題

我們需要執(zhí)行 CPU 密集型或系統(tǒng)級編程任務,而hex.pm中沒有好的解決方案,在這個例子中,我們假設沒有好的方法可以使用 Elixir 進行圖像處理。

通常情況下,有一個名為image的高質量 Rust 庫聲稱它就是解決方案!但是糟糕,我們的整個應用程序已經用 Elixir 編寫了,我們真的不知道如何很好地使用Rust。

Elixir 如何轉向 Rust 代碼以實現高性能操作?

二、解決方案

輸入rustler,這個庫旨在使使用 Rust 及其包生態(tài)系統(tǒng)變得簡單。讓我們開始吧!

按照入門指南,首先將rustler添加到我們的mix.exs文件中:

{:rustler, "~> 0.27.0"}

一旦我們運行mix deps.get使用內置的 mix 任務來生成我們的空 rust 項目:

mix rustler.new

This is the name of the Elixir module the NIF module will be registered to.

Module name > MyApp.RustImage

This is the name used for the generated Rust crate. The default is most likely fine.

Library name (myapp_rustimage) > rust_image

* creating native/rust_image/.cargo/config.toml

* creating native/rust_image/README.md

* creating native/rust_image/Cargo.toml

* creating native/rust_image/src/lib.rs

* creating native/rust_image/.gitignore

Ready to go! See /Users/me/projects/my_app/native/rust_image/README.md for further instructions

你應該去打開它README.md,但我會幫你省去麻煩,我們需要制作一個 Elixir 模塊,其中l(wèi)ib/my_app/rust_image.ex包含以下內容:

defmodule MyApp.RustImage do

use Rustler, otp_app: :my_app, crate: "rust_image"

# When your NIF is loaded, it will override this function.

def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded)

end

從那時起,我們準備好做一些 Rust。默認的生成器給了我們一個add/2實現的函數讓native/rust_image/src/lib.rs我們來看看

#[rustler::nif]

fn add(a: i64, b: i64) -> i64 {

a + b

}

rustler::init!("Elixir.MyApp.RustImage", [add]);

三、什么是 NIF?

Native Implemented Functions 是 BEAM 允許進程直接調用本地函數的方法。他們通常有大量的樣板文件,你需要認真清理內存、處理錯誤和確保安全。幸運的是,這就是 Rust 的全部!例如這里是 Erlang NIF 教程。我們不需要做任何這些!

我們的超級優(yōu)化代碼將添加兩個大小為 i64 的整數并返回結果。請注意此處 Rustler 的特定部分:

  • #[rustler::nif]是一個宏,告訴 Rustler 將此函數公開為 NIF。
  • rustler::init!("Elixir.MyApp.RustImage", [add]);這將初始化 Erlang NIF 運行時,以便 beam 可以將add/2函數放在模塊上Elixir.MyApp.RustImage并替換我們留下的存根。

這太棒了??纯催@是否有效,讓我們開火iex -S mix

iex(1)> MyApp.RustImage.add(100, 20)

12

如果第一次一切正常,你應該已經看到 cargo 在發(fā)布模式下構建應用程序并在打開 iex 術語之前成功。如果你還沒有安裝 Rust,它會顯示一個錯誤,你可以按照通常的方式安裝 Rust 。

Rustler 甚至很聰明,會自動重新編譯,保持 iex 打開并更改我們的lib.rs

#[rustler::nif]

fn add(a: i64, b: i64) -> i64 {

a + b + 1

}

保存然后再次打開正在運行的 iex 會話:

iex(2)> r(MyApp.RustImage)

... truncated output of cargo doing it's thing an maybe some beam warnings

{:reloaded, [MyApp.RustImage]}

iex(3)> MyApp.RustImage.add(1,1)

3

極好的!我們得到了相同的工作流程和與 Elixir 一起工作的好處,而對 Rust 的煩惱最少。

四、圖片

首先將我們的圖像依賴項添加到我們的Cargo.toml文件中:

[dependencies]

rustler = "0.27.0"

image = "0.24.6"

然后改變我們lib.rs創(chuàng)建一個函數,它接受一個input路徑,一個output路徑,quality并將任何圖像更改為具有我們設置質量的 JPEG。

use image::io::Reader as ImageReader;

use image::codecs::jpeg::JpegEncoder;

use std::fs::File;

#[rustler::nif]

fn jpg(input: String, output: String, quality: i64) -> Result<String, String> {

let img = ImageReader::open(&input).unwrap().decode().unwrap();

let out_file = std::fs::File::create(&output).unwrap();

let mut jpg = JpegEncoder::new_with_quality(&out_file, quality as u8);

jpg.encode_image(&img).unwrap();

Ok(output.to_string())

}

// add code...

rustler::init!("Elixir.MyApp.RustImage", [add, jpg]);

我們還想更新我們的 RustImage 模塊以包含一個存根jpg/3,但這留給讀者作為練習。

現在讓我們試試吧!iex -S mix

iex(1)> MyApp.RustImage.jpg("input.png", "output.jpeg", 75)

{:ok, "output.jpeg"}

和繁榮!我們已將 PNG 轉換為 JPEG,質量為 75%。

五、做一個良好的 BEAM 公民

我們還應該在這里考慮一件事,那就是 CPU 負載。雖然此功能可能會在我們的筆記本電腦上立即運行,但在部署時可能需要更長時間才能共享 CPU/RAM。

而且因為 BEAM 直接運行我們的代碼,它會鎖定運行時直到它完成運行。我們所說的直接意思是,當使用 NIF 時,beam 會像對待任何其他代碼一樣對待它,主要的警告是它不能自動搶占 Rust 代碼。

在 BEAM 上,這是一個大問題,因為整個運行時都希望能夠隨時在數百萬個進程之間切換上下文。

幸運的是 Rustler 和 BEAM 團隊已經想到了這一點并給了我們一個解決方案。只需將該宏更改為此jpeg即可

-- #[rustler::nif]

++ #[rustler::nif(schedule = "DirtyCpu")]

這告訴 Rustler 和 BEAM 以一種在它工作時不會阻塞整個世界的方式自動安排它。再次令人驚嘆,這被稱為 DirtyNif,當你通過 C 手動使用它時,使用起來會更加困難。

六、部署

使用 Docker 將其部署到 Fly.io 并不是那么自動,我們需要進行一些小的更改,以便我們的 Docker 環(huán)境可以構建 Rust。首先,通過在我們的 Elixir 構建步驟之前添加一個構建步驟來更新 Dockerfile:

#... ARG stuff..

FROM rust:1.68.0 as rust

# install build dependencies

RUN apt-get update -y && apt-get install -y build-essential git \

&& apt-get clean && rm -f /var/lib/apt/lists/*_*

workdir /app

COPY native/rust_images ./

RUN cargo rustc --release

#..Elixir builder.....

# compile assets

RUN mix assets.deploy

#NEW STUFF

COPY --from=rust /app/target/release/librust_images.so priv/native/librust_images.so

#/NEW

# Compile the release

RUN mix compile

然后更新我們config/prod.exs添加以下行:

config :my_app, MyApp.RustImage,

crate: :rust_image,

skip_compilation?: true,

load_from: {:my_app, "priv/native/librust_image"}

我們在這里所做的是在其自己的 Docker 構建器上下文中構建庫,因此它與我們其余的 Docker 步驟并行運行并且可以輕松緩存。然后我們告訴 Rustler 跳過編譯并直接從我們放置它的地方加載它。

我們都準備好了,fly deploy你就可以出發(fā)了!

七、討論

關于結合使用 NIF 和 Rust 的強大功能,我們只是真正觸及了皮毛。從加載海量數據集到做科學研究再到通過 WebRTC 進行連接,Rust 社區(qū)已經構建了一套令人印象深刻的包和工具,現在我們也可以使用這些包和工具。Rustler 使之成為可能!

原文鏈接:https://fly.io/phoenix-files/elixir-and-rust-is-a-good-mix/

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2021-04-13 06:35:13

Elixir語言編程語言軟件開發(fā)

2015-11-23 16:27:35

人工智能

2023-04-24 12:57:01

數據中心綜合布線

2023-07-11 13:34:19

Rust開發(fā)軟件

2024-06-07 08:59:35

2025-02-27 00:00:15

2020-09-16 23:00:15

Rust編程語言開發(fā)

2010-09-10 15:32:53

SQL函數日期格式化

2021-01-03 16:30:34

Rust編程語言

2017-07-13 12:33:15

戴爾

2012-07-20 09:51:56

贊揚管理藝術管理

2012-09-18 01:33:34

程序員創(chuàng)意開發(fā)者

2024-01-09 18:00:22

Rust后端slvelte

2024-07-10 08:51:29

2024-02-27 07:33:32

搜索引擎Rust模型

2022-04-10 23:02:08

GoRust語言

2024-02-28 07:48:05

Rust項目框架

2016-11-02 00:22:13

數字化改造數字化

2021-07-06 14:36:05

RustLinux內核模塊

2021-08-02 08:21:53

Python編程語言開發(fā)
點贊
收藏

51CTO技術棧公眾號