stardust alpha-2610171653
- per-thread leak: about 4 MB per thread, never freed. the plugin uses a fixed thread pool
- schema clause leak: about 0.25 MB per commit, never freed. fixed in alpha-2610212237
per-thread leak
memory grows with every new thread that calls stardust, and isn't freed when the thread exits. a fixed pool of threads stays flat.
leak.c creates a new, empty database and runs one inline query
400 times: on a new thread each (MODE=new), or on 4 reused
threads (MODE=pool).
gcc -O2 -I$STARDUST/abi leak.c -L$STARDUST/lib/linux_amd64 -lstardust -lpthread \
-Wl,-rpath,$STARDUST/lib/linux_amd64 -o leak
STARDUST_LICENSE=... MODE=new ./leak new.db
resident size:
| queries | a new thread each | 4 reused threads |
|---|---|---|
| start | 15 MB | 15 MB |
| 100 | 373 MB | 48 MB |
| 200 | 781 MB | 48 MB |
| 300 | 1189 MB | 48 MB |
| 400 | 1597 MB | 48 MB |
leak.c, 112 lines
// Stardust C ABI only. Creates an empty database, then runs the same inline
// query 400 times one of two ways, printing resident size after every 100:
//
// MODE=new (default) each query on a new pthread, joined before the next
// starts
// MODE=pool on 4 pthreads that live for the whole run, 25 queries each per
// 100
//
// STARDUST_LICENSE=... MODE=new ./leak new.db
//
// What grows per new thread, as measured (alpha-2610171653 and
// alpha-2610212237):
//
// - an inline query (STARDUST_SOURCE_DOCUMENT): every one tried, with one
// clause or two, with or without orderBy, on an empty database or one
// with matching entities
// - a stored query (STARDUST_SOURCE_PATH) with orderBy, when its result
// is empty or it joins two clauses
//
// What stays flat: a stored query with one clause and matching rows, with or
// without orderBy, and a stored query with two clauses and no orderBy on an
// empty database.
static stardust_db *db;
static stardust_document *query_doc;
static pthread_barrier_t step;
static stardust_bytes
static long
static void
static void
static void *
// A pool worker: 25 queries, then wait for the report, four times.
static void *
int
schema clause leak
while a subscription to a query with a schema clause is open, each commit that changes its result adds memory: about 0.25 MB per commit with 4000 matching entities. releasing the subscription doesn't free it, and a new subscription doesn't reuse it. the same query without the schema clause stays flat.
subcommit.c creates a database with a schema and 4000
items matching it. then, twice: it subscribes to the query below, makes 400
commits that each toggle one item, reading the subscription up to each
commit, and releases the subscription.
{find [?e ?text ?done] where [[schema item ?e] [?e text ?text] [?e done ?done]] orderBy [?e]}
SCHEMA=0 runs the same query without its schema clause.
each run is a fresh process and a new database.
gcc -O2 -I$STARDUST/abi subcommit.c -L$STARDUST/lib/linux_amd64 -lstardust \
-Wl,-rpath,$STARDUST/lib/linux_amd64 -o subcommit
STARDUST_LICENSE=... ./subcommit new.db
resident size:
| with the schema clause | without it | |
|---|---|---|
| round 1: start | 16 MB | 16 MB |
| 100 commits | 50 MB | 25 MB |
| 200 commits | 74 MB | 26 MB |
| 300 commits | 101 MB | 27 MB |
| 400 commits | 126 MB | 31 MB |
| released | 126 MB | 31 MB |
| round 2: start | 125 MB | 29 MB |
| 100 commits | 152 MB | 31 MB |
| 200 commits | 177 MB | 31 MB |
| 300 commits | 203 MB | 31 MB |
| 400 commits | 230 MB | 33 MB |
| released | 230 MB | 33 MB |
subcommit.c, 121 lines
// Stardust C ABI only, one thread. Creates a database with schema `item` and
// 4000 items matching it. Then, twice: subscribes to a query over them, makes
// 400 commits that each toggle one item, reading the subscription up to each
// commit, and releases the subscription. Prints resident size after every
// 100 commits and after each release.
//
// STARDUST_LICENSE=... ./subcommit new.db
// SCHEMA=0 drops [schema item ?e] from the query.
static stardust_db *db;
static int64_t first; // the item the commits toggle
static stardust_bytes
static long
static stardust_document *
static int64_t
int