Skip to content

Commit 51e55ae

Browse files
committed
Improve website's grid layout and add Payload CMS benchmarks results.
1 parent f92c048 commit 51e55ae

File tree

4 files changed

+146
-82
lines changed

4 files changed

+146
-82
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
import { Card } from "@astrojs/starlight/components";
3+
4+
export interface Props {
5+
title: string;
6+
icon?: any;
7+
reverse?: boolean;
8+
}
9+
10+
const { title, icon, reverse } = Astro.props as Props;
11+
---
12+
13+
<Card title={title} icon={icon}>
14+
<div
15+
class:list={[
16+
"flex",
17+
"flex-col",
18+
reverse ? "md:flex-row-reverse" : "md:flex-row",
19+
"gap-2",
20+
"md:gap-8",
21+
]}
22+
>
23+
<div class="md:w-[45%]">
24+
<slot name="first" />
25+
</div>
26+
27+
<div class="md:w-[55%]">
28+
<slot name="second" />
29+
</div>
30+
</div>
31+
</Card>

docs/src/content/docs/index.mdx

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ hero:
2222

2323
import { Image } from "astro:assets";
2424
import { Aside, Card, CardGrid } from "@astrojs/starlight/components";
25+
import SplitCard from "@/components/SplitCard.astro";
26+
27+
import Roadmap from "./_roadmap.md";
2528

2629
import screenshot from "@/assets/screenshot.webp";
2730
import dotnetLogo from "@/assets/dotnet_logo.svg";
@@ -30,64 +33,60 @@ import tsLogo from "@/assets/ts_logo.svg";
3033

3134
import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx";
3235

33-
<div class="flex justify-center">
34-
<div class="md:w-[80%] flex flex-col gap-4">
36+
<div class="flex flex-col gap-4">
3537

36-
<div>
37-
<h3>Total time for 100k insertions</h3>
38+
<SplitCard title="Performance" icon="rocket">
39+
<div slot="first">
40+
Blazingly fast thanks to its constituents:
3841

39-
<a href="/reference/benchmarks">
40-
TrailBase adds minimal overhead compared to in-process SQLite and
41-
beats other excellent choices:
42-
</a>
42+
* Rust: one of the lowest overhead languages,
43+
* Axum: one of the fastest HTTP servers,
44+
* SQLite/Libsql: one of the fastest full-SQL databases,
45+
* V8: one of the fastest JS engines.
4346

44-
<div class="w-full h-[260px] mt-4">
47+
TrailBase APIs are [6-7x faster than PocketBase's and 15x faster than SupaBase's
48+
needing only a fraction of the footprint](/reference/benchmarks), allowing
49+
you to serve millions of customers from a tiny box.
50+
TrailBase JS runtime is ~40x faster than PocketBase's.
51+
</div>
52+
53+
<div slot="second">
54+
<a href="/reference/benchmarks">Total time for 100k insertions:</a>
55+
56+
<div class="w-full h-[300px]">
4557
<Duration100kInsertsChart client:only="solid-js" />
4658
</div>
4759
</div>
60+
</SplitCard>
61+
62+
<Card title="Admin Dashboard" icon="setting">
63+
TrailBase ships with a builtin admin dashboard UI, see demo above, that
64+
lets you quickly configure your instance and visually explore your data.
65+
Following TrailBase's mantra of not getting in your way, the UI is
66+
entirely optional letting you fall back to a purely config &
67+
migration-based setup for integration tests or managing an entire fleet
68+
of deployments.
4869

49-
#### Live Demo
70+
Check out the **live demo**:
5071

51-
<div class="relative" >
72+
<div class="flex justify-center">
73+
<div class="max-w-[680px] relative" >
5274
<a href="https://demo.trailbase.io/_/admin">
5375
<Image class="z-0 rounded-xl" src={screenshot} alt="Screenshot of TrailBase's admin dashboard" />
5476
</a>
5577

