diff --git a/benchmarks/benches/data.rs b/benchmarks/benches/data.rs index 4b9829dbe..090c8a556 100644 --- a/benchmarks/benches/data.rs +++ b/benchmarks/benches/data.rs @@ -21,7 +21,7 @@ const MUNICH_COORDS: TileCoords = TileCoords { pub struct DummyContext; impl Context for DummyContext { - fn send(&self, _message: T) -> Result<(), SendError> { + fn send_back(&self, _message: T) -> Result<(), SendError> { Ok(()) } } diff --git a/maplibre/src/headless/map.rs b/maplibre/src/headless/map.rs index 3a3eadd83..b40e207dc 100644 --- a/maplibre/src/headless/map.rs +++ b/maplibre/src/headless/map.rs @@ -162,7 +162,7 @@ pub struct HeadlessContext { } impl Context for HeadlessContext { - fn send(&self, message: T) -> Result<(), SendError> { + fn send_back(&self, message: T) -> Result<(), SendError> { self.messages.deref().borrow_mut().push(message.into()); Ok(()) } diff --git a/maplibre/src/io/apc.rs b/maplibre/src/io/apc.rs index 165591ef1..d6792e632 100644 --- a/maplibre/src/io/apc.rs +++ b/maplibre/src/io/apc.rs @@ -88,7 +88,7 @@ pub enum SendError { /// Allows sending messages from workers to back to the caller. pub trait Context: 'static { /// Send a message back to the caller. - fn send(&self, message: T) -> Result<(), SendError>; + fn send_back(&self, message: T) -> Result<(), SendError>; } #[derive(Error, Debug)] @@ -190,7 +190,7 @@ pub struct SchedulerContext { } impl Context for SchedulerContext { - fn send(&self, message: T) -> Result<(), SendError> { + fn send_back(&self, message: T) -> Result<(), SendError> { self.sender .send(message.into()) .map_err(|_e| SendError::Transmission) @@ -282,7 +282,7 @@ pub mod tests { pub struct DummyContext; impl Context for DummyContext { - fn send(&self, _message: T) -> Result<(), SendError> { + fn send_back(&self, _message: T) -> Result<(), SendError> { Ok(()) } } diff --git a/maplibre/src/raster/process_raster.rs b/maplibre/src/raster/process_raster.rs index 77547f5bf..44ff038f4 100644 --- a/maplibre/src/raster/process_raster.rs +++ b/maplibre/src/raster/process_raster.rs @@ -55,7 +55,7 @@ impl ProcessRasterContext { image_data: RgbaImage, ) -> Result<(), ProcessRasterError> { self.context - .send(T::LayerRaster::build_from(*coords, layer_name, image_data)) + .send_back(T::LayerRaster::build_from(*coords, layer_name, image_data)) .map_err(|e| ProcessRasterError::Processing(Box::new(e))) } } diff --git a/maplibre/src/raster/request_system.rs b/maplibre/src/raster/request_system.rs index cf2a24a40..410d73b1f 100644 --- a/maplibre/src/raster/request_system.rs +++ b/maplibre/src/raster/request_system.rs @@ -142,7 +142,7 @@ pub fn fetch_raster_apc::LayerRasterMissing::build_from( + .send_back(::LayerRasterMissing::build_from( coords, )) .map_err(ProcedureError::Send)?; diff --git a/maplibre/src/vector/process_vector.rs b/maplibre/src/vector/process_vector.rs index 991efb8d9..79ff7a3bc 100644 --- a/maplibre/src/vector/process_vector.rs +++ b/maplibre/src/vector/process_vector.rs @@ -125,7 +125,7 @@ impl ProcessVectorContext { fn tile_finished(&mut self, coords: &WorldTileCoords) -> Result<(), ProcessVectorError> { self.context - .send(T::TileTessellated::build_from(*coords)) + .send_back(T::TileTessellated::build_from(*coords)) .map_err(|e| ProcessVectorError::SendError(e)) } @@ -135,7 +135,7 @@ impl ProcessVectorContext { layer_name: &str, ) -> Result<(), ProcessVectorError> { self.context - .send(T::LayerMissing::build_from(*coords, layer_name.to_owned())) + .send_back(T::LayerMissing::build_from(*coords, layer_name.to_owned())) .map_err(|e| ProcessVectorError::SendError(e)) } @@ -147,7 +147,7 @@ impl ProcessVectorContext { layer_data: tile::Layer, ) -> Result<(), ProcessVectorError> { self.context - .send(T::LayerTessellated::build_from( + .send_back(T::LayerTessellated::build_from( *coords, buffer, feature_indices, @@ -162,7 +162,7 @@ impl ProcessVectorContext { geometries: Vec>, ) -> Result<(), ProcessVectorError> { self.context - .send(T::LayerIndexed::build_from( + .send_back(T::LayerIndexed::build_from( *coords, TileIndex::Linear { list: geometries }, )) diff --git a/maplibre/src/vector/request_system.rs b/maplibre/src/vector/request_system.rs index c2207a442..1c410fead 100644 --- a/maplibre/src/vector/request_system.rs +++ b/maplibre/src/vector/request_system.rs @@ -151,7 +151,7 @@ pub fn fetch_vector_apc::LayerMissing::build_from( + .send_back(::LayerMissing::build_from( coords, to_load.to_string(), )) diff --git a/web/lib/build.mjs b/web/lib/build.mjs index d47a560d0..7c2b66b54 100644 --- a/web/lib/build.mjs +++ b/web/lib/build.mjs @@ -59,6 +59,7 @@ if (multithreaded) { let baseConfig = { platform: "browser", bundle: true, + minify: release, assetNames: "assets/[name]", define: { WEBGL: `${webgl}`, diff --git a/web/lib/src/index.ts b/web/lib/src/index.ts index 64e40f577..b49a82cb6 100644 --- a/web/lib/src/index.ts +++ b/web/lib/src/index.ts @@ -25,7 +25,7 @@ export const startMapLibre = async (wasmPath: string | undefined, workerPath: st preventDefaultTouchActions(); if (MULTITHREADED) { - const MEMORY = 209715200; // 200MB + const MEMORY = 900 * 1024 * 1024; // 900 MB const PAGES = 64 * 1024; const memory = new WebAssembly.Memory({initial: 1024, maximum: MEMORY / PAGES, shared: true}) diff --git a/web/lib/src/multithreaded/multithreaded-pool.worker.ts b/web/lib/src/multithreaded/multithreaded-pool.worker.ts index 75ff69a08..695f76bd1 100644 --- a/web/lib/src/multithreaded/multithreaded-pool.worker.ts +++ b/web/lib/src/multithreaded/multithreaded-pool.worker.ts @@ -1,7 +1,7 @@ import * as maplibre from "../wasm/maplibre" type MessageData = {type: 'wasm_init', module: WebAssembly.Module, memory: WebAssembly.Memory} - | {type: 'call', work_ptr: number} + | {type: 'pool_call', work_ptr: number} let initialised: Promise = null @@ -17,7 +17,7 @@ onmessage = async (message: MessageEvent) => { const data = message.data; const module = data.module; const memory = data.memory; - const initialised = maplibre.default(module, memory).catch(err => { + initialised = maplibre.default(module, memory).catch(err => { // Propagate to main `onerror`: setTimeout(() => { throw err; @@ -25,10 +25,8 @@ onmessage = async (message: MessageEvent) => { // Rethrow to keep promise rejected and prevent execution of further commands: throw err; }); - } else if (type === 'call') { + } else if (type === 'pool_call') { const work_ptr = message.data.work_ptr; // because memory is shared, this pointer is valid in the memory of the main thread and this worker thread - // This will queue further commands up until the module is fully initialised: - await initialised; const process_data: (msg: any) => Promise = maplibre["multithreaded_process_data"] diff --git a/web/src/platform/multithreaded/pool.rs b/web/src/platform/multithreaded/pool.rs index cff02abad..0b15ae87b 100644 --- a/web/src/platform/multithreaded/pool.rs +++ b/web/src/platform/multithreaded/pool.rs @@ -4,7 +4,6 @@ use std::{cell::RefCell, rc::Rc}; -use js_sys::Promise; use rand::prelude::*; use wasm_bindgen::prelude::*; use web_sys::Worker; @@ -17,8 +16,10 @@ extern "C" { fn new_worker() -> JsValue; } +pub type PinnedFuture = std::pin::Pin + 'static)>>; + type NewWorker = Box Result>; -type Execute = Box Promise) + Send>; +type Execute = Box PinnedFuture) + Send>; pub struct WorkerPool { new_worker: NewWorker, @@ -44,7 +45,7 @@ pub struct Work { } impl Work { - pub fn execute(self) -> Promise { + pub fn execute(self) -> PinnedFuture { (self.func)() } } @@ -139,13 +140,16 @@ impl WorkerPool { /// /// Returns any error that may happen while a JS web worker is created and a /// message is sent to it. - pub fn execute(&self, f: impl (FnOnce() -> Promise) + Send + 'static) -> Result<(), WebError> { + pub fn execute( + &self, + f: impl (FnOnce() -> PinnedFuture) + Send + 'static, + ) -> Result<(), WebError> { let worker = self.worker()?; let work = Work { func: Box::new(f) }; let work_ptr = Box::into_raw(Box::new(work)); match worker.post_message( &js_sys::Object::from_entries(&js_sys::Array::of2( - &js_sys::Array::of2(&JsValue::from("type"), &js_sys::JsString::from("call")), + &js_sys::Array::of2(&JsValue::from("type"), &js_sys::JsString::from("pool_call")), &js_sys::Array::of2(&JsValue::from("work_ptr"), &JsValue::from(work_ptr as u32)), )) .expect("can not fail"), diff --git a/web/src/platform/multithreaded/pool_scheduler.rs b/web/src/platform/multithreaded/pool_scheduler.rs index 53488cbc9..3049a9968 100644 --- a/web/src/platform/multithreaded/pool_scheduler.rs +++ b/web/src/platform/multithreaded/pool_scheduler.rs @@ -36,12 +36,7 @@ impl Scheduler for WebWorkerPoolScheduler { T: Future + 'static, { self.pool - .execute(move || { - wasm_bindgen_futures::future_to_promise(async move { - future_factory().await; - Ok(JsValue::undefined()) - }) - }) + .execute(move || Box::pin(future_factory())) .map_err(|e| ScheduleError::Scheduling(Box::new(e))) } } diff --git a/web/src/platform/multithreaded/wasm_entries.rs b/web/src/platform/multithreaded/wasm_entries.rs index bf5fd59be..118ae3d07 100644 --- a/web/src/platform/multithreaded/wasm_entries.rs +++ b/web/src/platform/multithreaded/wasm_entries.rs @@ -1,15 +1,11 @@ -use maplibre::io::apc::CallError; use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::JsFuture; use crate::{platform::multithreaded::pool::Work, JSError}; /// Entry point invoked by the worker. #[wasm_bindgen] pub async fn multithreaded_process_data(work_ptr: *mut Work) -> Result<(), JSError> { - let work = unsafe { Box::from_raw(work_ptr) }; - JsFuture::from(work.execute()) - .await - .map_err(|_e| CallError::Schedule)?; + let work: Box = unsafe { Box::from_raw(work_ptr) }; + work.execute().await; Ok(()) } diff --git a/web/src/platform/singlethreaded/apc.rs b/web/src/platform/singlethreaded/apc.rs index efa21f797..01e0b734e 100644 --- a/web/src/platform/singlethreaded/apc.rs +++ b/web/src/platform/singlethreaded/apc.rs @@ -84,7 +84,7 @@ pub struct PassingContext { } impl Context for PassingContext { - fn send(&self, message: T) -> Result<(), SendError> { + fn send_back(&self, message: T) -> Result<(), SendError> { let message = message.into(); let tag = if WebMessageTag::LayerRaster.dyn_clone().as_ref() == message.tag() { &WebMessageTag::LayerRaster