首页 文章 精选 留言 我的

精选列表

搜索[高性能通信库],共10000篇文章
优秀的个人博客,低调大师

用 Rust 创建高性能 JavaScript API,并在 WebAssembly 中运行

WasmEdge 正在参加今年的 Hacktoberfest,为开源项目贡献4个 PR,就能获得 Hacktoberfest 提供的一件 T shirt 。 WasmEdge 将 Rust 的性能和 JavaScript 的易用性结合在一起 在我之前的文章中,我讨论了如何将 JavaScript 代码嵌入到 Rust 程序。 然而,对于 JavaScript 开发者来说,需求往往相反——是将 Rust 函数合并到 JavaScript API 中。 这使开发者能够使用“纯 JavaScript”编写程序,同时仍然可以利用 Rust 函数的绝佳性能。 使用 WasmEdge Runtime ,你可以做到这一点。 接下来,让我们看几个示例。查看 wasmedge-quickjs Github repo 并打开 examples/embed_js 文件夹。 $ git clone https://github.com/second-state/wasmedge-quickjs $ cd examples/embed_js 要先安装 Rust 和 WasmEdge 才能构建和运行本文中的示例。 embed_js demo 展示了几个关于如何在 Rust 中嵌入 JavaScript 的不同示例。 你可以按如下方式构建和运行所有示例。 $ cargo build --target wasm32-wasi --release $ wasmedge --dir .:. target/wasm32-wasi/release/embed_js.wasm 创建一个 JavaScript 函数 API 以下代码片段定义了一个 Rust 函数,该函数可以作为 API 合并到 JavaScript 解释器中。 fn run_rust_function(ctx: &mut Context) { struct HelloFn; impl JsFn for HelloFn { fn call(_ctx: &mut Context, _this_val: JsValue, argv: &[JsValue]) -> JsValue { println!("hello from rust"); println!("argv={:?}", argv); JsValue::UnDefined } } ... } 下面的代码片段展示了如何将这个 Rust 函数添加到 JavaScript 解释器中,命名为 hi() 作为它的 JavaScript API,然后从 JavaScript 代码中调用它。 fn run_rust_function(ctx: &mut Context) { ... let f = ctx.new_function::<HelloFn>("hello"); ctx.get_global().set("hi", f.into()); let code = r#"hi(1,2,3)"#; let r = ctx.eval_global_str(code); println!("return value:{:?}", r); } 执行结果如下: hello from rust argv=[Int(1), Int(2), Int(3)] return value:UnDefined 使用这种方法,可以创建一个带有自定义 API 函数的 JavaScript 解释器。 解释器在 WasmEdge 内部运行,可以从 CLI 或网络执行调用此类 API 函数的 JavaScript 代码。 创建 JavaScript 对象 API 在 JavaScript API 设计中,我们有时需要提供一个同时封装数据和函数的对象。 在以下示例中,我们为 JavaScript API 定义了一个 Rust 函数。 fn rust_new_object_and_js_call(ctx: &mut Context) { struct ObjectFn; impl JsFn for ObjectFn { fn call(_ctx: &mut Context, this_val: JsValue, argv: &[JsValue]) -> JsValue { println!("hello from rust"); println!("argv={:?}", argv); if let JsValue::Object(obj) = this_val { let obj_map = obj.to_map(); println!("this={:#?}", obj_map); } JsValue::UnDefined } } 然后我们在 Rust 端创建一个“对象”,设置它的数据字段,然后将 Rust 函数注册为与对象关联的 JavaScript 函数。 let mut obj = ctx.new_object(); obj.set("a", 1.into()); obj.set("b", ctx.new_string("abc").into()); let f = ctx.new_function::<ObjectFn>("anything"); obj.set("f", f.into()); 接下来,我们使 Rust “对象”作为 JavaScript 对象 test_obj在 JavaScript 解释器中可用。 ctx.get_global().set("test_obj", obj.into()); 在 JavaScript 代码中,你现在可以直接使用 test_obj 作为 API 的一部分。 let code = r#" print('test_obj keys=',Object.keys(test_obj)) print('test_obj.a=',test_obj.a) print('test_obj.b=',test_obj.b) test_obj.f(1,2,3,"hi") "#; ctx.eval_global_str(code); } 执行结果如下。 test_obj keys= a,b,f test_obj.a= 1 test_obj.b= abc hello from rust argv=[Int(1), Int(2), Int(3), String(JsString(hi))] this=Ok( { "a": Int( 1, ), "b": String( JsString( abc, ), ), "f": Function( JsFunction( function anything() { [native code] }, ), ), }, ) 一个完整的 JavaScript 对象 API 在前面的示例中,我们演示了从 Rust 创建 JavaScript API 的简单示例。 在这个例子中,我们将创建一个完整的 Rust 模块并将其作为 JavaScript 对象 API 提供。 该项目位于 examples/embed_rust_module 文件夹中。 你可以在 WasmEdge 中将其作为标准 Rust 应用程序构建和运行。 $ cargo build --target wasm32-wasi --release $ wasmedge --dir .:. target/wasm32-wasi/release/embed_rust_module.wasm 该对象的 Rust 实现是一个模块,如下所示。 它具有数据字段、构造函数、getter 和 setter 以及函数。 mod point { use wasmedge_quickjs::*; #[derive(Debug)] struct Point(i32, i32); struct PointDef; impl JsClassDef<Point> for PointDef { const CLASS_NAME: &'static str = "Point\0"; const CONSTRUCTOR_ARGC: u8 = 2; fn constructor(_: &mut Context, argv: &[JsValue]) -> Option<Point> { println!("rust-> new Point {:?}", argv); let x = argv.get(0); let y = argv.get(1); if let ((Some(JsValue::Int(ref x)), Some(JsValue::Int(ref y)))) = (x, y) { Some(Point(*x, *y)) } else { None } } fn proto_init(p: &mut JsClassProto<Point, PointDef>) { struct X; impl JsClassGetterSetter<Point> for X { const NAME: &'static str = "x\0"; fn getter(_: &mut Context, this_val: &mut Point) -> JsValue { println!("rust-> get x"); this_val.0.into() } fn setter(_: &mut Context, this_val: &mut Point, val: JsValue) { println!("rust-> set x:{:?}", val); if let JsValue::Int(x) = val { this_val.0 = x } } } struct Y; impl JsClassGetterSetter<Point> for Y { const NAME: &'static str = "y\0"; fn getter(_: &mut Context, this_val: &mut Point) -> JsValue { println!("rust-> get y"); this_val.1.into() } fn setter(_: &mut Context, this_val: &mut Point, val: JsValue) { println!("rust-> set y:{:?}", val); if let JsValue::Int(y) = val { this_val.1 = y } } } struct FnPrint; impl JsMethod<Point> for FnPrint { const NAME: &'static str = "pprint\0"; const LEN: u8 = 0; fn call(_: &mut Context, this_val: &mut Point, _argv: &[JsValue]) -> JsValue { println!("rust-> pprint: {:?}", this_val); JsValue::Int(1) } } p.add_getter_setter(X); p.add_getter_setter(Y); p.add_function(FnPrint); } } struct PointModule; impl ModuleInit for PointModule { fn init_module(ctx: &mut Context, m: &mut JsModuleDef) { m.add_export("Point\0", PointDef::class_value(ctx)); } } pub fn init_point_module(ctx: &mut Context) { ctx.register_class(PointDef); ctx.register_module("point\0", PointModule, &["Point\0"]); } } 在解释器的实现中,首先调用 point::init_point_module 将 Rust 模块注册到 JavaScript 上下文中,然后我们就可以运行一个简单地使用 point 对象的 JavaScript 程序。 use wasmedge_quickjs::*; fn main() { let mut ctx = Context::new(); point::init_point_module(&mut ctx); let code = r#" import('point').then((point)=>{ let p0 = new point.Point(1,2) print("js->",p0.x,p0.y) p0.pprint() try{ let p = new point.Point() print("js-> p:",p) print("js->",p.x,p.y) p.x=2 p.pprint() } catch(e) { print("An error has been caught"); print(e) } }) "#; ctx.eval_global_str(code); ctx.promise_loop_poll(); } 上述应用程序的执行结果如下。 rust-> new Point [Int(1), Int(2)] rust-> get x rust-> get y js-> 1 2 rust-> pprint: Point(1, 2) rust-> new Point [] js-> p: undefined An error has been caught TypeError: cannot read property 'x' of undefined 接下来 使用 Rust 函数和模块来实现 JavaScript API 是一个强大的想法。 这允许 WasmEdge Runtime 显着提高 JavaScript 应用程序的性能。 然而,Rust 函数仍然需要编译成 WebAssembly 字节码。 对于一些函数,比如 AI 推理,直接从 WasmEdge 调用原生 C 库函数效率更高。 在下一篇文章中,我们将讨论如何运用 WasmEdge 来支持 C 原生函数,然后将这些函数公开为 Rust 和 JavaScript API。 云原生 WebAssembly 中的 JavaScript 是下一代云和边缘计算基础设施中的新兴领域。 我们也是刚开始涉足。如果对此感兴趣,请加入 WasmEdge 项目或通过提出 feature request issue 告诉我们,你需要的是什么。

优秀的个人博客,低调大师

TLog v1.3.2 版本发布,全日志高性能版

TLog在v1.3.1发布之后,很长段时间没有更新。 在1.3.1版本中,有很多社区的小伙伴报出在logback的异步日志下,TLog占用内存过多,导致性能不佳。 这个bug在v1.3.2得到修复。改变了实现方式。同时增强了几个小功能。 如果你是第一次知道TLog,可以点击以下链接进行了解,可追踪日志增强的神器 官方网站:https://yomahub.com/tlog 仓库托管:https://gitee.com/dromara/TLog 也可以看这篇文章进行了解使用使用场景和理念: https://my.oschina.net/u/1584523/blog/4994375 本次更新日志如下: enhancement: #I4D4XB 目前logback的的异步日志会有内存占用过多的情况 https://gitee.com/dromara/TLog/issues/I4D4XB enhancement: #I419TD 输出日志,可以打印出当前服务ip https://gitee.com/dromara/TLog/issues/I419TD bug: #I3Y6LR 业务标签,数值类型long时,无法显示 https://gitee.com/dromara/TLog/issues/I3Y6LR

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册