Skip to content

Commit

Permalink
Add musl release builds and basic load testing scripts (#940)
Browse files Browse the repository at this point in the history
Closes #116 
Closes #548 (this PR just adds basics, but there is always more to do,
so no point in keeping the issue open)
CC #934 
CC #59 

This PR adds some basic load testing scripts and also adds `-musl`
builds as officially supported release binary. To do the latter, scripts
are adjusted and test deployments on Tue, Thurs and Saturday use musl.
This might seem very weird (and it kind of is), but this means that we
will constantly testing both builds to avoid some hard to spot bugs
sneaking in. Additionally, Tobira now uses jemalloc as allocator due to
musl performance reasons, see below.

See commit messages for more information.

---

### Musl performance considerations

Our main blocker for just offering musl builds were performance
considerations. One often reads on the interwebz that musl is slow. This
is only partially true and many comments are outdated (see
#116 (comment)).
However, we wanted to test for ourselves. That's why this PR adds basic
load tests. They are not amazing, but they helped already.

Results of running locally (the ms are average response times):


| | `GET index.html` | Homepage GraphQL query | Video page GraphQL query
|
| ------------------ | ---------------- | ---------------------- |
------------------------ |
| musl | 110k req/s | 430 req/s (35ms) | 1250 req/s (11.6ms)
| gnu | 276k req/s | 2760 req/s (5.0ms) | 4120 req/s (3.1ms)
| musl with jemalloc | 272k req/s | 2830 req/s (4.8ms) | 4100 req/s
(3.1ms)
| gnu with jemalloc | 271k req/s | 2860 req/s (4.8ms) | 4090 req/s
(3.2ms)

The gist: musl with built-in allocator is still significantly slower
than all other options. And all other options don't differ significantly
(the differences are most certainly below noise threshold).

So yeah, that lead to the decision to use jemalloc for both kinds of
builds.

CC @mtneug
  • Loading branch information
owi92 authored Sep 20, 2023
2 parents 4974312 + bc12207 commit 7fbc13d
Show file tree
Hide file tree
Showing 20 changed files with 2,024 additions and 18 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,31 @@ jobs:
draft: true
fail_on_unmatched_files: true
generate_release_notes: true

build-musl:
name: Build musl release
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Install musl requisites
run: sudo apt install -y musl-dev musl-tools

- name: Install musl target
run: rustup target add x86_64-unknown-linux-musl

- name: Create release build
run: ./x.sh build-release --musl

- name: Rename binary to include target information
run: mv deploy/tobira deploy/tobira-x86_64-unknown-linux-musl

- name: create new release
uses: softprops/action-gh-release@v1
with:
files: |
deploy/tobira-x86_64-unknown-linux-musl
draft: true
fail_on_unmatched_files: true
generate_release_notes: true
42 changes: 28 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,35 @@ jobs:
steps:
- uses: actions/checkout@v3

# Figure out build mode
- name: Determine build mode
run: |
target_dir="target"
if (( "$(date +%w)" % 2 == 0 )); then
sudo apt install -y musl-dev musl-tools
rustup target add x86_64-unknown-linux-musl
echo "ci_cargo_target=--target=x86_64-unknown-linux-musl" >> $GITHUB_ENV
echo "rust_cache_key=musl" >> $GITHUB_ENV
target_dir="${target_dir}/x86_64-unknown-linux-musl"
else
echo "ci_cargo_target=" >> $GITHUB_ENV
echo "rust_cache_key=gnu" >> $GITHUB_ENV
fi
if [[ "$GITHUB_REPOSITORY" == "elan-ev/tobira" ]] && [ "$GITHUB_REF" == "refs/heads/master" ]; then
echo "ci_cargo_flags=--release" >> $GITHUB_ENV
echo "ci_targetdir=${target_dir}/release" >> $GITHUB_ENV
echo "ci_webpack_flags=production" >> $GITHUB_ENV
else
echo "ci_cargo_flags=--features=embed-in-debug" >> $GITHUB_ENV
echo "ci_targetdir=${target_dir}/debug" >> $GITHUB_ENV
echo "ci_webpack_flags=development" >> $GITHUB_ENV
fi
- name: Restore backend cache
uses: Swatinem/rust-cache@v2
with:
key: ${{ env.rust_cache_key }}
workspaces: backend

# Frontend cache: only the NPM folder is cached, not the node_modules, as
Expand All @@ -52,18 +78,6 @@ jobs:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('frontend/package-lock.json') }}

