包阅导读总结
1. `Rust`、`WebAssembly`、`数据分析`、`前端开发`、`AI 技术`
2. 本文介绍了在超大型远洋航运船舶管理系统中,借助 Rust 和 AI 技术在 Web 端实现智能数据分析及可视化渲染,阐述了背景、技术挑战、优势及实现过程,包括环境准备、代码编译、数据处理与分析、与前端工程集成和端侧 AI 能力探索。
3.
– 引言
– 介绍在超大型远洋航运船舶管理系统中借助 Rust 和 AI 技术实现 Web 端智能数据分析和可视化渲染工作。
– 背景
– 指出在现代 Web 应用中处理和展示海量数据的需求及传统前端技术的不足。
– 技术挑战
– 列举在浏览器环境中进行复杂数据处理面临的性能瓶颈、计算效率、资源消耗等问题。
– Rust 与 WebAssembly 的优势
– 说明 Rust 和 WebAssembly 组合可解决上述挑战。
– 主要脉络
– 介绍将 Rust Code 编译为 WASM 并在 WEB 端集成的环境准备、项目初始化、配置、构建过程。
– 阐述如何借助 Rust 实现大批量数据的预处理与分析,包括基础和并发处理,以及与前端工程的 Webpack 集成和端侧 AI 能力探索。
– 结语
– 总结 Rust 和 WebAssembly 组合在 Web 端数据处理方面的优势及未来潜力。
思维导图:
文章地址:https://mp.weixin.qq.com/s/uN39-nZYyCE-VRpN0zvdEw
文章来源:mp.weixin.qq.com
作者:cyber
发布时间:2024/8/21 2:35
语言:中文
总字数:4225字
预计阅读时间:17分钟
评分:91分
标签:Web开发,Rust,WebAssembly,数据分析,前端技术
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
本文作者为 360 奇舞团前端开发工程师
引言
在现代 Web 开发中,将高性能计算和智能分析集成到前端应用中已经成为一种趋势。本文将介绍在超大型远洋航运颗/货船舶管理系统中,借助于 Rust 和 AI 技术实现 Web 侧 端智能数据分析处理海量传感器数据进行可视化界面的渲染工作,通过一系列的数据清洗、转换和分析,提升用户体验。
背景
数据分析与预处理的需求
在现代 Web 应用中,特别是在数据密集型的应用场景下,处理和展示海量数据是一项具有挑战性的任务。传统的前端技术堆栈,如 JavaScript 和框架库,虽然能提供基本的数据处理功能,但在面对复杂的数据分析任务时可能显得力不从心。这些任务包括数据清洗、转换、聚合、以及实时分析等。
随着数据规模的增大和分析需求的复杂化,前端应用需要能够高效地处理大量数据,同时保持良好的用户体验。例如,电商平台需要实时处理用户行为数据来提供个性化推荐,社交媒体应用需要分析用户生成内容以进行情感分析,金融应用则需要实时处理市场数据以进行预测和决策支持。
技术挑战
在浏览器环境中进行复杂的数据处理面临几个主要挑战:
-
性能瓶颈:JavaScript 的单线程模型限制了其在处理大量数据时的性能,尤其是涉及到复杂计算和数据分析时。 -
计算效率:在进行复杂数据处理时,JavaScript 的执行速度可能不够高效,特别是在处理海量数据时。 -
资源消耗:前端的资源(如内存和计算能力)有限,处理大量数据可能导致浏览器变得响应迟钝或崩溃。
Rust 与 WebAssembly 的优势
为了应对这些挑战,Rust 和 WebAssembly (WASM) 的组合提供了一种解决方案。Rust 是一种系统编程语言,具有高效的内存管理和高性能的计算能力。WebAssembly 是一种可以在浏览器中运行的低级字节码格式,它允许开发者用非 JavaScript 语言编写代码,并将其编译为可以在浏览器中执行的高效二进制格式。
主要脉络
熟悉或者已经阅读过 Mdn 上面关于如何实现“Compiling from Rust to WebAssembly”的小伙伴可以跳过前面这一部分。
-
介绍如何将 Rust Code 编译为 WASM,编译为 WebAssembly 并在 WEB 端集成。 -
场景化演示:使用 Rust Code 实现海量数据的数据与处理与数据分析。
环境准备
无需过多心理压力,本文中的代码会尽可能得将注释和用意阐述清晰完整,纵使对于 Rust 这门编程语言一窍不通的读者也不会有过多的阅读障碍。
首先我们需要安装 Rust 和 WebAssembly 工具链:
#安装Rust
curl--proto'=https'--tlsv1.2-sSfhttps://sh.rustup.rs|sh
#安装wasm-pack
cargoinstallwasm-pack
#addWebAssemblytarget
rustuptargetaddwasm32-unknown-unknown
此处对于不同操作系统的 PC 如何安装 Rust 可以参考https://www.rust-lang.org/tools/install,此处不做过多赘述。
wasm-pack,由于我们需要打包工具,所有这里引出了一个额外的工具–wasm-pack,有了 wasm-pack,我们可以将 rust code 编译为 WebAssembly,供给 WEB 端进行调用;
Rust 项目初始化
接下来我们在命令行输入类似于如下的命令:
cargonew--libyour-rust-project
此处为了方面演示,使用了 cargo new –lib rust-social-emotion-analysis 这个名称作为 Rust 项目根目录在 cargo new –lib your-rust-project 命令执行过后,我们会看到本地多出了以下几个文件:
├──Cargo.toml
└──src
└──lib.rs
这里我们可以使用 Cargo.toml 对构建进行配置,Cargo.toml 类似于前端工程的 package.json 文件。
cd src,进入到 src 目录中之后,我们会发现 lib.rs 内部的几行代码:
#[cfg(test)]
modtests{
#[test]
fnit_works(){
assert_eq!(2+2,4);
}
}
这部分代码直接删除即可,然后替换为我们需要的 demo code:
//引入wasm_bindgen库,这允许Rust代码与WebAssembly的JavaScript进行无缝交互
usewasm_bindgen::prelude::*;
//使用#[wasm_bindgen]属性声明外部JavaScript函数
//这里声明了一个名为`alert`的函数,该函数会在浏览器中弹出alert框
#[wasm_bindgen]
extern{
//外部函数`alert`,用于显示alert对话框,接受一个字符串参数
//在浏览器环境中,这会弹出一个alert框显示传入的消息
pubfnalert(s:&str);
}
//使用#[wasm_bindgen]属性公开Rust函数,使其可被JavaScript代码调用
//这个函数将用于向用户打招呼
#[wasm_bindgen]
pubfngreet(name:&str){
//使用Rust的`format!`宏创建一个格式化的greet字符串
//`format!`宏将`name`参数插入到字符串中,生成类似"Hello,John!"的greet信息
//调用外部的`alert`函数来弹出显示该greet信息
alert(&format!("Hello,{}!",name));
}
这里之所以引入 wasm_bindgen 这一 Crate 的原因是 wasm-pack 需要借助于 wasm-bindgen 来生成桥接 Javascript 与 Rust 的代码,进而使得我们可以在 JS 中调用 Rust API 或者 Rust 函数。
配置 Cargo.toml
打开项目的 cargo.toml 文件按照如下进行配置:
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
通过以上代码,首先我们添加了[package],其次通过[lib]这一部分是为了告知 Rust 我们想要打包成 cdylib 的版本。最后的[dependencies]是为了让 Cargo 知道我们依赖于 wasm-bindgen 0.2.x 版本。
构建
这里我们通过以下一段简短的命令进行构建:
wasm-packbuild--targetweb