5678
<div class="z-1 w-full h-full absolute top-0 flex justify-center items-center pointer-events-none">
5779
<a class="pointer-events-auto no-underline flex flex-col items-center bg-gray-200 dark:bg-accent-900 px-4 py-2 rounded" href="https://demo.trailbase.io/_/admin">
80+
<strong>Live Demo</strong>
5881
<span>login: admin@localhost</span>
5982
<span>password: secret</span>
6083
</a>
6184
</div>
6285
</div>
86+
</div>
87+
</Card>
6388

64-
<Aside type="caution" title="Early Days">
65-
TrailBase is very young.
66-
You can expect many new features but also moving APIs until things settle.
67-
We'll make sure to follow semantic versioning and welcome brave, early
68-
adopters.
69-
</Aside>
70-
71-
</div>
72-
</div>
73-
74-
<div class="w-full py-8">
75-
76-
<CardGrid stagger>
77-
78-
<Card title="Performance" icon="rocket">
79-
Blazingly fast thanks to its constituents:
80-
81-
* Rust: one of the lowest overhead languages,
82-
* Axum: one of the fastest HTTP servers,
83-
* SQLite/Libsql: one of the fastest full-SQL databases.
84-
* V8: one of the fastest JS runtimes
85-
86-
TrailBase APIs are [6-7x faster than PocketBase and 15x faster than SupaBase
87-
needing only a fraction of the footprint](/reference/benchmarks), allowing
88-
you to serve millions of customers from a tiny box.
89-
TrailBase JS runtime is ~40x faster than PocketBase's.
90-
</Card>
89+
<CardGrid>
9190

9291
<Card title="Simple" icon="heart">
9392
TrailBase is a small, single file, static binary that is incredibly easy
@@ -100,15 +99,6 @@ import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx
10099
let you move faster, more confidently and pivot when necessary.
101100
</Card>
102101

103-
<Card title="Admin Dashboard" icon="setting">
104-
TrailBase ships with a builtin admin dashboard UI, see demo above, that
105-
lets you quickly configure your instance and visually explore your data.
106-
Following TrailBase's mantra of not getting in your way, the UI is
107-
entirely optional letting you fall back to a purely config &
108-
migration-based setup for integration tests or managing an entire fleet
109-
of deployments.
110-
</Card>
111-
112102
<Card title="Authentication" icon="open-book">
113103
TrailBase comes with an authentication system and UI built in supporting
114104
both password-based and Social/OAuth (Google, Discord, ...) sign-ups.
@@ -151,9 +141,10 @@ import { Duration100kInsertsChart } from "./reference/_benchmarks/benchmarks.tsx
151141
</Card>
152142

153143
</CardGrid>
144+
154145
</div>
155146

156-
import Roadmap from "./_roadmap.md";
147+
<div class="h-8" />
157148

158149
<div class="flex justify-center">
159150
<div class="md:w-[80%] flex flex-col items-center gap-4">

docs/src/content/docs/reference/_benchmarks/benchmarks.tsx

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Datum = {
1818
};
1919

2020
const colors = {
21+
payload: "rgb(0, 101, 101)",
2122
supabase: "rgb(62, 207, 142)",
2223
pocketbase0: "rgb(230, 128, 30)",
2324
pocketbase1: "rgb(238, 175, 72)",
@@ -57,37 +58,41 @@ function transformMillisecondTicks(
5758
}
5859
}
5960

