Aller au contenu

Cette page n'est pas encore traduite. Elle s'affiche en anglais.

Performance tuning

The Elide settings that change speed and memory: serving contexts, network transport, heap size and profiles, plus how to benchmark startup and serving.

Sur cette page

This page lists the settings that change Elide’s speed and memory use, and how to measure them.

SettingApplies toDefault
--contexts=N, --contexts=autoFetch-handler servers under run, serve, dev (Linux for more than one)1
engine.contexts in elide.pklelide serve, elide dev1
--max-mem=SIZEEvery command4g for one-shot runs; sized from host memory for serve, dev
--transport=VALUE, ELIDE_TRANSPORT_V2fetch and dependency downloadsauto
--sandbox=PROFILEEvery programtrusted

Add serving contexts

A context is one copy of your app with its own module state. Each context runs requests on its own thread, so more contexts serve more requests at once on more cores.

elide serve --no-tui --contexts=4 server.mjs
elide run --contexts=auto server.mjs

auto uses the physical cores minus two. Set it per project for serve and dev:

// elide.pkl
amends "elide:project.pkl"

engine {
  contexts { spawn = "auto"; reserve = 2; min = 1; max = 16 }
}
RuleDetail
elide runReads --contexts only; pass the flag.
Module stateNot shared between contexts; keep shared state in a database or another service.
node:http serversOne context; a second copy fails with EADDRINUSE.
PlatformsMore than one context requires Linux.

Server I/O threads follow the context count; ELIDE_HTTP_NATIVE_WORKERS does not change them under run, serve or dev. Field reference: Engine contexts; walkthrough: Several contexts.

Cap memory

elide --max-mem=512m run app.js
elide --max-mem=2g serve server.mjs

--max-mem caps the heap. One-shot runs (run, a bare file) default to at most 4g; serve and dev size the heap from host or container memory, so set it on every container or shared host. A full heap exits 1 with the heap address space is exhausted; a cap of 128m or less fails at startup. See Troubleshooting.

Choose a network transport

--transport picks how fetch and dependency downloads reach the network. It does not change HTTP servers.

ValueUse
autoBest transport for the host. On Linux this is v2 with epoll.
v2Elide’s own transport, with its own TLS. ELIDE_TRANSPORT_V2=1 selects it when no flag is given.
epoll, io_uringv2 with that Linux event driver.
kqueuev2 on macOS; other platforms exit 2.
nioPortable transport, for comparison or when a native driver fails.
elide --transport=io_uring run client.mjs
elide info

elide info prints the selected transport and driver on its Transport: line. An explicit --transport wins over ELIDE_TRANSPORT_V2. ELIDE_TRANSPORT_DIAGNOSTICS=1 prints transport statistics to stderr.

Pick an execution profile

ProfileStatus
--sandbox=trustedDefault; no confinement cost.
--sandbox=sandboxedExits 2: --sandbox=sandboxed is unavailable
--sandbox=isolatedExits 2: --sandbox=isolated is not available in this build

Permission flags and limits are on Sandbox and Limits.

Find the slow part

QuestionTool
Where does startup time go?ELIDE_DIAG_STARTUP=1 elide run app.js prints each startup phase with a timestamp to stderr.
Which functions run most?elide run --profiler=cputracing app.js; see Debugging.
What happened during a run or a request?elide --jfr=run.jfr run app.js; see Monitoring and Profiling.
Where does compiled code spend CPU time?--jitdump=DIR with Linux perf; see Monitoring and Profiling.
Which requests are slow in production?Server spans and http.server.request.duration; see OpenTelemetry.

Measure startup

Run hyperfine with -N (no shell) so each sample is one process:

// hello.js
console.log("Hello, world!");
hyperfine -N --warmup 10 --runs 100 --export-json startup.json \
  'elide run hello.js' 'node hello.js' 'bun hello.js' 'deno run hello.js'

Call each runtime’s real binary: a version-manager shim or wrapper script adds a process to every sample. Give the full path if which elide is not the installed binary.

Measure serving

Serve one fixed response and load it with wrk:

// server.mjs
export default {
  hostname: "127.0.0.1",
  port: 3000,
  fetch() {
    return new Response("Hello, world!");
  },
};
elide run server.mjs &
wrk -t12 -c256 -d5s http://127.0.0.1:3000/ > /dev/null
wrk -t12 -c256 -d10s --latency http://127.0.0.1:3000/ > elide.txt
kill %1
StepWhy
Discard a 5-second run firstThe first requests compile the handler.
Pin the server and wrk to separate cores, e.g. taskset -c 0-7 elide run server.mjs and taskset -c 8-15 wrk ...Keeps the load generator from taking the server’s CPU.
Repeat with --contexts=autoOne context uses one thread for your handler.
Compare Requests/sec and the --latency percentilesAverages hide tail latency.

bun server.mjs serves the same file; deno serve --port 3000 --host 127.0.0.1 server.mjs needs the address on the command line.

Multi-context serving

elide run --contexts=auto server.mjs
# Or choose the count explicitly:
elide run --contexts=24 server.mjs

One process evaluates the server entry module in each context and serves requests concurrently. Each context has its own JavaScript globals and module state. The process shares one managed heap, garbage collector, and eligible parsed/JIT-compiled code across contexts. Ordinary objects are not shared application state; use external coordination when replicas must agree. Process failures and GC pauses can affect all contexts. Start with auto, then measure your workload before choosing a fixed count.

The published HTTP benchmarks distinguish default single-context serving from tuned multi-context serving with HTTP pipelining, and include a configuration table, architecture diagram, hardware/OS details, and a downloadable runner. Their peak configuration also selects inline scheduling and io_uring; --contexts alone does not reproduce it.

See also

Cette page vous a-t-elle aidé ?