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

WebAssembly: Add threading for download manager #2775

Closed
DenizUgur opened this issue Mar 11, 2024 · 0 comments · Fixed by #2803
Closed

WebAssembly: Add threading for download manager #2775

DenizUgur opened this issue Mar 11, 2024 · 0 comments · Fixed by #2803

Comments

@DenizUgur
Copy link
Contributor

For some reason, download manager is not working properly in a worker. Considering both the main thread and worker thread are running on their own thread, I can't find the reason why download manager experiences degraded performance while using gpac in a worker.

What happens is that when using worker and a remote source, gpac takes almost 60-70 times more to load the source. It seems that the reason lies with scheduling fetch promises while the same thread runs gpac. I've tried a very rough way to run fetch in seperate threads but I think I'm still blocked by scheduling. The correct way to achieve this seems to be through native (pthread) threading for download manager. Just how -dm-threads option supposed to work.

I would be happy to open a PR to bring -dm-threads to WebAssembly version but I need some guidance on what is needed and what might be a blocking issue. @jeanlf any idea on how to proceed with this one?

My attempt at multi-threaded fetch:

let workerScript = `self.onmessage = async function(event)
{
	let {url, options} = event.data;
	let res = await fetch(url, options);
	if (res.ok)
	{
		self.postMessage({
			ok: res.ok,
			url: res.url,
			status: res.status,
			headers: JSON.stringify([...res.headers]),
			redirected: res.redirected,
			body: res.body
		}, [res.body])
	} else self.postMessage({ok: res.ok, status: res.status})
}`;
let workerBlob = new Blob([workerScript], { type: 'application/javascript' });
fetcher._worker = new Worker(URL.createObjectURL(workerBlob));

fetcher._worker.onmessage = (event) =>
{
	if (event.data.ok)
	{
		fetcher._state = 1;
		fetcher._bytes = 0;
		fetcher._reader = event.data.body.getReader();

		let final_url = null;
		if (event.data.redirected) final_url = event.data.url;
		libgpac._fetcher_set_reply(fetcher.sess, event.data.status, final_url);

		let headers = JSON.parse(event.data.headers);
		headers.forEach(([value, key]) => {
			libgpac._fetcher_set_header(fetcher.sess, key, value);
		});
		libgpac._fetcher_set_header(fetcher.sess, 0, 0);
	}
	else
	{
		libgpac._fetcher_set_reply(fetcher.sess, event.data.status, null);
		do_log_err('fetcher for ' + url + ' failed ' + event.data.status);
		fetcher._state = 3;
	}
};

fetcher._state = 0;
fetcher._worker.postMessage({url, options}, [...(options.body ? [options.body] : [])]);
return ret;

Was placed here:

fetch(url, options).then( (response) => {

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

Successfully merging a pull request may close this issue.

1 participant