<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Performance on Dwarf</title><link>https://docs.dwarf.run/performance/</link><description>Recent content in Performance on Dwarf</description><generator>Hugo</generator><language>en-US</language><atom:link href="https://docs.dwarf.run/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>Cloud Benchmarks</title><link>https://docs.dwarf.run/performance/benchmark-cloud/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dwarf.run/performance/benchmark-cloud/</guid><description>&lt;h1 id="cloud-benchmarks"&gt;Cloud Benchmarks&lt;a class="anchor" href="#cloud-benchmarks" aria-label="Anchor" aria-hidden="true"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;For operators&lt;/strong&gt; sizing a deployment. This page answers how much one database serves, what adding
shards and engine replicas does, and what the engine itself costs. Every number was measured, and the
configuration that produced it is stated beside it.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2 id="the-short-version"&gt;The Short Version&lt;a class="anchor" href="#the-short-version" aria-label="Anchor" aria-hidden="true"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What it delivers&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One 32 vCPU PostgreSQL database runs 18,900–24,300 steps/s with the archive on&lt;/strong&gt;, 1.6–2.1 billion steps a day,
at the engine&amp;rsquo;s shipped defaults and with the database&amp;rsquo;s checkpoints sized as recommended. The range is the
instance: the slower one spent 22% more database CPU per step and took 25% longer per log flush. Check yours
(&lt;a href="#method-notes"&gt;Method Notes&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Payload is paid in write-ahead log.&lt;/strong&gt; With 8 KB of JSON per step the same database runs ~10,300 steps/s, with
64 KB ~2,800 (~176 MB/s of payload). Every flush of the log costs about 0.8 ms plus its bytes, so the bytes a step
logs set the rate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Size the database&amp;rsquo;s checkpoints.&lt;/strong&gt; With 8 KB payloads, a 20 GB &lt;code&gt;max_wal_size&lt;/code&gt; ran 42% more steps/s than the
1.5 GB default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;32 vCPU is the most economical database size&lt;/strong&gt;, $0.036–0.047 per million steps at full load. Smaller
databases run out of CPU; larger ones are held back by the write-ahead log&amp;rsquo;s flush, so past 32 vCPU you add
shards.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The engine is cheap.&lt;/strong&gt; A shard&amp;rsquo;s work takes about 5 engine cores. Two 8 vCPU engine hosts per
32 vCPU database serve it at about a third of their CPU each, and either can carry it alone.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shards add throughput linearly.&lt;/strong&gt; Four 32 vCPU shards ran 91,800 steps/s, 3.8 times one shard, each shard
at close to what one shard runs alone.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No flow failed in any run.&lt;/strong&gt; In the 243 runs behind this page, across 40 sessions, no flow errored and no
step was left stuck. The engine recovered a crashed worker&amp;rsquo;s step only in the runs that killed engines on
purpose.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Failover takes about 40 seconds and loses nothing.&lt;/strong&gt; With every dispatcher killed at once, dispatch
paused for ~40 s, standby replicas took over, and every flow completed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replicas add availability, not cost.&lt;/strong&gt; One, two or four replicas on a shard deliver the same
throughput within 6%. Each shard is served by two of them, and any others stand by to take over.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Long tasks cost no throughput, and mixed durations share one engine.&lt;/strong&gt; With 8-second tasks the engine
delivered the full offered rate, and a mix of 5 ms, 200 ms and 8 s tasks ran at the latency each class
predicts. 10,000 concurrent 60-second tasks ran on under one engine core.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Large state works up to the database column&amp;rsquo;s limit.&lt;/strong&gt; 250 MB per step completed cleanly, at ~45 MB/s for
one flow and ~135 MB/s for four.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A day of varied load ran without falling behind.&lt;/strong&gt; 4.5 hours of mixed shapes, payloads, task durations and
priorities, with bursts above capacity, a rolling restart and a database restart: flows completed at the rate they
arrived, bursts cost only the lowest priorities a wait, and the live tables levelled off at 10 GB
(&lt;a href="https://docs.dwarf.run/performance/benchmark-day/"&gt;A Day of Varied Load&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A growing archive costs nothing measurable.&lt;/strong&gt; A 32 vCPU database ran saturated until its archive held 100 million
step rows, and ran at its empty rate the whole way, while the live tables stayed at ~3 GB. Archived reads took
7–20 ms at every size (&lt;a href="#database-volume"&gt;Database Volume&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What it means for sizing&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>A Day of Varied Load</title><link>https://docs.dwarf.run/performance/benchmark-day/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dwarf.run/performance/benchmark-day/</guid><description>&lt;h1 id="a-day-of-varied-load"&gt;A Day of Varied Load&lt;a class="anchor" href="#a-day-of-varied-load" aria-label="Anchor" aria-hidden="true"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;For operators&lt;/strong&gt; deciding whether one database carries their traffic through a day, not just at a steady rate.
Four and a half hours of mixed flows on one PostgreSQL database, with bursts above its capacity, a rolling restart
of the engines and a restart of the database itself. The steady-rate measurements are in
&lt;a href="https://docs.dwarf.run/performance/benchmark-cloud/"&gt;Cloud Benchmarks&lt;/a&gt;, whose database and settings this run shares.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;img src="https://docs.dwarf.run/performance/benchmark-day.png" alt="A day on one database: offered load and completed flows by priority" /&gt;&lt;/p&gt;</description></item><item><title>Sizing &amp; Tuning</title><link>https://docs.dwarf.run/performance/sizing-and-tuning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dwarf.run/performance/sizing-and-tuning/</guid><description>&lt;h1 id="sizing--tuning"&gt;Sizing &amp;amp; Tuning&lt;a class="anchor" href="#sizing--tuning" aria-label="Anchor" aria-hidden="true"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;For operators&lt;/strong&gt; who want to know how the engine sizes itself, or who need to override it. You don&amp;rsquo;t need
this page to run Dwarf: the decisions are in &lt;a href="https://docs.dwarf.run/operating/deployment/"&gt;Deployment&lt;/a&gt;, and the engine applies
these numbers for you. The measurements behind them are in the &lt;a href="https://docs.dwarf.run/performance/benchmark-cloud/"&gt;Cloud Benchmarks&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2 id="connection-pool"&gt;Connection Pool&lt;a class="anchor" href="#connection-pool" aria-label="Anchor" aria-hidden="true"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Each shard&amp;rsquo;s connection budget is a constant adjusted for distance and capped by the server: &lt;strong&gt;250&lt;/strong&gt;
connections up to 0.25 ms of round-trip time, rising evenly to &lt;strong&gt;500&lt;/strong&gt; at 1 ms, and never more than half
the server&amp;rsquo;s own &lt;code&gt;max_connections&lt;/code&gt; (a fixed 8 on SQLite). The budget is shared by the shard&amp;rsquo;s two
dispatching replicas, about 125 connections each at the default. The rules for overriding it are in
&lt;a href="https://docs.dwarf.run/operating/deployment/#connection-pool"&gt;Deployment&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Dialect Benchmarks</title><link>https://docs.dwarf.run/performance/benchmark/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.dwarf.run/performance/benchmark/</guid><description>&lt;h1 id="benchmarks"&gt;Benchmarks&lt;a class="anchor" href="#benchmarks" aria-label="Anchor" aria-hidden="true"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;For developers and operators&lt;/strong&gt; comparing SQL dialects or shard counts on their own hardware. These are
single-host laptop-scale numbers — good for &lt;em&gt;relative&lt;/em&gt; comparison, not for capacity planning. For
absolute numbers and how to size a deployment, see &lt;a href="https://docs.dwarf.run/performance/benchmark-cloud/"&gt;Cloud Benchmarks&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;The benchmarks in &lt;a href="https://github.com/microbus-io/dwarf/tree/main/fixtures" target="_blank" rel="noopener"&gt;&lt;code&gt;fixtures&lt;/code&gt;&lt;/a&gt; in the Dwarf repository measure end-to-end flow throughput and latency through the &lt;strong&gt;public API&lt;/strong&gt;
(&lt;code&gt;Run&lt;/code&gt; = create + await) against whatever SQL dialect &lt;code&gt;SEQUEL_TESTING_DSN&lt;/code&gt; points at. They measure what code
review cannot tell you: how many flows and steps per second each dialect sustains at each shard count, and the
dispatch-latency percentiles.&lt;/p&gt;</description></item></channel></rss>