Search code examples
rustwebassembly

Rust function response is very slow when working with Webassembly with 200k data in vector


When I call Rust function from JavaScript with 200k data list in an array it freezes the application. As per my debug the issue is with IF CONDITION (if time_value.contains(&value) == false). When I remove this condition the response is very fast. But I need this condition.

#[wasm_bindgen]
pub fn channel_duplicate_timestamp(value: &JsValue) -> JsValue {
    panic::set_hook(Box::new(console_error_panic_hook::hook));
    let request: ChanDup = value.into_serde().unwrap();
    let mut time_value = Vec::new();
    let mut time_index: Vec<i32> = Vec::new();
    for (index, value) in request.time_list.into_iter().enumerate() {
        if time_value.contains(&value) == false {
            time_value.push(value);
            time_index.push(index as i32);
        }
    }
    let response = ChanDupRes {
        time_list: time_value,
        t_index:time_index
    };

    JsValue::from_serde(&response).unwrap()
}

}

I tried to get it done by using another function but since I am new to Rust I failed. I want to get the index of duplicate items from the list


Solution

  • Instead of having time_value and time_index be parallel vectors, you should use a single HashMap<&JsValue, i32> for the main loop and only convert to vectors when building the result. Something like this (untested):

    #[wasm_bindgen]
    pub fn channel_duplicate_timestamp(value: &JsValue) -> JsValue {
        panic::set_hook(Box::new(console_error_panic_hook::hook));
        let request: ChanDup = value.into_serde().unwrap();
        let mut time = HashMap::new();
        for (index, value) in request.time_list.into_iter().enumerate() {
            time.entry (&value).or_insert (index as u32);
        }
        let mut time_value = Vec::new();
        let mut time_index = Vec::new();
        for (v, i) in time {
            time_value.push (v);
            time.index.push (i);
        }
        let response = ChanDupRes {
            time_list: time_value,
            t_index:time_index
        };
    
        JsValue::from_serde(&response).unwrap()
    }
    

    Note that this will output the times in random order. You can sort on index if you need them in order.