Оптимизация кода для повышения производительности: руководство по использованию Rust и WebAssembly

JavaScript – это мощный язык для создания веб-приложений, но по мере усложнения приложений производительность может стать проблемой. Когда дело доходит до оптимизации вашего кода, одним из многообещающих решений является использование Rust и WebAssembly.

Rust — это язык системного программирования, известный своей производительностью и безопасностью, а WebAssembly — это двоичный формат для запуска кода в Интернете, разработанный для того, чтобы быть быстрым и эффективным. В сочетании Rust и WebAssembly могут значительно повысить производительность вашего кода JavaScript.

В этом сообщении блога мы рассмотрим, как использовать Rust и WebAssembly для оптимизации приложения JavaScript. Мы начнем с рассмотрения простого примера кода JavaScript, который вычисляет последовательность Фибоначчи, и покажем, как использовать Rust и WebAssembly для создания более быстрой и более эффективная версия кода. Попутно мы обсудим преимущества совместного использования Rust и WebAssembly и дадим советы и рекомендации по началу работы с этой захватывающей и мощной комбинацией технологий. .

Создание проекта грузового wasm

Начало работы с Rust и WebAssembly включает настройку проекта Rust и его настройку для компиляции в WebAssembly. Вот основные шаги, которые вам необходимо выполнить:

  • Установите набор инструментов Rust. Вы можете легко сделать это, перейдя на https://rustup.rs/
  • С помощью утилиты командной строки cargo создайте проект:
$ cargo new --lib fib-wasm
  • Настройте проект так, чтобы он был нацелен на WebAssembly, и добавьте wasm-bindgen к зависимостям.
[package]
name = "fib-wasm"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.74"

Теперь мы проверим нашу настройку, создав простую функцию greet, которая является оболочкой для alert из наших браузеров:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    pub fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

Давайте скомпилируем его:

$ wasm-pack build 

Это создаст каталог pkg в нашем проекте с файлом модуля .js, а также наш скомпилированный код rust для .wasm.

Тестирование с помощью HTML

Самый простой способ запустить наш пример — создать файл index.html в корне нашего проекта cargo.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="module">
      import init, { greet } from "./pkg/fib_wasm.js";

      init().then(() => {
        greet("It works!");
      });
    </script>
  </body>
</html>

Обратите внимание, что запуск этого показывает нам предупреждение в браузере. Обратите внимание, что мы используем новую функцию type=module, которая является новой функцией браузера, поэтому нам не нужно иметь дело с упаковщиками для нашего небольшого эксперимента.

Вариант использования: медленная функция Фибоначчи

Мы начнем с создания функции, которая регистрирует время выполнения.

function logExecutionTime(fn) {
  console.time("Start time");
  fn();
  console.timeEnd("End time");
}

А теперь определите медленную функцию JS fib(n):

function fib(n) {
  if (n <= 1) {
    return n;
  }
  return fib(n - 1) + fib(n - 2);
}

Запустив его так, мы можем увидеть результаты теста:

logExecutionTime(fib.bind(null, 40));
// logs timer: 2466ms - timer ended

Теперь давайте перейдем к нашему коду Rust и напишем улучшенную версию этой функции:

use wasm_bindgen::prelude::*;

#[no_mangle]
#[wasm_bindgen]
pub extern "C" fn fib(n: i32) -> i32 {
    if n <= 1 {
        return 1;
    }

    let mut a = 0;
    let mut b = 1;
    let mut c = 0;
    for _i in 1..n {
        c = a + b;
        a = b;
        b = c;
    }
    c
}

Этот код использует итеративный подход вместо рекурсивного, который намного быстрее и эффективнее.

Давайте посмотрим, как это работает:

import init, { rust_fib } from "./pkg/fib_wasm.js";
// ...

init().then(() => {
    logExecutionTime(rust_fib.bind(null, 40));
    // Logs 8ms
 });

Прирост производительности довольно значительный. Фактически, оптимизированный код с использованием Rust и WebAssembly работает почти в 10 раз быстрее, чем исходный код JavaScript.

Это демонстрирует возможности Rust и WebAssembly в повышении производительности вашего кода, а также подчеркивает, почему стоит учитывать эту комбинацию технологий при оптимизации ваших приложений JavaScript. Улучшенная производительность обеспечит лучший пользовательский интерфейс для ваших пользователей, а также позволит вашему приложению легко справляться с более требовательными задачами.

Заключение

В заключение, Rust и WebAssembly — это мощные технологии, которые могут помочь вам оптимизировать код JavaScript и добиться значительного повышения производительности. Являетесь ли вы опытным веб-разработчиком или только начинаете, самое время изучить возможности Rust и WebAssembly. Так почему бы не попробовать? Вы можете быть просто удивлены тем, чего вы можете достичь.

Удачного кодирования! | Если хотите, вы можете поддержать мой контент здесь. :)