WebAssembly js性能对比

一般几何里面用相交比较多 简单写个demo测试下WebAssembly 和js的速度,

主要计算的就是射线交线段,主要是测试计算速度 算法不一定对,

rust代码如下,刚开始写rust 可能有点不规范

ray表示射线

另外两个用float32array作为 线的顶点和索引 

这里说明下,如果不转换成rust的vec 直接使用float32array.get_index()调用的话,由于要频繁调用js代码会更慢

pub fn insert(ray:js_sys::Float32Array,in_points:js_sys::Float32Array, in_indexes:js_sys::Int32Array)->js_sys::Float32Array
{
    let points = in_points.to_vec();
    let indexes = in_indexes.to_vec();
    let mut results:Vec = vec![];
    let o_x = ray.get_index(0);
    let o_y = ray.get_index(1);
    let o_z = ray.get_index(2);
    let d_x = ray.get_index(3);
    let d_y = ray.get_index(4);
    let d_z = ray.get_index(5);


    let size = indexes.len();
    let mut index = 0;
    while index < size {
        let s_i =indexes[index] as usize;
        let e_i =indexes[index + 1] as usize;
        index = index + 2 as usize;

        let s_x = points[s_i * 3];
        let s_y = points[s_i * 3 + 1];
        let s_z = points[s_i * 3 + 2];

        let e_x = points[e_i * 3];
        let e_y = points[e_i * 3 + 1];
        let e_z = points[e_i * 3 + 2];

        let c_length = f32::sqrt((e_x - s_x).powi(2) + (e_y - s_y).powi(2)+(e_z-s_z).powi(2));
        let c_d_x = (e_x - s_x) / c_length;
        let c_d_y = (e_y - s_y) / c_length;
        let c_d_z = (e_z - s_z) / c_length;


        let sbv1 = cross(d_x, d_y, d_z, c_d_x, c_d_y, c_d_z);
        let sbv2 = cross(c_d_x, c_d_y, c_d_z, d_x, d_y, d_z);
        let sb1 =  array_dots(sbv2,sbv1);
        let sb2 =  array_dots(sbv1,sbv2);
        if sb1 < 0.00000001 || sb2 < 0.0000001
        {
            continue;
        }
        let mut temp_1 = sub(o_x, o_y, o_z, s_x, s_y, s_z);
        let mut temp_2 = cross(temp_1[0], temp_1[1],temp_1[2],c_d_x,c_d_y,c_d_z);
        let mut temp_3 = cross(temp_2[0], temp_2[1], temp_2[2], d_x, d_y, d_z);
        let t1 = array_dots(temp_2, temp_3) /sb1;
        
        temp_1 = sub(o_x, o_y, o_z, s_x, s_y, s_z);
        temp_2 = cross(temp_1[0], temp_1[1],temp_1[2],c_d_x,c_d_y,c_d_z);
        temp_3 = cross(temp_2[0], temp_2[1], temp_2[2], d_x, d_y, d_z);
        let t2 = array_dots(temp_2, temp_3) /sb1;

        let array = [o_x + t1 * d_x, o_y + t1 * d_y, o_z + t1 * d_z, s_x + t2 * c_d_x, s_y + t2 * c_d_y, s_z + t2 * c_d_z];
        if (array[0] - array[3]).powi(2) + (array[1] - array[4]).powi(2) + (array[2] - array[5]).powi(2) < 1.0
        {
            results.push(array[0]);
            results.push(array[1]);
            results.push(array[2]);
            results.push(array[3]);
            results.push(array[4]);
            results.push(array[5]);
        }
        // let array = js_sys::Float32Array::default();
        // array.copy_from(&[o_x + t1 * d_x, o_y + t1 * d_y, o_z + t1 * d_z, s_x + t2 * c_d_x, s_y + t2 * c_d_y, s_z + t2 * c_d_z]);
        // return array;
    }
    let array = js_sys::Float32Array::new_with_length(results.len() as u32);
    array.copy_from(&results);
    return  array;
}