60-
const durations100k = [
61-
{
61+
const durations100k = {
62+
payload: {
63+
label: "Payload v3+SQLite",
64+
data: [656.09],
65+
backgroundColor: colors.payload,
66+
},
67+
supabase: {
6268
label: "SupaBase",
6369
data: [151],
6470
backgroundColor: colors.supabase,
6571
},
66-
{
72+
pocketbase_ts: {
6773
label: "PocketBase TS",
6874
data: [67.721],
6975
backgroundColor: colors.pocketbase0,
7076
},
71-
// {
72-
// label: "PocketBase Dart (AOT)",
73-
// data: [62.8136],
74-
// },
75-
{
77+
pocketbase_dart_aot: {
78+
label: "PocketBase Dart (AOT)",
79+
data: [62.8136],
80+
},
81+
pocketbase_dart_jit: {
7682
label: "PocketBase Dart (JIT)",
7783
data: [61.687],
7884
backgroundColor: colors.pocketbase1,
7985
},
80-
{
86+
trailbase_ts: {
8187
label: "TrailBase TS",
8288
data: [16.742],
8389
backgroundColor: colors.trailbase0,
8490
},
85-
// {
86-
// label: "TrailBase Dart (AOT)",
87-
// data: [11.1],
88-
// },
89-
{
90-
// label: "TrailBase Dart (JIT)",
91+
trailbase_dart_aot: {
92+
label: "TrailBase Dart (AOT)",
93+
data: [11.1],
94+
},
95+
trailbase_dart_jit: {
9196
label: "TrailBase Dart",
9297
data: [9.4247],
9398
backgroundColor: colors.trailbase1,
@@ -96,22 +101,46 @@ const durations100k = [
96101
// label: "TrailBase Dart (JIT + PGO)",
97102
// data: [10.05],
98103
// },
99-
// {
100-
// label: "TrailBase Dart (INT PK)",
101-
// data: [8.5249],
102-
// backgroundColor: colors.trailbase2,
103-
// },
104-
{
104+
trailbase_dart_jit_int_pk: {
105+
label: "TrailBase Dart (INT PK)",
106+
data: [8.5249],
107+
backgroundColor: colors.trailbase2,
108+
},
109+
drizzle: {
105110
label: "In-process SQLite (Drizzle)",
106111
data: [8.803],
107112
backgroundColor: colors.drizzle,
108113
},
109-
];
114+
};
110115

111116
export function Duration100kInsertsChart() {
112117
const data: ChartData<"bar"> = {
113-
labels: ["Time [s] (lower is better)"],
114-
datasets: durations100k as ChartDataset<"bar">[],
118+
labels: ["Time in seconds (lower is faster)"],
119+
datasets: [
120+
durations100k.supabase,
121+
durations100k.pocketbase_ts,
122+
durations100k.pocketbase_dart_jit,
123+
durations100k.trailbase_ts,
124+
durations100k.trailbase_dart_jit,
125+
durations100k.drizzle,
126+
] as ChartDataset<"bar">[],
127+
};
128+
129+
return <BarChart data={data} />;
130+
}
131+
132+
export function Duration100kInsertsChartMoreResults() {
133+
const data: ChartData<"bar"> = {
134+
labels: ["Time in seconds (lower is faster)"],
135+
datasets: [
136+
durations100k.payload,
137+
durations100k.supabase,
138+
durations100k.pocketbase_ts,
139+
durations100k.pocketbase_dart_jit,
140+
durations100k.trailbase_ts,
141+
durations100k.trailbase_dart_jit,
142+
durations100k.drizzle,
143+
] as ChartDataset<"bar">[],
115144
};
116145

117146
return <BarChart data={data} />;

docs/src/content/docs/reference/benchmarks.mdx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Performance comparison with similar products.
44
---
55

66
import {
7-
Duration100kInsertsChart,
7+
Duration100kInsertsChartMoreResults,
88
PocketBaseAndTrailBaseReadLatencies,
99
PocketBaseAndTrailBaseInsertLatencies,
1010
SupaBaseMemoryUsageChart,
@@ -53,13 +53,13 @@ Ultimately, nothing beats benchmarking your own workload and setup.
5353
_Total Time for 100k Insertions_
5454

5555
<div class="flex justify-center">
56-
<div class="h-[300px] w-[90%]">
57-
<Duration100kInsertsChart client:only="solid-js" />
56+
<div class="h-[400px] w-[90%]">
57+
<Duration100kInsertsChartMoreResults client:only="solid-js" />
5858
</div>
5959
</div>
6060

6161
The graph shows the overall time it takes to insert 100k messages into a mock
62-
"chat-room" table setup. Less time is better.
62+
*chat-room* table setup. Less time is better.
6363

6464
Unsurprisingly, in-process SQLite is the quickest [^2].
6565
All other setups add additional table look-ups for access checking, IPC
@@ -69,11 +69,15 @@ and the cost a project would pay by adopting any of the systems over in-process
6969
SQLite.
7070

7171
The data suggests that depending on your setup (client, data, hardware)
72-
TrailBase can insert 100k records 9 to 16 times faster than SupaBase[^4] and
73-
roughly 6 to 7 times faster than PocketBase [^1].
72+
TrailBase can insert 100k records almost 70 times faster than Payload[^4], 9 to
73+
16 times faster than SupaBase[^5], and roughly 6 to 7 times faster than
74+
PocketBase [^1].
75+
76+
{/*
7477
The fact that our TS/node.js benchmark is slower than the Dart one, suggests a
7578
client-side bottleneck that could be overcome by tuning the setup or trying
7679
other JS runtimes with lower overhead HTTP clients.
80+
*/}
7781

7882
Total time of inserting a large batch of data tells only part of the story,
7983
let's have a quick look at resource consumption to get an intuition for
@@ -90,7 +94,7 @@ _TrailBase & PocketBase Utilization_
9094
The graph shows the CPU utilization and memory consumption (RSS) of both
9195
PocketBase and TrailBase. They look fairly similar apart from TrailBase
9296
finishing earlier. They both load roughly 3 CPUs with PocketBase's CPU
93-
consumption being slightly more variable [^5].
97+
consumption being slightly more variable [^6].
9498
The little bump after the TrailBase run is likely due to SQLite check-pointing.
9599

96100
Both only consume about 140MB of memory at full tilt, which makes them a great
@@ -218,8 +222,8 @@ The benchmarks are available on [GitHub](https://github.com/trailbaseio/trailbas
218222

219223
[^2]:
220224
Our setup with drizzle and node.js is certainly not the fastest possible.
221-
For example, we could drop down to using raw SQLite in C or another
222-
low-level language.
225+
For example, we could drop down to SQLite in C or another low-level
226+
language with less FFI overhead.
223227
That said, drizzle is a great popular choice which mostly serves as a
224228
point-of-reference and sanity check.
225229

@@ -228,14 +232,23 @@ The benchmarks are available on [GitHub](https://github.com/trailbaseio/trailbas
228232
For the benchmarks at hand we're using a loopback network device.
229233

230234
[^4]:
235+
We picked Payload as representative of popular Node.js CMS, which
236+
[itself claims](https://payloadcms.com/blog/performance-benchmarks)
237+
to be many times faster than popular options like Strapi or Directus.
238+
We were using a v3 pre-release, as recommended, also using the
239+
SQLite/drizzle database adapter marked as beta.
240+
We manually turned on WAL mode and filed an issue with payload, otherwise
241+
stock payload was ~210x times slower.
242+
243+
[^5]:
231244
The SupaBase benchmark setup skips row-level access checks. Technically,
232245
this is in its favor from a performance standpoint, however looking at the
233246
overall load on its constituents with PG being only a sliver, it probably
234247
would not make much of an overall difference nor would PG17's vectorization,
235248
which has been released since the benchmarks were run. That said, these
236249
claims deserve re-validation.
237250

238-
[^5]:
251+
[^6]:
239252
We're unsure as to what causes these 1-core swings.
240253
Runtime-effects, such as garbage collection, may have an effect, however we
241254
would have expected these to show on shorter time-scales.

0 commit comments

Comments
 (0)