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

Never create more than one Tokio runtime. Remove tokio_util::block_on #2960

Closed
ry opened this issue Sep 16, 2019 · 6 comments · Fixed by #3388
Closed

Never create more than one Tokio runtime. Remove tokio_util::block_on #2960

ry opened this issue Sep 16, 2019 · 6 comments · Fixed by #3388

Comments

@ry
Copy link
Member

ry commented Sep 16, 2019

There is a hack we've introduced called tokio_util::block_on, which can execute a future in a new Tokio runtime. Not only is this blocking, but it creates many extra threads. We use it in the module loader to avoid certain deadlocks - fundamentally the things we are blocking on are simple network connections which could be done on a single thread.

Recently we parallelized some module loading, which caused a visible explosion in the number of threads.

This tokio_util::block_on is a problem of our own creation (indeed, it's my design mistake). There is no fundamental reason for it to exist. We should be able to load and execute complex code on a single thread. It may be some of our fundamental abstractions are causing this even, and need to be reconsidered. Namely the idea that an Isolate is a Future and that all of its ops are polled manually from that future.

This is a v1.0 blocker.

This was referenced Sep 16, 2019
@hayd
Copy link
Contributor

hayd commented Sep 16, 2019

Is the issue we should be using .await instead block_on (and rewrite higher up the stack in terms of futures), or is there something fundamental I'm missing ?

@ry
Copy link
Member Author

ry commented Sep 16, 2019

@hayd No - it's more complicated than that... I'll try to write up something later. But it has to do with how Isolate::poll is designed.

@bartlomieju
Copy link
Member

bartlomieju commented Sep 16, 2019

This maybe a naive question, but why didn't we use tokio_threadpool::blocking in the first place? It seems like exactly the thing that is needed for this kind of job - won't spawn new thread and can be used for synchronous code (it's even used in JSON dispatch now for sync calls).

EDIT: Nevermind... tokio_threadpool::blocking doesn't convert async code to sync. futures::Future::wait is the closest to what we need but it doesn't work in this case.

@ry
Copy link
Member Author

ry commented Oct 3, 2019

Update: in #3043 the major bottleneck to removing tokio_util::block_on was eliminated by reorganizing how the TS compiler works.

There are still many usages:

> grep block_on cli -R
cli/http_util.rs:    tokio_util::block_on(fetch_string_once(url))
cli/worker.rs:    tokio_util::block_on(self.execute_mod_async(module_specifier, is_prefetch))
cli/file_fetcher.rs:    tokio_util::block_on(self.fetch_source_file_async(specifier))
cli/file_fetcher.rs:      tokio_util::block_on(self.fetch_remote_source_async(
cli/file_fetcher.rs:      tokio_util::block_on(self.get_source_file_async(
cli/file_fetcher.rs:      let result = tokio_util::block_on(fetcher.fetch_remote_source_async(
cli/tokio_util.rs:  rt.block_on_all(future).unwrap();
cli/tokio_util.rs:pub fn block_on<F, R>(future: F) -> Result<R, ErrBox>
cli/tokio_util.rs:      Ok(mut rt) => rt.block_on(future),
cli/ops/dispatch_minimal.rs:      // tokio_util::block_on.
cli/compilers/ts.rs:      tokio_util::block_on(self.compile_async(state, source_file))
cli/compilers/ts.rs:    assert!(tokio_util::block_on(out).is_ok());

but I suspect these should be easily removable now...

@bartlomieju
Copy link
Member

@ry most of those usages are for test. I'll look into it

@bartlomieju
Copy link
Member

Update: with #3059 and #3080 landed, we're left with a single call to tokio_util::block_on in SourceFileFetcher::fetch_source_file. Also we don't create a new threadpool runtime for this purpose but rather use tokio::runtime::current_thread effectively meaning that running this blocking section requires a new thread.

bartlomieju added a commit to bartlomieju/deno that referenced this issue Oct 10, 2019
@ry ry closed this as completed in #3388 Nov 22, 2019
ry pushed a commit that referenced this issue Nov 22, 2019
This PR removes tokio_util::block_on - refactored compiler and file 
fetcher slightly so that we can safely block there - that's because 
only blocking path consist of only synchronous operations.

Additionally I removed excessive use of tokio_util::panic_on_error 
and tokio_util::run_in_task and moved both functions to cli/worker.rs, 
to tests module.

Closes #2960
bartlomieju added a commit to bartlomieju/deno that referenced this issue Dec 28, 2019
This PR removes tokio_util::block_on - refactored compiler and file 
fetcher slightly so that we can safely block there - that's because 
only blocking path consist of only synchronous operations.

Additionally I removed excessive use of tokio_util::panic_on_error 
and tokio_util::run_in_task and moved both functions to cli/worker.rs, 
to tests module.

Closes denoland#2960
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.

3 participants