# Figure out build mode
- name: Determine build mode
run: |
if [[ "$GITHUB_REPOSITORY" == "elan-ev/tobira" ]] && [ "$GITHUB_REF" == "refs/heads/master" ]; then
echo "ci_cargo_flags=--release" >> $GITHUB_ENV
echo "ci_targetdir=target/release" >> $GITHUB_ENV
echo "ci_webpack_flags=production" >> $GITHUB_ENV
else
echo "ci_cargo_flags=--features=embed-in-debug" >> $GITHUB_ENV
echo "ci_targetdir=target/debug" >> $GITHUB_ENV
echo "ci_webpack_flags=development" >> $GITHUB_ENV
fi

# The actual building and testing!
- name: Installing frontend dependencies (npm ci)
Expand All @@ -84,10 +98,10 @@ jobs:

- name: Build backend
working-directory: backend
run: cargo build ${{ env.ci_cargo_flags }}
run: cargo build ${{ env.ci_cargo_flags }} ${{ env.ci_cargo_target }}
- name: Test backend
working-directory: backend
run: cargo test
run: cargo test ${{ env.ci_cargo_target }}

- name: Move Tobira binary
run: mv backend/${{ env.ci_targetdir }}/tobira tobira
Expand Down
21 changes: 21 additions & 0 deletions backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ tokio-postgres-rustls = "0.10.0"
[target.'cfg(target_os = "linux")'.dependencies]
procfs = "0.15.1"

[target.'cfg(not(target_env = "msvc"))'.dependencies]
tikv-jemallocator = "0.5"

[build-dependencies]
built = { version = "0.7", features = ["chrono", "git2"] }

Expand Down
1 change: 1 addition & 0 deletions backend/src/http/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl Assets {
"buildDateUtc": crate::version::build_time_utc(),
"gitCommitHash": crate::version::git_commit_hash(),
"gitWasDirty": crate::version::git_was_dirty(),
"target": crate::version::target(),
}).to_string());
variables.insert("global-style".into(), config.theme.to_css());
variables.insert("auth".into(), json!({
Expand Down
4 changes: 4 additions & 0 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! The Tobira backend server.
#[cfg(not(target_env = "msvc"))]
#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

use clap::{FromArgMatches, CommandFactory};
use deadpool_postgres::Pool;
use util::Never;
Expand Down
7 changes: 6 additions & 1 deletion backend/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ pub(crate) fn git_was_dirty() -> bool {
build_info::GIT_DIRTY == Some(true)
}

pub(crate) fn target() -> &'static str {
build_info::TARGET
}

/// Returns a string containing all version-related information.
pub(crate) fn full() -> String {
format!(
"{} ({}{}), built {}",
"{} ({}{}), built {} ({})",
identifier(),
git_commit_hash(),
if git_was_dirty() { ", dirty" } else { "" },
build_time_utc(),
target(),
)
}
11 changes: 11 additions & 0 deletions docs/docs/versioning-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ Every release mentions all potentially breaking changes in its release notes.

---

## Provided release binaries

We currently provide pre-built binaries for `x86_64-unknown-linux-gnu` and `x86_64-unknown-linux-musl`.
Both are supported and should work fine.

The `-gnu` build relies on dynamically linked libraries on your system.
We create that build on the oldest supported Ubuntu runner of GitHub actions, which is currently `20.04`.
Our release binary could require a glibc version up to the one on that runner, which is currently `2.31`.
In general, the dynamic library version requirements could change with any release.
If your server doesn't have those libraries, consider using the `-musl` build or [compiling Tobira yourself](./dev/build/release).

## Breaking and non-breaking changes

Our definition of these terms for Tobira. Defines what we guarantee and what we don't.
Expand Down
1 change: 1 addition & 0 deletions frontend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type VersionInfo = {
buildDateUtc: string;
gitCommitHash: string;
gitWasDirty: boolean;
target: string;
};

type UploadConfig = {
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/routes/About.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ABOUT_PATH } from "./paths";
import { makeRoute } from "../rauta";
import { PageTitle } from "../layout/header/ui";
import { Breadcrumbs } from "../ui/Breadcrumbs";
import { COLORS } from "../color";


export const AboutRoute = makeRoute(url => {
Expand Down Expand Up @@ -56,6 +57,10 @@ const About: React.FC = () => {
<a href={`https://github.com/elan-ev/tobira/releases/tag/${version.identifier}`}>
Tobira <strong>{version.identifier}</strong>
</a>
{" "}
<span css={{ color: COLORS.neutral80, paddingLeft: 8 }}>
(<code css={{ fontSize: 13 }}>{version.target}</code>)
</span>
<br />
{"Git info: "}
<a href={`https://github.com/elan-ev/tobira/commit/${version.gitCommitHash}`}>
Expand Down
2 changes: 2 additions & 0 deletions util/loadtest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/*.html
Loading

0 comments on commit 7fbc13d

Please sign in to comment.