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

Decrease time spent waiting for compilation requests #457

Open
ffissore opened this issue Jan 23, 2019 · 11 comments
Open

Decrease time spent waiting for compilation requests #457

ffissore opened this issue Jan 23, 2019 · 11 comments
Labels
enhancement Something new the playground could do help wanted Not immediately going to be prioritized — ask for mentoring instructions!

Comments

@ffissore
Copy link

Have you considered asking the community support in terms of mirroring the playground?
At the moment https://play.rust-lang.org/ takes about ~1.5 secs to compile and run a snippet. Could sharing the load across different VMs make it snappier?

@shepmaster shepmaster added help wanted Not immediately going to be prioritized — ask for mentoring instructions! question maintenance Keeping the wheels turning labels Jan 23, 2019
@shepmaster
Copy link
Member

As of right now, the load average is 0.99, 0.86, 0.86, so the machine is pretty much right at where it should be. I don't believe I have any longer-term stats handy.

community support

The EC2 instance provided by Mozilla is 2x2.30GHz with 8GB of RAM, so it's not a tiny machine.

Could sharing the load across different VMs make it snappier?

It's possible, but would require deeper digging to determine what the problem really is.

For example, the alternate deployment (https://play.integer32.com/) has a load average of 0.05, 0.09, 0.04, but is a 1x2.40GHz with 1GB of RAM, and compiling takes the same amount of time (1.14s vs 1.19s, measured via Chrome's network inspector).

This may mean that the performance bottleneck is mostly centered around disk access.

@ffissore
Copy link
Author

I've just run the playground on my machine (kind of beefy i7 with 32 gb of ram) and the hello world snippet takes ~1.3 secs, so I've reproduced the issue locally. I'll try to investigate

@ffissore
Copy link
Author

It looks like the root cause is docker. Starting a temporary container takes ~1sec, regardless of the container and the command you run (try time docker run --rm ubuntu:18.04 whoami). Then there's the time taken by cargo.

Only idea that comes to my mind is this.
We start only one container at playground start up time, and have a server running inside the container. Such server exposes an /execute API that:

  1. makes a copy of the current playground folder into a temporary folder
  2. stores the snippet into src/main.rs
  3. calls modify-cargo-toml on the temporary cargo folder
  4. runs cargo build/run/whatever
  5. deletes the temporary folder

Drawbacks are:

  1. an "evil" snippet could list the currently running snippets
  2. in order to call the server running inside docker, we need to give network capabilities to it and therefore to the snippets

I'm not linux security expert but maybe the cap params currently provided to docker have to be relaxed as well in order to run such server, and this could then lead to more issues

@ffissore
Copy link
Author

One possible solution to drawback 2 is to run cargo through firejail (which I've just discovered, so I'm no expert), which has a --net=none param

@ffissore
Copy link
Author

I've tried and failed to implement the solution above.
For the record, instead of making another server listening from inside the docker container, I've interacted with it through docker exec and cp commands
It worked until I hit a wall:

  • once the contents of /playground are copied into a temp folder, cargo thinks they have to be recompiled, thus wasting time (and btw some fail to compile too)
  • /playground is 1.1G, so making many copies of it is not a good idea

Should you want to take a look at the diff, it's here ffissore@d181e9a

@shepmaster shepmaster added enhancement Something new the playground could do and removed maintenance Keeping the wheels turning question labels Jan 28, 2019
@shepmaster shepmaster changed the title Have you considered mirroring? Decrease time spent waiting for compilation requests Jan 28, 2019
@shepmaster
Copy link
Member

Starting a temporary container takes ~1sec, regardless of the container and the command you run

FWIW, I think this is predicated on disk speed:

$ time docker run --rm ubuntu:18.04 whoami
root

real	0m0.319s
user	0m0.048s
sys	0m0.025s

@shepmaster
Copy link
Member

I'm going to reopen this just to keep track of ways of improving the speed; it's certainly something we'd like!

@shepmaster shepmaster reopened this Jan 28, 2019
@shepmaster
Copy link
Member

  1. makes a copy of the current playground folder into a temporary folder

Instead of this, I wonder if the Cargo.toml could be copied (foo-Cargo.toml) and then main file name in the new Cargo.toml changed (foo-main.rs).

@shepmaster
Copy link
Member

We start only one container at playground start up time

An alternative would be a pool of started servers that are started and idling, ready to go once they receive data.

@ffissore
Copy link
Author

The pool approach makes sense. I'll give it a try

@ffissore
Copy link
Author

After some experimentation, a couple of questions:

  1. are we fine in preventing users from writing on the filesystem?
  2. if not, is there a way to make sys::fs map to an in-memory fs implementation?

The problem with using shared docker containers is that whatever file a snippet creates stays in the container and it's possibly accessible by other users. With the current one-snippet <-> one-container approach, saving files is not a problem.
One possible convoluted solution is to run cargo build in a container and then move/copy the executable into another container which is started with docker --read-only: this way at build time cargo is happily using precompiled crates, and at run time we are sure snippets won't leave any files around because the fs won't be writable.

If instead we do want to allow filesystem write access and we do care about not having user generated files around, then the shared container approach is a no-go.
I've tried investigating various approaches (apparmor, firejail and chroot) but they all require sysadmin knowledge which I don't have.

Unless we can replace the underlying fs implementation of rust with an in-memory one. Judging from https://github.com/rust-lang/rust/blob/master/src/libstd/sys/mod.rs#L25 the answer is no, but I'm new to rust

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Something new the playground could do help wanted Not immediately going to be prioritized — ask for mentoring instructions!
Projects
None yet
Development

No branches or pull requests

2 participants