Remote Development With Codespaces
Are you tired of spending hours setting up your local machine so you can work with a new repository? Is Docker hogging CPU and memory, killing the promise of...
Are you tired of spending hours setting up your local machine so you can work with a new repository? Is Docker hogging CPU and memory, killing the promise of all-day battery life? Sick of gigabyte image downloads consuming your mobile data plan? Are you having issues running Docker or Terraform on Apple silicon? Over dealing with machine-specific problems that you can’t reproduce? If you answered yes to any of the above, maybe Github Codespaces might be the solution you’re looking for.
This post will cover why you might want to switch from local development to coding in the cloud with Github Codespaces. I also provide some comparison benchmarks, pricing analysis and a full-stack demo project to help you explore the concepts and give you a jumping-off point to build a Codespace environment.
Github Codespaces is a service that provides on-demand access to a development environment in the cloud.
Access to the remote environment is completely seamless using VSCode. VSCode makes a remote environment behave like a local environment by automatically handling things like port forwarding. Support for access via ssh is also included, so if tmux and neovim are your preferred tools, then Codespaces has you covered. Codespaces can enable development on a more limited device like an iPad Pro by offering a variant of VSCode that runs in the browser. Port forwarding, in this case, is supported through an Internet routable HTTPS URL which Codespaces will forward to the target process running inside your container.
With Codespaces, you define your environment configuration, operating system, software dependencies and recommended VSCode extensions using a Devcontainer. A Devcontainer is comprised of a configuration file, a Docker container and some scripts that run commands at different points in the container’s lifecycle. You can control how your Devcontainer is run through configuration, allowing you to run it in privileged mode if you need support for Docker-In-Docker.
A Codespace runs inside an isolated virtual machine; Codespaces are never co-located on the same virtual machine.
Running a development environment on Codespaces has a couple of distinct advantages.
First off, by defining your development environment as a Devcontainer, a new engineer can get up and running in minutes instead of hours or days. A Devcontainer is entirely self-contained, removing the need to install anything other than VSCode on a local machine.
Codespaces runs the Devcontainer on x86_64 Intel hardware, eliminating library compatibility issues with Apple’s ARM64 architecture. When you put it all together, Codespaces ensures all the engineers in your team are running a consistent software configuration on the same hardware. Consistency allows environment issues to be reproduced, avoiding wasted cycles spent investigating hardware or operating system-specific compatibility issues.
Shifting your environment to the cloud means you need less compute and memory on your local device, supporting development on more limited devices like a Chromebook, MacBook Air or an iPad via VSCode in the browser. Moving development off your local machine will extend battery life because software like Docker can significantly impact power consumption even while running idle containers.
A Codespace runs on a virtual machine hosted in an Azure datacentre, which gives you gigabit access to the Internet, speeding up downloads and supporting development on bandwidth capped mobile broadband plans.
Codespace servers are available in four regions - Southeast Asian (Singapore), Europe West (Netherlands), US West (Virginia), and US East (California). Depending on your location, network latency might be a consideration. If you’re based in Australia, Singapore is your closest region. Ping round trip time is between 90ms-100ms between regions. This level of latency can comfortably support VSCode, ssh sessions and editing with vim.
Codespaces are suspended after a period of inactivity. On suspension, all running processes are terminated. This can become annoying if you manually start a bunch of server processes. Automating environment startup by creating a postStartCommand script can resolve this. You can also make Codespaces more useable by increasing the “default idle timeout” to a period of up to four hours.
Secrets and Credentials
Developer secrets such as personal access tokens, preshared VPN keys, and credentials for private registries can be encrypted and managed by Codespaces. Secrets are injected into your Devcontainer as environment variables. A newly created secret will only be injected into your environment when you create a new Codespace or restart an existing one.
Developer Customisation
Additional developer customisations can be applied to a Codepsace using a dotfiles repository. A dotfiles repository can run a custom installation script or symlink configuration files and directories to your $HOME
directory. You can find an example of a dotfile repository with custom neovim and tmux settings here.
Codespaces claims to offer “better performance than your laptop”, so let’s put this claim to the test. I have two laptops to test against, a 2020 M1 MacBook Air and a 2020 Macbook Pro 13 with a quad-core i7.
Compute
In terms of hardware, the:
The benchmarks below were collated using Geekbench.
Intel Macbook Pro 13 - i7 Quad-Core | M1 MacBook Air 8-Core | 8-Core Codespace | 16-Core Codespace | |
---|---|---|---|---|
Single-Core Score | 1184 (68%) | 1725 | 914 (53%) | 898 (52.1%) |
Mult-Core Score | 4181 (57%) | 7311 | 4256 (58.2%) | 7673 (105%) |
Apple’s M1 single-core performance is around two times better than all Intel-based alternatives. Better single-core performance can significantly reduce build times in a development context because pipelines can’t always take advantage of multiple cores.
An 8-Core Codespace offers close to the same level of performance as the i7 Macbook Pro, scoring slightly lower on the single-core test and somewhat higher on the multicore test.
In conclusion, Codespaces is more than adequate for most development projects offering better or equivalent performance if your laptop is Intel-based. While M1 has compelling single-core performance, Apple’s ARM64 architecture still has library compatibility challenges making it more trouble than it’s worth for many projects.
Disk Throughput
Apple SSDs were benchmarked using AmorphousDiskMark; Codespaces storage was benchmarked using fio.
MacBook Pro 1TB SSD | M1 Air 1TB SSD | Codespace /workspaces | |
---|---|---|---|
Sequential Read (bs=1m, qd=8) | 3024.61 MB/s (87%) | 3462 MB/s | 4793 MB/s (138%) |
Sequential Write (bs=1m, qd=8) | 3315.22 MB/s (99%) | 3336 MB/s | 311MB/s (9%) |
Random Read (bs=4k, qd=64) | 798.30 MB/s (76%) | 1046 MB/s | 771 MB/s (67%) |
Random Write (bs=4k,qd=64) | 241.59 MB/s (158%) | 152.22 MB/s | 146 MB/s (96%) |
Codespaces’ random write performance is comparable with Apple M1 SSDs, both are outperformed by the MacBook Pro SSD. Random read performance is comparable between the Intel Macbook Pro and Codespaces, while the M1 achieves 25% more throughput.
Apple appears to aggressively cache sequential writes, so the write throughput probably doesn’t include flushing to disk. Codespaces sequential read performance is also suspiciously high, probably due to operating system level caching. Caching may occur because fio
is running inside Docker where the direct I/O flag doesn’t work.
Bottom line, Codespaces’ disk throughput is more than adequate for development purposes and is unlikely to bottleneck a build process. While the variances are interesting, they will not be noticeable in most build processes.
Compilation Performance
This test compiles a large codebase (Node.js) with different parallelism options to validate performance on a real-world development build. The -j
option causes make
to run simultaneous compilation jobs. The results are compilation time in seconds.
MB Pro - i7 Quad-Core | M1 Macbook Air 8-Core | 8-Core Codespace | 16-Core Codespace | |
---|---|---|---|---|
make -j4 |
2290 (208%) | 1099 | 2301 (209%) | 2232 (203%) |
make -j6 |
1955 (203%) | 959 | 1939 (202%) | 1951 (203%) |
make -j8 |
1786 (188%) | 947 | 1850 (195%) | 1772 (187%) |
make -j16 |
- | - | - | 884 (93%) |
The results here pretty much mirror the CPU benchmarks. The 8-Core Codespace and the Intel Macbook Pro achieve comparable compile times.
The 16-Core Codespace achieves the shortest compile time by running 16 simultaneous compilation jobs, exploiting all available threads.
Network Speed
Codespaces offers ~10 GiB pipe to the Internet; this is significantly faster than anything available in most business and domestic settings. In Australia, the fastest NBN tier available to domestic users is gigabit. In many office settings, a fast Internet connection is bottlenecked by a slower WIFI connection, constraining bandwidth on the end-user device to sub-gigabit.
For remote workers on mobile data plans using Microsofts Internet means large image downloads won’t count towards your mobile data usage or starve Zoom of bandwidth.
Codespaces doesn’t charge you for any data transferred into or out of the environment.
Assuming a twenty-day working month, an eight-hour working day and a default idle timeout of four hours, we can model our costs on 240 hours of Codespace uptime per month.
Cost Per Hour | Max Storage Per Month | Cost Per Month | Cost Per Year | |
---|---|---|---|---|
4-Core, 8GB RAM, 32GB | $0.36 | $2.24 | $88.64 | $1,063.68 |
8-Core, 16GB RAM, 64GB | $0.72 | $4.48 | $177.28 | $2,127.36 |
16-Core, 32GB RAM, 128GB | $1.44 | 8.96 | $354.56 | $4,254.72 |
Storage is charged at $0.07 per GB per month, which doesn’t have a significant cost impact given the limited amount of storage provisioned.
For development environments with multiple Docker containers, I found the 8-Core instance type to be most practical because it offered the right balance of compute, storage and memory at a reasonable price point.
The demo project is a non-trivial Codespace development environment representing a full-stack project using React, Next.js, Hasura and Postgres.
The development environment demonstrates the following:
You can find the demo project here.
Are you tired of spending hours setting up your local machine so you can work with a new repository? Is Docker hogging CPU and memory, killing the promise of...
In the post, we will explore how we can use partitions to reduce job execution time by increasing parallelism. Specifically, we will focus on building Spark ...
Aws-azure-login is a command-line utility for organisations using Azure Active Directory to authenticate users to the AWS console. It lets you use an Azure A...