根据 Mozilla Hacks 上面的描述,简而言之以上代码大致做了以下五件事:
-
在新编译的 WASM 内部运行 wasm-bindgen,生成一个将新的 WebAssembly 文件以模块形式包裹引入到浏览器端的 js 文件 -
新建一个 pkg 目录,并将上面最新生成的 js 和 webAssembly 文件移入其中 -
读取项目的 Cargo.toml 文件并且据此生成 package.json -
将项目内部的 README.md 拷贝到 pkg 中
截至目前为止,我们的 Rust 项目目录基本如下:
├──Cargo.lock
├──Cargo.toml
├──index.html<--新建一个index.html文件放置于Rust工程的根目录
├──pkg
│├──hello_wasm.d.ts
│├──hello_wasm.js
│├──hello_wasm_bg.wasm
│├──hello_wasm_bg.wasm.d.ts
│└──package.json
├──src
│└──lib.rs
└──target
├──CACHEDIR.TAG
├──release
└──wasm32-unknown-unknown
在根目录新建一个 index.html 文件,并在其中编写如下代码:
<!DOCTYPEhtml>
<htmllang="en-US">
<head>
<metacharset="utf-8"/>
<title>hello-wasmexample</title>
</head>
<body>
<scripttype="module">
importinit,{greet}from"./pkg/hello_wasm.js";
init().then(()=>{
greet("WebAssembly");
});
</script>
</body>
</html>
OK,现在我们可以借助于 http-server 启动一个本地的静态资源服务,浏览页面效果:
npxhttp-server
至此,我们的第一步,即–“将 Rust Code 编译为 WASM,编译为 WebAssembly 并在 WEB 端集成”基本实现完成了。这部分为了方面演示省略了很多譬如压缩 Rust 转化为 WASM 文件的体积、以及老生常谈的 Rust 所有权和借用系统。
接下来我们看一下如何借助于 rust 实现海量数据的预处理与数据分析工作,以满足我们页面可视化渲染相关的需求。
大批量数据的预处理与分析
这一部分我们将重点讨论如何使用 Rust 的并发特性来提高数据处理的效率,并将结果集成到 WebAssembly 中以用于浏览器端的数据分析。
引入所需的库
//引入wasm-bindgen库的预处理模块,用于与JavaScript交互
usewasm_bindgen::prelude::*;
定义数据结构
//定义一个结构体来表示传感器数据项
//结构体包含一个id和一个值,分别表示数据项的唯一标识符和传感器读取的值
#[derive(Clone,Debug)]
structSensorData{
id:u32,
value:f64,
}
基础数据预处理
//通过一个函数来对数据进行预处理,例如筛选出值大于某个阈值的数据
#[wasm_bindgen]
pubfnpreprocess_sensor_data(data:&[SensorData],threshold:f64)->Vec<SensorData>{
//使用迭代器和过滤方法筛选出符合条件的数据
data.iter()
.filter(|item|item.value>threshold)
.cloned()
.collect()
}
并发数据预处理
为了提高处理海量数据的效率,我们可以利用 Rust 的并发特性。使用 rayon 库,可以轻松实现数据的并行处理。
首先,添加 rayon 依赖到 Cargo.toml:
[dependencies]
wasm-bindgen = "0.2"
rayon = "1.5" // 添加 rayon 依赖
接下来,修改数据预处理函数以利用并发处理:
//引入rayon库
userayon::prelude::*;
//并发数据预处理逻辑
#[wasm_bindgen]
pubfnparallel_preprocess_sensor_data(data:&[SensorData],threshold:f64)->Vec<SensorData>{
//使用rayon的并行迭代器来加速数据预处理
data.par_iter()//使用并行迭代器
.filter(|item|item.value>threshold)
.cloned()
.collect()
}
这里主要做了两件事:
-
parallel_preprocess_sensor_data 函数使用 rayon 的 par_iter() 方法将数据迭代并行化,从而提高处理速度。 -
rayon 会自动将任务分配到多个线程中,并且在合适的条件下使用并行计算来加速数据处理。
数据分析
基础数据分析:
//对数据进行分析,例如计算数据的平均值
#[wasm_bindgen]
pubfnanalyze_sensor_data(data:&[SensorData])->f64{
//计算总和
letsum:f64=data.iter().map(|item|item.value).sum();
//计算平均值
sum/data.len()asf64
}
并发数据分析
对于大数据集的并发分析,特别是需要进行复杂计算时,利用并发可以显著提高性能:
//引入rayon库
userayon::prelude::*;
//并发分析计算数据的标准差
#[wasm_bindgen]
pubfnparallel_analyze_sensor_data(data:&[SensorData])->f64{
//使用rayon的并行迭代器来加速数据分析
letmean=analyze_sensor_data(data);
letvariance:f64=data.par_iter()//使用并行迭代器
.map(|item|(item.value-mean).powi(2))//计算每个数据点与均值的平方差
.sum();//汇总平方差
//计算标准差
(variance/data.len()asf64).sqrt()
}
与前端工程的 Webpack 集成
在项目的 webpack.config.js 类似的配置文件中,添加 WebAssembly 支持:
constpath=require("path");
constWasmPackPlugin=require("@wasm-tool/wasm-pack-plugin");
module.exports={
configureWebpack:{
plugins:[
newWasmPackPlugin({
crateDirectory:path.resolve(__dirname,"rust_data_processing"),
}),
],
experiments:{
asyncWebAssembly:true,
},
},
};
在 Vue 项目中的调用:
<template>
<div>
<h1>数据分析</h1>
<p>预处理后的数据:{{processedData}}</p>
<p>分析结果:{{analysisResult}}</p>
</div>
</template>
<scriptlang="ts">
import{defineComponent,onMounted,ref}from'vue';
importinit,{parallel_preprocess_sensor_data,parallel_analyze_sensor_data}from'rust_data_processing';
exportdefaultdefineComponent({
setup(){
constprocessedData=ref<SensorData[]>([]);
constanalysisResult=ref<number|null>(null);
onMounted(async()=>{
awaitinit();//初始化WebAssembly模块
constrawData:SensorData[]=[/*海量传感器数据*/];
constthreshold=10.0;
//预处理数据
processedData.value=parallel_preprocess_sensor_data(rawData,threshold);
//分析数据
analysisResult.value=parallel_analyze_sensor_data(processedData.value);
});
return{processedData,analysisResult};
},
});
</script>
<stylescoped>
/*样式*/
</style>
端侧 AI 能力探索
这一部分我们主要探索如何编写数据处理代码
定义数据结构和实现数据预处理功能,例如数据标准化和特征提取:
//引入必要的库
usewasm_bindgen::prelude::*;
usendarray::Array2;
usendarray_rand::RandomExt;
usendarray_rand::rand_distr::Uniform;
//定义数据结构
#[derive(Debug,Clone)]
pubstructSensorData{
id:u32,
value:f64,
}
//实现数据预处理函数
#[wasm_bindgen]
pubfnpreprocess_sensor_data(data:&[SensorData],threshold:f64)->Vec<SensorData>{
//过滤掉值低于阈值的数据
data.iter()
.filter(|item|item.value>threshold)
.cloned()
.collect()
}
K-Means 聚类是一种广泛使用的无监督学习算法,用于将数据分组为 K 个簇。一个 Rust 实现的 K-Means 聚类库,适用于高性能计算。Rust 版 K-Means 实现主要有Rust K-Means —- Rust 实现的 K-Means 聚类库,适用于高性能计算以及rust-kmeans — Crates.io 上的 rust-kmeans 库,可用于 K-Means 聚类算法的实现。
此处我们使用 ndarray 实现基本的聚类算法(K-Means)作为数据分析的一部分:
//引入必要的库
usewasm_bindgen::prelude::*;
usendarray::Array2;
usendarray_rand::RandomExt;
usendarray_rand::rand_distr::Uniform;
//定义数据结构
#[derive(Debug,Clone)]
pubstructSensorData{
id:u32,
value:f64,
}
//数据预处理
#[wasm_bindgen]
pubfnpreprocess_sensor_data(data:&[SensorData],threshold:f64)->Vec<SensorData>{
//过滤掉值低于阈值的数据
data.iter()
.filter(|item|item.value>threshold)
.cloned()
.collect()
}
结语
本文主要探索了如何利用 Rust 和 WebAssembly 的组合,将数据处理能力引入 Web 端。通过 Rust 的并发计算和 WASM 的高执行效率优势,尝试克服传统 JavaScript 的性能瓶颈,进而实现了在浏览器中进行复杂数据分析的可能性。随着 AI 快速发展的当下,Rust + WASM 凭借着高并发、高执行效率以及跨平台的优势,将会是端智能甚至是边缘计算中一个非常不错的选择。
参考文档
-
Compiling from Rust to WebAssembly: https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_Wasm -
https://developer.mozilla.org/en-US/docs/WebAssembly -
https://github.com/yewstack/yew -
https://www.rust-lang.org/tools/installls -
https://github.com/rust-ndarray/ndarray -
https://en.wikipedia.org/wiki/K-means_clustering -
https://docs.rs/ndarray/latest/ndarray/