# Pass JS Float64Array to Rust using WASM

**URL:** <https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669>\
**Category:** help\
**Created:** [February 16, 2021, 2:31am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669 "2021-02-16T02:31:44Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 16, 2021, 2:31am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/1 "2021-02-16T02:31:45Z")

</div>

I want to pass an array of floating point numbers from JavaScript to Rust using WASM. I think I should create a Float64Array in the JavaScript code and pass it to a Rust function that takes `&[f64]`. Is this currently possible? If so, can someone point me to an example that does this or something similar?

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [February 16, 2021, 5:13am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/2 "2021-02-16T05:13:50Z")

</div>

You can pass a `&Float64Array` and call [view](https://docs.rs/js-sys/0.3.47/js_sys/struct.Float64Array.html#method.view) on it.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 16, 2021, 11:30am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/3 "2021-02-16T11:30:49Z")

</div>

Could you point me to an example of using this that shows both the JS and Rust code?

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [February 16, 2021, 1:45pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/4 "2021-02-16T13:45:33Z")

</div>

not really…

JS:

```javascript
var arr = new Float64Array(…);
wasm_bindgen.foo(arr);

```

Rust:

```rust
#[wasm_bindgen]
fn foo(arr: &Float64Array) {
   let data = unsafe { arr.view() };
   println!("{}", data[0]);
}

```

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/bjorn3/32/5255_2.png) [@bjorn3](https://users.rust-lang.org/u/bjorn3)\
**Post date:** [February 16, 2021, 1:59pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/5 "2021-02-16T13:59:28Z")

</div>

`Float64Array::view` makes a `Float64Array` which is a view into the specified WASM linear memory covering just the slice. You can use `.copy_to()` or `.to_vec()` to get the contents of the array.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 17, 2021, 12:38am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/6 "2021-02-17T00:38:20Z")

</div>

This line gives the error "no method named `view` found for reference `&Float64Array` in the current scope; this is an associated function, not a method":

```rust
   let data = unsafe { arr.view() };

```

So I changed it to this:

```rust
   let data = unsafe { Float64Array::view(&arr) };

```

But that gives the error "mismatched types; expected slice `[f64]`, found `&Float64Array`"

I can use the `to_vec` method to copy the Float64Array into a vector. But I was hoping to find a way to access shared memory so the Rust code can use data from JavaScript without an copying. Is that possible? Is this what the `copy_to` and `to_vec` methods do?

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/bjorn3/32/5255_2.png) [@bjorn3](https://users.rust-lang.org/u/bjorn3)\
**Post date:** [February 17, 2021, 9:05am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/7 "2021-02-17T09:05:09Z")

</div>

You have to copy it into the linear memory one way or the other, as this is the only thing wasm can directly access. Everything else has to go through javascript. The `copy_to` and `to_vec` methods copy a `Float64Array` into the linear memory of the current wasm module.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 17, 2021, 12:32pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/8 "2021-02-17T12:32:05Z")

</div>

It’s the “one way or the other” part that is confusing me. I can’t find a single example on web of doing this. Has anyone seen code that does this?

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [February 17, 2021, 1:25pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/9 "2021-02-17T13:25:02Z")

</div>

Right.

