Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small optimizations: Benchmark moving fetches, model parsing to web workers #489

Open
gkjohnson opened this issue Feb 22, 2024 · 2 comments
Milestone

Comments

@gkjohnson
Copy link
Contributor

It seems that sometimes fetches can take a few milliseconds to run and likewise parsing and generating data blobs for image bitmaps can also be a bit slow - between parsing and loading the data it can take ~4ms sometimes. Image bitmaps and geometry array buffers are fast to transfer over webworkers. These could help address the performance hiccups during load of complex models

@gkjohnson gkjohnson added this to the v0.3.26 milestone Feb 22, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.26, v0.3.27, v0.3.28 Feb 29, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.28, v0.3.29, v0.3.30 Mar 11, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.31, v0.3.32 Mar 25, 2024
@gkjohnson gkjohnson modified the milestones: v0.3.32, v0.3.33 Apr 24, 2024
@Nmzik
Copy link
Contributor

Nmzik commented May 3, 2024

@gkjohnson I'd like to contribute to the issue you mentioned regarding fetch. We have a lot of b3dm tiles in the scene (each tile is around 3MB + ktx texture 4096x4096). While profiling (in Chrome), I noticed that a lot of time is spent on the arrayBuffer() call. By using a worker and performing fetch and arrayBuffer() calls and transfering the result back (Transferable) to the main thread, I no longer experience frame rate hiccups during scene traversal (almost constant 60fps). The thing is, I don't really have a proper explanation for this. Perhaps memory allocation for each tile (around 3MB) is causing this issue (due to parsing the response, allocating memory, and copying bytes to the buffer). I simply don't know. I thought, as it is a promise (and maybe a function, implemented in V8 internally), it should be executed on a separate V8 internal thread (aside from the JS main application thread).

downloadQueue.add( tile, downloadTile => {

				if ( downloadTile.__loadIndex !== loadIndex ) {

					return Promise.resolve();

				}

				const uri = this.preprocessURL ? this.preprocessURL( downloadTile.content.uri ) : downloadTile.content.uri;

				return fetch( uri, Object.assign( { signal }, this.fetchOptions ) );

			} )
				.then( res => {

					if ( tile.__loadIndex !== loadIndex ) {

						return;

					}
                                        // :))
					return res.arrayBuffer();

				} )

As for the GLTFLoader in the worker thread, I didn't notice any significant difference.

@gkjohnson
Copy link
Contributor Author

@Nmzik Thanks for taking a look at this! Would you be able to make a small PR with the change to perform fetches in a WebWorker so I can try it out, as well? Then we can figure out what an API change might look like to enable it. Unfortunately we can't have this set by default since bundlers still choke on WebWorkers and they can't be started with cross origin scripts (ie via CDNs).

I simply don't know. I thought, as it is a promise (and maybe a function, implemented in V8 internally), it should be executed on a separate V8 internal thread (aside from the JS main application thread).

Yeah I figured it would be fairly asynchronous, as well, but when I'd tested it I noticed that at least when starting a fetch it was causing some stalls which is why I made the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants