los*_*aut 5 node.js rust apache-arrow rust-arrow2
使用 Apache Arrow 格式将数据从 Node.js 传递到 Rust 的最佳方法是什么?用每种语言存储数据很容易,但共享内存给我带来了挑战。
我正在使用Napi-rs生成 node.js API 绑定。
对于下面的 JavaScript 代码,我收到“无法从缓冲区创建引用”的消息。当我尝试传递arrowVector.data[0].buffers给 rust 函数时,我得到 "../src/node_buffer.cc:245:char *node::Buffer::Data(Local<v8::Value>): Assertion `val->IsArrayBufferView() ' 失败的。”
我想我在这里缺少一些核心内容。
这是我的示例节点测试代码:
import { makeVector } from 'apache-arrow';
import {testFn} from './index.js';
// Create arrow Vec
const LENGTH = 2000;
const rainAmounts = Float32Array.from(
{ length: LENGTH },
() => Number((Math.random() * 20).toFixed(1)));
const arrowVector = makeVector(rainAmounts);
// how to get buffers from vec? and send to rust function
testFn(arrowVector);
Run Code Online (Sandbox Code Playgroud)
这是我的 Rust 代码示例:
use napi::bindgen_prelude::Buffer;
#[napi]
pub fn test_fn(buffers: Buffer) {
println!("test_fn called");
}
Run Code Online (Sandbox Code Playgroud)
NAPI-RS确实提到:
BufferRust 和 Node.js 之间通过和进行零拷贝数据交互TypedArray
但是...您直接传递给 Rust 函数的不是缓冲区。
它是一个箭头向量。
testFn(arrowVector);
Run Code Online (Sandbox Code Playgroud)
这与 Rust 方面不兼容:
#[napi]
pub fn test_fn(buffers: Buffer) {
println!("test_fn called");
}
Run Code Online (Sandbox Code Playgroud)
因此,出现Failed to create reference from Buffer错误消息。
在 Node.js 代码中,获取 Arrow 向量的缓冲区并将它们直接传递给 Rust。
import { makeVector } from 'apache-arrow';
import {testFn} from './index.js';
// Create arrow Vec
const LENGTH = 2000;
const rainAmounts = Float32Array.from(
{ length: LENGTH },
() => Number((Math.random() * 20).toFixed(1))
);
const arrowVector = makeVector(rainAmounts);
// Get buffers from the Arrow vector and send to Rust
testFn(arrowVector.data.buffers[0].buffer);
Run Code Online (Sandbox Code Playgroud)
在 Rust 中,Napi-rs 缓冲区应该能够直接从 Node.js 获取缓冲区。
use napi::{CallContext, Env, JsObject, Result, Task};
use napi_derive::napi;
#[napi]
fn test_fn(ctx: CallContext) -> Result<JsObject> {
let buffer: Buffer<u8> = ctx.get::<Buffer<u8>>(0)?;
// Here, buffer.data() gives you a slice to the actual data
println!("test_fn called with buffer of length {}", buffer.length());
ctx.env.get_undefined()
}
Run Code Online (Sandbox Code Playgroud)
但是,请记住,箭头向量通常包含多个缓冲区。根据所涉及的数据类型,您可能需要将多个缓冲区从 Node.js 传递到 Rust 并在 Rust 中正确解释它们。
看apache/arrow/js/src/data.ts#buffers()
public get buffers() {
return [this.valueOffsets, this.values, this.nullBitmap, this.typeIds] as Buffers<T>;
}
Run Code Online (Sandbox Code Playgroud)
这种方法可以让您避免复制数据,但内存仍然由 Node.js 管理,因此您需要小心生命周期。如果 Node.js 垃圾收集原始 Arrow 向量,则传递给 Rust 的缓冲区数据可能会被释放。为了避免这种情况,请确保只要 Rust 代码可以访问其数据,Node.js 中的箭头向量就保持在范围内并处于活动状态。
有关更多信息,请参阅“变量在 Node.js 中在内存中保留多长时间”。