We are trying to speed up JavaScript code using Rust (WebAssembly). The code is as follows, but it is noticeably slower than the equivalent JavaScript code. I had hoped that Rust (WebAssembly) would be faster, but am I missing something (e.g. compiler options)?
#[wasm_bindgen]
pub unsafe fn subtract(volume: JsValue, lathe: JsValue) {
let a: Volume = serde_wasm_bindgen::from_value(volume).unwrap();
let b: Lathe = serde_wasm_bindgen::from_value(lathe).unwrap();
let matrix_b_to_a = a.matrix.inverted().multiply(&b.matrix);
let x0 = b.bbox.min.x - b.threshold;
let x1 = b.bbox.max.x + b.threshold;
let y0 = b.bbox.min.y - b.threshold;
let y1 = b.bbox.max.y + b.threshold;
let z0 = b.bbox.min.z - b.threshold;
let z1 = b.bbox.max.z + b.threshold;
let p0 = matrix_b_to_a.multiply_point(&Point3::new(x0, y0, z0));
let p1 = matrix_b_to_a.multiply_point(&Point3::new(x1, y0, z0));
let p2 = matrix_b_to_a.multiply_point(&Point3::new(x0, y1, z0));
let p3 = matrix_b_to_a.multiply_point(&Point3::new(x1, y1, z0));
let p4 = matrix_b_to_a.multiply_point(&Point3::new(x0, y0, z1));
let p5 = matrix_b_to_a.multiply_point(&Point3::new(x1, y0, z1));
let p6 = matrix_b_to_a.multiply_point(&Point3::new(x0, y1, z1));
let p7 = matrix_b_to_a.multiply_point(&Point3::new(x1, y1, z1));
let min_x = min(&vec![p0.x, p1.x, p2.x, p3.x, p4.x, p5.x, p6.x, p7.x]);
let max_x = max(&vec![p0.x, p1.x, p2.x, p3.x, p4.x, p5.x, p6.x, p7.x]);
let min_y = min(&vec![p0.y, p1.y, p2.y, p3.y, p4.y, p5.y, p6.y, p7.y]);
let max_y = max(&vec![p0.y, p1.y, p2.y, p3.y, p4.y, p5.y, p6.y, p7.y]);
let min_z = min(&vec![p0.z, p1.z, p2.z, p3.z, p4.z, p5.z, p6.z, p7.z]);
let max_z = max(&vec![p0.z, p1.z, p2.z, p3.z, p4.z, p5.z, p6.z, p7.z]);
let (min_x_index, min_y_index, min_z_index) = a.get_index(&Point3::new(min_x, min_y, min_z));
let (max_x_index, max_y_index, max_z_index) = a.get_index(&Point3::new(max_x, max_y, max_z));
let min_x_index = clamp(min_x_index, 0, (a.resolution.x - 1) as i32) as usize;
let max_x_index = clamp(max_x_index, 0, (a.resolution.x - 1) as i32) as usize;
let min_y_index = clamp(min_y_index, 0, (a.resolution.y - 1) as i32) as usize;
let max_y_index = clamp(max_y_index, 0, (a.resolution.y - 1) as i32) as usize;
let min_z_index = clamp(min_z_index, 0, (a.resolution.z - 1) as i32) as usize;
let max_z_index = clamp(max_z_index, 0, (a.resolution.z - 1) as i32) as usize;
let manager = BufferManager::lock();
let arc_a = manager.get(a.values_id).unwrap();
let arc_b = manager.get(b.values_id).unwrap();
let mut mutex_a = arc_a.lock().unwrap();
let mutex_b = arc_b.lock().unwrap();
let values_a = mutex_a.slice_mut::<u8>();
let values_b = mutex_b.slice::<u8>();
let matrix_a_to_b = b.matrix.inverted().multiply(&a.matrix);
let resolution_u = b.resolution.x;
let resolution_v = b.resolution.y;
for z_index in min_z_index .. max_z_index + 1 {
for y_index in min_y_index .. max_y_index + 1 {
for x_index in min_x_index .. max_x_index + 1 {
let index = x_index + y_index * a.resolution.x + z_index * a.resolution.x * a.resolution.y;
let value_a = values_a[index];
if value_a == 0 {
continue;
}
let x = a.origin.x + (x_index as f64) * a.cell_size;
let y = a.origin.y + (y_index as f64) * a.cell_size;
let z = a.origin.z + (z_index as f64) * a.cell_size;
let p = matrix_a_to_b.multiply_point(&Point3::new(x, y, z));
let squared_u = p.x * p.x + p.y * p.y;
if b.max_u * b.max_u < squared_u {
continue;
}
let u = squared_u.sqrt() - b.origin.x;
let v = p.z - b.origin.y;
let u_index = (u / b.cell_size) as usize;
let v_index = (v / b.cell_size) as usize;
if v < 0.0 || resolution_u <= u_index || resolution_v <= v_index {
continue;
}
let v_index0 = (v_index + 0) * resolution_u;
let v_index1 = (v_index + 1) * resolution_u;
let c00 = values_b[u_index + v_index0] as f64;
let c01 = values_b[u_index + v_index1] as f64;
let c10: f64;
let c11: f64;
if u_index + 1 < resolution_u {
c10 = values_b[u_index + 1 + v_index0] as f64;
c11 = values_b[u_index + 1 + v_index1] as f64;
} else {
c10 = 0.0;
c11 = 0.0;
}
let u_ratio = u / b.cell_size - u_index as f64;
let v_ratio = v / b.cell_size - v_index as f64;
let c0 = c00 + (c10 - c00) * u_ratio;
let c1 = c01 + (c11 - c01) * u_ratio;
let c = c0 + (c1 - c0) * v_ratio;
let value_b = (255.0 - c) as u8;
if value_b < value_a {
values_a[index] = value_b;
}
}
}
}
}