campaigns: use a persistent RPC container in volume mode
Created by: LawnGnome
One performance issue I called out in #412 in volume mount mode was that large diffs could be slower. My hypothesis was that this was caused by the diffs being transmitted over the container's stdout, which means it has to pass through Docker, potentially get logged, and so on.
This PR adds an experimental new workspace mode called marionette
(although, if we decide to go ahead with this, I would replace volume
with it). This uses the same basic technique as volume mode, where the workspace is on a Docker volume, but instead of running ad hoc containers to run git
and unzip
commands, a single container runs during the entire set of steps that exposes a service (called marionette
) that provides a gRPC server that closely mimics the Workspace
interface.
As a result, the diff (and intermediate changes metadata) comes back over an established gRPC connection, instead of via stdout.
I used the same stress test I used in #412 for this: a campaign that essentially does this:
- Clones sourcegraph/sourcegraph.
- Runs
gunzip -ck /usr/share/cracklib/cracklib-words.gz >> README.md
.
This results in a ~15 MB diff. Extreme, but not unreasonable if a user is doing something with binaries (say, running ImageMagick or pngcrush
transforms on image assets).
On macOS:
- Bind mode: ~13 seconds
- Volume mode: ~28 seconds
- Marionette mode: ~11 seconds
Therefore, this results in a workspace mode that outperforms both bind and volume mode on macOS. (And probably also on Windows.)
The big question for me in this PR is: is this a good enough improvement to be worth the extra complexity? The workspace implementation isn't really any more complicated, but the control flow gets a bit more complex because we have to manage the lifecycle of the marionette container, plus we now have another cmd
to manage, plus we have to pull in the protobuf and gRPC libraries.
So, @sourcegraph/campaigns, thoughts?