测试float32array转vec的时间,为了避免未使用变量优化 计算下结果

#[wasm_bindgen]
pub fn only_copy(ray:js_sys::Float32Array,in_points:js_sys::Float32Array, in_indexes:js_sys::Int32Array)->f32
{
    let points = in_points.to_vec();
    let indexes = in_indexes.to_vec();
    let o_x = ray.get_index(0);
    let o_y = ray.get_index(1);
    let o_z = ray.get_index(2);
    let d_x = ray.get_index(3);
    let d_y = ray.get_index(4);
    let d_z = ray.get_index(5);
    return points[0] + indexes[1] as f32 + o_x + d_x + d_y + d_z + o_y + o_z;
}

js的代码

let js = (ray:Float32Array,points:Float32Array, indexes:Int32Array)=>{
            let origin =new THREE.Vector3(ray[0], ray[1], ray[2]);
            let direction =new THREE.Vector3(ray[3], ray[4], ray[3]);
            let start = new THREE.Vector3();
            let end = new THREE.Vector3();
            let sbv1 = new THREE.Vector3();
            let lDirection = new THREE.Vector3();
            let sbv2 = new THREE.Vector3();
            let size = indexes.length;
            let index = 0;
            while (index < size) {
                let s_i =indexes[index] ;
                let e_i =indexes[index + 1] ;
                index = index + 2 ;
                start.set(points[s_i * 3],points[s_i * 3 +1],points[s_i * 3 + 2]);
                end.set(points[e_i * 3],points[e_i * 3 +1],points[e_i * 3 + 2]);
        
        
                lDirection = lDirection.copy(end).sub(start).normalize();
        
        
                sbv1 =sbv1.copy(lDirection).cross(direction);
                sbv2 =sbv2.copy(direction).cross(lDirection);
                let sb1 = sbv1.dot(sbv2);
                let sb2 =  sbv2.dot(sbv1);
                if (sb1 < 0.00000001 || sb2 < 0.0000001)
                {
                    continue;
                }
                let  temp_1 = origin.clone().sub(start).cross(lDirection);
                let  temp_2 = start.clone().sub(origin).cross(direction);
        
                let t1 = temp_1.dot(temp_2) /sb1;
                
                temp_1 = origin.clone().sub(start).cross(lDirection);
                temp_2 = start.clone().sub(origin).cross(direction);
        
                let t2= temp_1.dot(temp_2) /sb1;
                // let array = js_sys::Float32Array::default();
                // array.copy_from(&[o_x + t1 * d_x, o_y + t1 * d_y, o_z + t1 * d_z, s_x + t2 * c_d_x, s_y + t2 * c_d_y, s_z + t2 * c_d_z]);
                // return array;
            }
        
            return  new Float32Array();
        }

测试数据 直接用随机数计算出线段

        const size = 10000;
        let index = [];
        for (let i = 0; i < size; i++)
        {
            array.push(Math.random() * 1000, Math.random() * 1000, Math.random() * 1000);
            index.push(i);
            if(i != 0 || i!= size-1)
            {
                index.push(i);
            }
        }
        let p1 = new Float32Array(array);
        let indies = new Int32Array(index);

10000结果如下:

rust: 1.133056640625 ms
only_copy: 0.083984375 ms
js: 3.298095703125 ms

100000结果

rust: 3.6298828125 ms
only_copy: 0.214111328125 ms
js: 5.56884765625 ms

1000000结果

rust: 28.794921875 ms
only_copy: 1.44482421875 ms
js: 23.551025390625 ms

数据量多的时候 rust编译出来的WebAssembly 开始慢下来了,推测可能是内存有点施展不开来

10000000时候慢的更多了

rust: 313.79296875 ms
only_copy: 19.958251953125 ms
js: 215.423828125 ms

个人感觉 对于密集型运算使用WebAssembly 会好很多,如果要是js和WebAssembly直接频繁调用还是直接js更块 因为js调用WebAssembly或者WebAssembly叫用js也耗用一定资源

你可能感兴趣的:(wasm,javascript,rust)