I have running code using Uint8Array:  
JS: [https://github.com/pdf-rs/pdf\_render/blob/master/wasm/index.js#L41](https://github.com/pdf-rs/pdf_render/blob/master/wasm/index.js#L41)  
Rust: [https://github.com/pdf-rs/pdf\_render/blob/master/view/src/lib.rs#L106](https://github.com/pdf-rs/pdf_render/blob/master/view/src/lib.rs#L106)

And indeed it uses to\_vec.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 17, 2021, 2:13pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/10 "2021-02-17T14:13:02Z")

</div>

Ah, this helped a lot! I have it working now, but the Rust version still is much slower than the JS version.  
See [https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/index.js#L45](https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/index.js#L45)  
and [https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/src/lib.rs#L17](https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/src/lib.rs#L17).  
Am I still doing something wrong that would explain the performance issue?

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [February 17, 2021, 2:24pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/11 "2021-02-17T14:24:43Z")

</div>

Rust can only access data that is in the Wasm memory. Typed arrays are not and so they have to be copied into memory accessible by Rust first.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 17, 2021, 2:26pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/12 "2021-02-17T14:26:26Z")

</div>

Can you point me to an example of copying a typed array into wasm memory?

---

<div class="post-metadata">

**Author:** ![s3bk](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/s3bk/32/16472_2.png) [@s3bk](https://users.rust-lang.org/u/s3bk)\
**Post date:** [February 17, 2021, 2:28pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/13 "2021-02-17T14:28:00Z")

</div>

When you call `.to_vec()` it copies the contents into Rusts memory.

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [February 17, 2021, 3:59pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/14 "2021-02-17T15:59:08Z")

</div>

You could avoid copying by creating a `Vec<f64>` in Rust and using `Float64Array::view` to create a `Float64Array` for JavaScript code to access it. This will let Rust and JavaScript share the same memory, instead of copying data back and forth.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 17, 2021, 4:34pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/15 "2021-02-17T16:34:29Z")

</div>

I currently create a `Vector<f64>` in Rust here: [https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/src/lib.rs#L26](https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/src/lib.rs#L26). That function returns a pointer to this back to JavaScript. Where are you suggesting I should call `Float64Array::view`?

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [February 17, 2021, 4:40pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/16 "2021-02-17T16:40:25Z")

</div>

That Vec is dropped as soon as the `get_vector_pointer` function exits, so it returns a dangling pointer.

Luckily, your [JavaScript code](https://github.com/mvolkmann/wasm-bind-demo/blob/11d4cf749c102078e0b8687b6527ac7f77bee8f5/index.js#L46) never actually uses that pointer, since `Float64Array(numbers, ...)` creates an array from the `numbers` list which was allocated in JavaScript. You then pass this JS-created `Float64Array` to your `sum` function.

One zero-copy possibility would be the following Rust code:

```rust
#[wasm_bindgen]
pub fn sum(ptr: *mut f64, count: usize) -> f64 {
    let data = unsafe { std::slice::from_raw_parts(ptr, count) };
    data.iter().sum()
}

#[wasm_bindgen]
pub fn get_vec_pointer(count: usize) -> *mut f64 {
    let mut v = Vec::with_capacity(count);
    let ptr = v.as_mut_ptr();
    std::mem::forget(v);
    ptr
}

#[wasm_bindgen]
pub fn get_array(ptr: *mut f64, count: usize) -> Float64Array {
    unsafe { Float64Array::view(std::slice::from_raw_parts(ptr, count)) }
}

```

Which would be called from JavaScript like this:

```javascript
function populateNumbers(numbers) {
  for (let i = 0; i < numbers.length; i++) {
    numbers[i] = Math.random() * 100;
  }
}

const ptr = m.get_vec_pointer(COUNT);
const arr = m.get_array(ptr, COUNT);
populateNumbers(arr);

startMs = Date.now();
result = m.sum(ptr, COUNT);
endMs = Date.now();

```

In release mode, this runs in 7ms on my laptop.

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [February 17, 2021, 4:53pm UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/17 "2021-02-17T16:53:39Z")

</div>

> [@mvolkmann](#):
>
> I want to pass an array of floating point numbers from JavaScript to Rust using WASM. I think I should create a Float64Array in the JavaScript code and pass it to a Rust function that takes `&[f64]` . Is this currently possible?

Yes, there are examples in the [wasm-bindgen refererence](https://rustwasm.github.io/docs/wasm-bindgen/reference/types/number-slices.html). In your code, it would look like this:

**Rust:**

```rust
#[wasm_bindgen]
pub fn sum(data: &[f64]) -> f64 {
    data.iter().sum()
}

```

**JavaScript:**

```rust
const numbers = getNumbers(COUNT);
const arr = new Float64Array(numbers);

startMs = Date.now();
result = m.sum(numbers);
endMs = Date.now();

```

This version takes 13ms in release mode on my laptop. So in this micro-benchmark, the copying overhead almost doubles the runtime. But if you were benchmarking a more expensive computation, the copying overhead might not be noticeable.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 18, 2021, 12:22am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/18 "2021-02-18T00:22:17Z")

</div>

Thanks so much for taking the time to look at this!

My `package.json` has two npm scripts, "build" (runs `webpack`) and "serve" (runs `webpack-dev-server`). Neither builds a release version of the Rust code. I tried running `cargo build --release` followed by `npm run serve`, but the performance didn't improve so I'm guessing it isn't really using the release version. How did you get it to build and use a release version?

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [February 18, 2021, 4:04am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/19 "2021-02-18T04:04:48Z")

</div>

I changed the `mode` property in `webpack.config.js` from `'development'` to `'production'`.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [February 18, 2021, 11:42am UTC](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669/20 "2021-02-18T11:42:52Z")

</div>

Whoa! That made a huge difference! The time for the Rust code went from 119 ms on my machine to 3 ms and now it is about 1/6 the time of the JavaScript code.

[Next page](https://users.rust-lang.org/t/pass-js-float64array-to-rust-using-wasm/55669.md?page=2)
