PostgreSQL
Benchmarks
How ARX compares with other ways of doing the same work on PostgreSQL, measured with BenchmarkDotNet.
A living summary of the PostgreSQL benchmarks: how ARX compares with raw Npgsql, Dapper and EF Core.
| Last updated | 2026-11-11: full run of every operation on Npgsql 10.0.3 and EF Core 10, with Dapper's one-statement unnest insert added |
| Operations measured | Create, CreateMultiple, batch scopes, Update, UpdateMultiple, Delete, DeleteMultiple, Retrieve, RetrieveMultiple (filters, paging, joins, complex queries), Execute (procedures, functions, tables from procedures, paging), the preloaded schema, services without a catalog |
| Machine | Intel Core i7-8750H, Windows 11, .NET 10.0.14, PostgreSQL 16 (postgres:16-alpine) in Docker Desktop, Npgsql 10.0.3, BenchmarkDotNet 0.15.8 |
| Compared with | Raw Npgsql (hand-written, typed parameters), Dapper 2.1.89, EF Core 10 (Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3; typed and property bag), binary COPY |
| Reports | The full run: results/2026-11-11-full-run.md (454 benchmarks, commit 9f8dc1f; the single-row Update class rerun on its own, see the report). The injection-check A/B: results/2026-11-08-security-ab.md. Earlier full run, on Npgsql 8.0.3 and EF Core 8: results/2026-11-08-full-run.md. |
In one line: ARX is level with hand-written SQL for single-row writes and for filtered, joined and 100,000-row reads, 1.13–1.18× it for a row by id, 1,000 rows and deep pages, and faster and lighter than EF Core almost everywhere. For many-row writes it was 0.81–1.33× the fastest hand-written Npgsql form measured here, and faster than the usual hand-written many-row write (part of that gap is this machine's large-command stall, see the caveat below). As a product it's a preview: all five providers are built on the shared model and pass the shared conformance suite.
Dapper's one-statement insert, measured. A Dapper user who knows PostgreSQL inserts many rows with one unnest
statement, one array per column. At 10,000 rows that took 109 ms against ARX's 122 ms (0.90×: Dapper is faster, and the
hand-written unnest with ARX's own row order took 112 ms). At 1,000 rows it took 38 ms against ARX's 24 ms, but every
hand-written unnest form sat near this machine's ~50 ms large-command stall there, so read that row with the caveat,
not as ARX being faster. ARX spends its extra time checking and converting each row before the call.
Read the ratios, not the absolute times, which depend on the machine. Differences under about 10% on a single run are inside the noise here. See also the caveat on large commands.
Every operation at a glance (full run, 2026-11-11)
Mean times. "Usual" is the hand-written form most code uses; "best" is the fastest hand-written form found.
| Operation | ARX | Raw Npgsql | Dapper | EF Core | ARX vs raw |
|---|---|---|---|---|---|
| Create, one row | 1.14 ms | 1.19 ms | 1.13–1.16 ms | 1.92–2.00 ms | level |
| CreateMultiple, 1,000 rows, ids back | 23.8 ms | usual 64.9 ms, unnest 47.5 ms |
one unnest statement: 38.3 ms; one statement per row (no ids): 1.09 s |
171 ms | not comparable on this machine: both hand-written rows sit near the large-command stall below, so this row doesn't show ARX faster (at 10,000 rows, 1.09× the best) |
| CreateMultiple, 10,000 rows | 122 ms | usual 256 ms, best 112 ms | one unnest statement: 109 ms; one statement per row (no ids): 11.0 s |
1.14–1.62 s | 1.09× best; 2.1× faster than usual |
| Update, one row | 1.20 ms | 1.19 ms | 1.29 ms | 1.45–1.89 ms | level |
| UpdateMultiple, 1,000 rows | 45.8 ms | usual 63.6 ms, best 41.0 ms | 1.14 s | 170 ms | 1.12× best; 1.4× faster than usual |
| UpdateMultiple, 10,000 rows | 184 ms | usual 331 ms, best 163 ms | 11.1 s | 1.71 s | 1.13× best; 1.8× faster than usual |
| Delete, one row | 1.06 ms | 1.19 ms | 1.07 ms | 1.34–1.68 ms | level |
| DeleteMultiple, 10,000 ids | 51.2 ms | IN 67.1 ms, = ANY 51.7 ms |
44.8 ms | 69.4 ms | level with best |
| DeleteMultiple, 100,000 ids | 143 ms | IN 256 ms, = ANY 161 ms |
139 ms | 178 ms | 0.89× best |
| Retrieve, one row by id | 828 µs | 709–723 µs | 761–828 µs | 1,046–1,125 µs | 1.15× |
| RetrieveMultiple, 1,000 rows | 3.96 ms | 3.43–3.46 ms | 3.18–3.29 ms | 4.26 ms | 1.15× |
| RetrieveMultiple, 100,000 rows | 242 ms | typed 255 ms, dictionaries 280 ms | 245–248 ms | 264 ms | 0.95× typed, 0.86× dictionaries |
| In list of 1,000 ids (of 100,000) | 6.00 ms | 5.93 ms | 5.79 ms | 7.19 ms | 1.01× |
| Nested AND/OR | 14.1 ms | 14.3 ms | 14.1 ms | 14.9 ms | 0.99× |
| Contains, case-insensitive | 76.0 ms | 72.4 ms | 73.0 ms | 75.2 ms | 1.05× |
| Page of 50, page 1 | 0.88 ms | 0.86 ms | – | 1.07 ms | 1.03× |
| Page of 50, page 1,000 + total | 25.5 ms | 21.6 ms | – | 30.0 ms | 1.18× |
| 1,000 rows with a joined name | 2.91 ms | 2.90 ms | 2.85 ms | – | level |
| Complex: 7-table join, page | 50.6 ms | 52.2 ms | 48.3 ms | 47.3 ms | 0.97× |
| Complex: report, 7 aggregates | 195 ms | 205 ms | 189 ms | 568 ms | 0.95× |
| Complex: search with an existence join | 9.35 ms | 9.88 ms | 9.33 ms | 5.48 ms (EXISTS) |
0.95× |
| Execute: a procedure with OUT values | 640 µs | 594–632 µs | 708 µs | no way to read OUT values | level |
| Execute: a function's 10,000 rows | 15.8 ms | 17.8 ms | 15.4 ms | 14.8 ms | 0.89× |
| Execute: a procedure's two tables (cursors) | 1.60 ms | 1.82 ms | – | – | 0.88× |
| Execute: a page of 50 of 100,000 + total, the routine paging itself | 6.5–10.4 ms | 7.0–10.8 ms | – | – | level |
Did the injection check cost anything?
No measurable cost (security-ab). The six write classes, run on the code
without the injection check and with it (commits fa6ba08 and fa54ee3), one after
the other:
- ARX's times moved by a median of +0.4%, and the code the check doesn't touch (raw, Dapper, EF Core) by +0.0%, both within the same −18% to +34% run-to-run spread.
- ARX's memory per call changed by at most 0.05 KB on single-row calls: allocations are exact, so this is the precise measure, and it says the normal path didn't change.
- Why: a valid name takes the same path as before. The check runs only on a name that has already failed validation, to choose ARX1017 over ARX1003.
Reads
From the full run.
One row and many rows
| Rows | Raw typed (ceiling) | Raw dictionaries (ARX's shape) | ARX | Dapper POCO / dynamic | EF Core AsNoTracking |
|---|---|---|---|---|---|
| 1 by id | 709 µs, 2.8 KB | 723 µs, 3.3 KB | 828 µs, 7.0 KB | 828 / 761 µs | 1,046 µs, 41.7 KB |
| 100 | 0.96 ms | 1.14 ms | 1.03 ms | 0.99 / 1.00 ms | 1.73 ms |
| 1,000 | 3.43 ms, 0.20 MB | 3.46 ms, 0.73 MB | 3.96 ms, 0.61 MB | 3.29 / 3.18 ms | 4.26 ms, 0.42 MB |
| 10,000 | 26.4 ms | 32.8 ms | 28.8 ms | 26.1 / 28.7 ms | 30.3 ms |
| 100,000 | 255 ms, 20 MB | 280 ms, 73 MB | 242 ms, 59 MB | 248 / 245 ms | 264 ms, 38 MB |
- One row: about 0.1 ms over raw Npgsql (1.15×), 1.26× faster than EF Core; Dapper's dynamic rows were 8% faster.
- Many rows: 0.86–1.14× the hand-written read into dictionaries (faster from 10,000 rows), with less memory; 0.95–1.16× the typed ceiling.
- Memory: an
ArxEntityper row is about 3× a typed row, less than a dictionary per row.
Queries
| Query | Raw Npgsql | ARX | Dapper | EF Core |
|---|---|---|---|---|
| In list of 1,000 ids | 5.93 ms | 6.00 ms | 5.79 ms | 7.19 ms |
| Nested AND/OR (499 rows) | 14.3 ms | 14.1 ms | 14.1 ms | 14.9 ms |
| Contains '99', case-insensitive | 72.4 ms | 76.0 ms | 73.0 ms | 75.2 ms |
| Page 1 of 50 | 0.86 ms | 0.88 ms | – | 1.07 ms |
| Page 1,000 of 50 | 11.9 ms | 13.4 ms | – | 12.1 ms |
| Page 1 of 50 + total | 6.70 ms | 6.64 ms | – | 10.1 ms |
| Page 1,000 of 50 + total | 21.6 ms | 25.5 ms | – | 30.0 ms |
| 1,000 rows, LEFT JOIN for a name | 2.90 ms | 2.91 ms (link entity), 2.93 ms (_lk), 2.96 ms (declared lookup + display name) |
2.85 ms | – |
- Every query is 0.99–1.05× raw Npgsql, except the deep pages (page 1,000: 1.13× and 1.18×, against 0.96–1.02× in the 2026-11-08 run; not investigated yet): building the SQL, validating every name and making every value a parameter doesn't show next to the database's work.
- The total is opt-in: a page with the total took 6.6 ms against 0.9 ms without it (counting 100,000 rows). ARX
sends both statements in one round trip; EF Core needs two.
Advanced7_PagingInDepthshows when to leave it off.
Complex queries
ArxQueryExpression in depth on seven joined tables (100,000 order lines). ARX's rows, values and order are checked
against the raw SQL by --verify first.
| Shape | Raw Npgsql | Dapper | EF Core | ARX |
|---|---|---|---|---|
| Deep join (7 tables, 17 columns, criteria in the joins, nested AND/OR across aliases, 3-table order), page 1 of 100 | 52.2 ms | 48.3 ms | 47.3 ms | 50.6 ms |
| The same, page 20 + total | 89.3 ms | 90.2 ms | 87.5 ms | 90.5 ms |
| The same, every matching row (3,423) | 65.6 ms, 4.1 MB | 65.5 ms, 2.7 MB | 72.5 ms, 2.8 MB | 61.5 ms, 3.3 MB |
| Report: 7 aggregates over 5 tables, grouped by 2 linked columns | 205 ms | 189 ms | 568 ms | 195 ms |
Search: nested OR groups, In, NotIn, Between, Contains, IS NULL, a link with its own nested OR, Distinct, _lk, Top 500 |
9.88 ms | 9.33 ms | 5.48 ms | 9.35 ms |
- ARX is level with hand-written SQL on every shape (0.94–1.01×, inside the noise).
- EF Core's report took 2.8× for the same result; not investigated.
- EF Core's search was fastest (0.55×):
Any()becomesEXISTS, which stops at the first matching order. ARX, like the hand-written join, reads every matching order and removes duplicates: it has no "exists" link yet. - The report groups by two link columns that its links also read. This run is the first since that was fixed: the preview.4 read engine refused it (ARX1004).
Execute
Procedures and functions, from the full run.
| Call | Raw Npgsql | Dapper | EF Core | ARX |
|---|---|---|---|---|
| A procedure, 2 IN and 2 OUT values | 594–632 µs | 708 µs | – | 640 µs |
| A function's value | 580 µs | 572 µs | 880 µs | 692 µs |
| A function's 1,000 rows | 1.96 ms | 1.84 ms | 2.66 ms | 2.03 ms |
| A function's 10,000 rows | 17.8 ms | 15.4 ms | 14.8 ms | 15.8 ms |
| A procedure's two tables | 1.82 ms (3 round trips) | – | – | 1.60 ms (2) |
| 100 calls in one transaction | 63.6 ms | – | – | 55.3 ms, 56.0 ms in a scope with savepoints (102.8 ms each on its own) |
Paging a page of 50 out of 100,000 rows with the total (page 1 / page 1,000), each way against raw Npgsql doing the same:
| Way | Raw | ARX |
|---|---|---|
| The routine pages itself | 7.0 / 10.8 ms | 6.5 / 10.4 ms |
| ARX pages a SQL function | 23.8 / 32.2 ms | 23.9 / 32.2 ms |
| ARX pages a PL/pgSQL function | 76.8 / 95.6 ms | 79.2 / 97.8 ms |
| ARX pages a cursor | 10.6 / 10.2 ms | 9.8 / 10.1 ms |
- Level with the hand-written call (0.87–1.08×; a function's single value 1.19×, about 0.1 ms). EF Core has no way to read a procedure's OUT values.
- The way of paging matters far more than the library: 6.5 ms when the routine pages itself, 24 ms when ARX pages a SQL function (the total counts every row), 79–98 ms for a PL/pgSQL function (it produces every row first).
Preloaded schema
What preloading the schema at service setup changes (full run).
| Measured | Declared by hand | Preloaded, DataTypes | Strict |
|---|---|---|---|
| Building the schema, once at startup | 2.2 µs | 13.0 ms (KeysOnly 14.2 ms; from saved JSON 20 µs) | – |
| First read of 100 rows with an enum, new service | 2.39 ms | 0.93 ms | – |
| 100 rows with an enum, same service | 0.92 ms | 0.89 ms | 0.91 ms |
| Create one row | 1.28 ms | 1.41 ms (KeysOnly 1.25 ms) | 1.24 ms |
- The first read of enum columns is 2.6× faster preloaded: no failed first attempt. Once per statement shape per service.
- Steady state: no measurable difference, Strict included (the Create rows are 1.21–1.41 ms, raw Npgsql 1.21 ms: inside the noise). Don't claim a preload makes calls faster: it resolves types at setup and refuses wrong values before the database.
Writes
Single record
| Operation | ARX | Raw Npgsql | Dapper | EF Core |
|---|---|---|---|---|
| Create (10 columns, returns the id) | 1.14 ms, 12.7 KB | 1.19 ms, 4.2 KB | 1.13–1.16 ms | 1.92–2.00 ms, 54–62 KB |
| Create with a selection set | 1.14 ms | 1.09 ms | – | – |
| Update by id (10 columns) | 1.20 ms, 16.5 KB | 1.19 ms, 4.5 KB | 1.29 ms | 1.45–1.89 ms, 55–64 KB |
| Delete by id | 1.06 ms, 5.1 KB | 1.19 ms, 2.2 KB | 1.07 ms | 1.34–1.68 ms, 41–45 KB |
All within the noise of raw Npgsql and Dapper (±0.1–0.3 ms on this machine); EF Core takes 1.2–1.8× as long.
Many records
| Rows | Raw multi-row VALUES (usual) | Raw unnest (best) |
ARX | EF Core typed |
|---|---|---|---|---|
| CreateMultiple, 10 | 1.60 ms | 1.74 ms | 1.41 ms | 4.60 ms |
| CreateMultiple, 100 | 3.51 ms | 2.51 ms | 3.35 ms | 30.5 ms |
| CreateMultiple, 1,000 | 64.9 ms | 47.5 ms (the stall) | 23.8 ms | 172 ms |
| CreateMultiple, 10,000 | 256 ms | 112 ms | 122 ms | 1,138 ms |
| UpdateMultiple, 100 | 3.74 ms | 2.42 ms | 2.92 ms | 18.1 ms |
| UpdateMultiple, 1,000 | 63.6 ms | 41.0 ms | 45.8 ms | 170 ms |
| UpdateMultiple, 10,000 | 331 ms | 163 ms | 184 ms | 1,708 ms |
| DeleteMultiple, 1,000 ids | IN 21.4 ms |
= ANY 4.27 ms |
4.79 ms | 11.7 ms |
| DeleteMultiple, 100,000 ids | IN 256 ms |
= ANY 161 ms |
143 ms | 178 ms |
- Against the usual hand-written SQL: level at 10 rows, then 1.05–2.7× faster.
- Against the best hand-written SQL: 0.81–1.33× (leaving out the 1,000-row create, where the hand-written form hit the stall).
- Against EF Core: 3.3–9.3× faster for many-row creates and updates; 1.2–2.4× for DeleteMultiple (both send one statement).
- Against Dapper:
ExecuteAsync(sql, list)runs one statement per row: 1.09 s for 1,000 creates and 11.1 s for 10,000 updates, against ARX's 24 ms and 184 ms. Dapper's oneunneststatement: 38.3 ms at 1,000 rows and 109 ms at 10,000 (0.90× ARX). - ARX's UpdateMultiple and DeleteMultiple also prove inside the statement that every entity found its row; none of the others does.
Very large loads
5,000,000 values per load, ids returned. From the full run.
| Shape | Raw multi-row VALUES | Raw unnest |
ARX | ARX ÷ unnest | Binary COPY (no ids) |
|---|---|---|---|---|---|
| 10 columns × 500,000 rows | 11.3 s | 4.03 s | 5.33 s | 1.32× | 1.67 s |
| 50 × 100,000 | 12.1 s | 2.60 s | 3.27 s | 1.26× | 0.93 s |
| 100 × 50,000 | 12.5 s | 2.37 s | 3.09 s | 1.30× | 0.87 s |
| 250 × 20,000 | 13.0 s | 2.11 s | 2.81 s | 1.33× | 0.75 s |
| 500 × 10,000 | 12.3 s | 2.14 s | 2.87 s | 1.34× | 0.74 s |
| 1,000 × 5,000 | 19.6 s | 3.17 s | 3.34 s | 1.05× | 0.88 s |
| 1,599 × 3,126 (PostgreSQL's maximum) | 13.2 s | 2.82 s | 3.25 s | 1.15× | 0.94 s |
- ARX is 2.1–5.9× faster than multi-row VALUES and 1.05–1.34× the best hand-written code (1.25–1.58× on 2026-11-08; each shape is 3 single-operation iterations, so a single slow iteration moves it).
- Binary
COPYis 3.2–3.9× faster than ARX but can't return ids. ARX has no COPY path yet.
Batch scopes, and mixed row shapes
From the full run, default write buffer (the 50-per-batch raw rows hit the large-command stall, ~5 s, so compare the 500 and 5,000 columns):
| Approach, 5,000 rows | 500 per batch | 5,000 |
|---|---|---|
ARX RunBatchAsync, savepoints off (the default) |
467 ms | 111 ms |
ARX RunBatchAsync, savepoints on |
427 ms | 129 ms |
| ARX, one call of all 5,000 rows | 127 ms | 107 ms |
| Raw: one transaction, multi-row INSERT per batch | 501 ms | 140 ms |
EF Core: BeginTransaction, SaveChanges per batch |
615 ms | 654 ms |
At 500 per batch the scope's commands share one connection and also hit the large-command stall: the same batches
without a scope, each on its own connection, took 159 ms. The 1 MB-buffer run of 2026-11-07, which avoids the stall, put
a scope at 0.4–0.85× the hand-written transaction (results/2026-11-07-create-multiple-batch-scope-write-buffer-1mb.md).
Rows that differ in attributes or attribute order can't share one unnest statement: 1,000 such rows take 80–111 ms
and 3.7–5.8 MB, against 64 ms and 0.6 MB for rows of one shape.
Without a catalog
A service created without a catalog resolves each table it writes or reads by id from the database
(Preload/NoCatalogBenchmarks, full run).
| Operation | With a catalog | Re-read (default) | Remembered |
|---|---|---|---|
| Create one row | 1.18 ms | 8.81 ms (7.4×) | 1.21 ms (1.02×) |
| CreateMultiple, 100 rows | 3.45 ms | 10.34 ms (3.0×) | 3.61 ms (1.04×) |
| Update one row by id | 1.09 ms | 8.89 ms (8.2×) | 1.09 ms (1.00×) |
| Retrieve one row by id | 0.74 ms | 7.99 ms (10.7×) | 0.80 ms (1.08×) |
- Re-reading is one more round trip per call, about 7–8 ms here (11–12 ms on 2026-11-10). Remembered calls are level with a catalog. For anything past simple CRUD in a small app, declare the catalog or preload it.
Memory
Bytes allocated per operation, full run.
| Operation | ARX | Raw best | Raw usual | Dapper | EF Core |
|---|---|---|---|---|---|
| Create one | 12.7 KB | – | 4.2 KB | 6.1–8.7 KB | 54–62 KB |
| CreateMultiple 1,000 / 10,000 | 0.58 / 5.7 MB | 0.15 / 1.5 MB | 2.4 / 24.6 MB | one unnest: 0.18 / 1.9 MB |
14.8 / 139 MB |
| UpdateMultiple 10,000 | 6.6 MB | 1.5 MB | 42.1 MB | 37.5 MB | 150 MB |
| DeleteMultiple 100,000 ids | 5.1 KB | 2.1 KB | 25.4 MB | 3.0 KB | 1.6 MB |
| Retrieve one | 7.0 KB | 2.8 KB (typed) | 3.3 KB (dictionary) | 3.9 KB | 41.7 KB |
| RetrieveMultiple 100,000 | 59 MB | 20 MB (typed) | 73 MB (dictionaries) | 42–45 MB | 38 MB |
- Far below EF Core and the usual hand-written SQL for writes; 2.4–4.4× the best hand-written code.
- CreateMultiple allocates more per row than in the earliest runs (590 KB for 1,000 rows, was 442–472 KB before the injection check came in): cause not yet found.
Where ARX stands
The speed and memory ratings are measured. The rest are assessments.
| Area | Rating | Notes | Basis |
|---|---|---|---|
| Write speed | Good | Single rows level with hand-written SQL. Many rows: 0.81–1.33× the fastest hand-written Npgsql form measured here, faster than the usual hand-written form and far faster than EF Core. Dapper's one unnest statement is 0.90× ARX at 10,000 rows (ARX checks and converts each row first) |
Measured |
| Execute speed | Strong | Level with hand-written calls for procedures, functions, cursors and every way of paging; EF Core can't read a procedure's OUT values | Measured |
| Read speed | Strong | Level with hand-written SQL into the same shape for filters, joins, complex 7-table queries and 100,000 rows; 1.15× for one row by id and for 1,000 rows, deep pages 1.13–1.18× in this run. One gap: no "exists" link | Measured |
| Memory | Good | Far below EF Core and the usual hand-written writes; reads lighter than a dictionary per row; 2.4–4.4× the best hand-written writes | Measured |
| Security cost | None measured | The injection check didn't move time or memory | Measured (A/B) |
| Learning curve | Low for basics | A create or a read is a few lines, with no model classes, mappings or SQL text. Attribute names are strings, so a typo is found at runtime, not at compile time | Assessment |
| Safety | Strong | Values are always parameters and names are validated in every operation, on every provider; SQL in a name is ARX1017. Stable ARX error codes. Updates and deletes are all or nothing. 1,211 PostgreSQL tests (on Npgsql 8.0.3 and 10.0.3), 333 core tests, and a shared conformance suite on every provider | Tests |
| Provider independence | Delivered, with documented differences | PostgreSQL, SQL Server, MySQL, MongoDB and DynamoDB run the same model, and every provider passes the shared conformance suite. What a provider can't do is refused with ARX8001 (see the Capabilities page); some comparisons still behave differently per database (case, nulls, ordering), so test a query on each database you move it to | Code state, conformance suite |
| Production readiness | Preview | Every provider is on nuget.org as 0.1.0-preview, with CI on every change. The API can still change before 1.0 | Releases, CI |
Caveat: large commands on this machine
On this machine, any command larger than Npgsql's 8 KB write buffer, sent on a reused connection, waits about 50 ms per round trip. That's most likely Docker Desktop's port forwarding; the cause isn't confirmed.
- Who it affects: the raw binary COPY rows at 1–1,000 rows (~50 ms), the raw batch-scope rows at 50 per batch
(~5 s), and hand-written multi-row VALUES at 50–1,000 rows (sooner than ARX's
unneststatements, so some ratios there may favour ARX). - Who it doesn't: the 5M-value loads, and the reads.
- Workaround: setting
ARX_BENCH_WRITE_BUFFER=1048576gives every approach a 1 MB buffer.
The reports
BenchmarkDotNet's own output for the runs the summary cites, as committed: every number above comes from one of these.
2026-11-11: full run
Full run, every operation (2026-11-11)
All 26 benchmark classes (454 benchmarks) in one run (--filter '*', 1 h 32 min), at commit 9f8dc1f
(0.1.0-preview.5 in preparation), after --verify passed. Every approach runs on Npgsql 10.0.3, and EF Core is
EF Core 10 (Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3); the 2026-11-08 run used Npgsql 8.0.3 and EF Core 8. New in
this run: Dapper's one-statement unnest insert in CreateMultiple. The batch-scope benchmarks that measure savepoints ask
for them (they are off by default from preview.5). The summary of these numbers is SUMMARY.md. The
large-command caveat applies: rows near 50 ms per round trip on a reused
connection are that stall, not the cost of the approach. Update.UpdateBenchmarks was run again on its own after
the full run: in the full run every approach in that class was about twice as slow as before, ARX with a spread of
±8 ms (the machine, not the code); the table is the rerun's.
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2), Intel Core i7-8750H 2.20GHz, 6 cores / 12 threads
.NET SDK 10.0.403, .NET 10.0.14 X64 RyuJIT x86-64-v3; PostgreSQL 16 (postgres:16-alpine) in Docker Desktop; Npgsql 10.0.3
Standard = 3 warmups, 8 iterations; LargeLoad = 1 warmup, 3 single-operation iterations; SingleOperation = 1 warmup, 12
Create.CreateBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed, $n)' | Create (10 columns, returns id) | 1.191 ms | 0.1974 ms | 0.0876 ms | 1.00 | 0.10 | - | 4.16 KB | 1.00 |
| 'ARX CreateAsync' | Create (10 columns, returns id) | 1.140 ms | 0.0667 ms | 0.0296 ms | 0.96 | 0.07 | 1.9531 | 12.71 KB | 3.05 |
| 'Dapper (POCO)' | Create (10 columns, returns id) | 1.159 ms | 0.1819 ms | 0.0951 ms | 0.98 | 0.10 | - | 6.07 KB | 1.46 |
| 'Dapper (dynamic: DynamicParameters)' | Create (10 columns, returns id) | 1.129 ms | 0.0904 ms | 0.0401 ms | 0.95 | 0.07 | - | 8.68 KB | 2.09 |
| 'EF Core (typed, new context)' | Create (10 columns, returns id) | 1.999 ms | 0.7879 ms | 0.4121 ms | 1.69 | 0.35 | 11.7188 | 54.08 KB | 12.99 |
| 'EF Core (property bag, new context)' | Create (10 columns, returns id) | 1.924 ms | 0.3359 ms | 0.1491 ms | 1.62 | 0.17 | 11.7188 | 62.23 KB | 14.95 |
| 'Raw Npgsql, option code written directly' | Create with selection set (11 columns) | 1.089 ms | 0.0697 ms | 0.0309 ms | 1.00 | 0.04 | - | 4.49 KB | 1.00 |
| 'ARX CreateAsync with ArxSelectionSetValue (catalog check)' | Create with selection set (11 columns) | 1.144 ms | 0.0948 ms | 0.0421 ms | 1.05 | 0.05 | 1.9531 | 13.57 KB | 3.02 |
Create.CreateMultipleBatchScopeBenchmarks
Job=SingleOperation InvocationCount=1 IterationCount=12
| Method | Categories | BatchSize | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw: one transaction, multi-row INSERT per batch' | Batch scope, 5,000 rows, every batch succeeds | 50 | 4,997.28 ms | 21.14 ms | 16.50 ms | 4,991.36 ms | 1.00 | 0.00 | 2000.0000 | - | - | 12.74 MB | 1.00 |
| 'Raw: one transaction, SAVEPOINT + INSERT + RELEASE per batch' | Batch scope, 5,000 rows, every batch succeeds | 50 | 4,997.72 ms | 37.90 ms | 29.59 ms | 4,995.08 ms | 1.00 | 0.01 | 2000.0000 | - | - | 12.76 MB | 1.00 |
| 'Raw: no transaction, each batch commits' | Batch scope, 5,000 rows, every batch succeeds | 50 | 268.54 ms | 46.64 ms | 36.41 ms | 258.19 ms | 0.05 | 0.01 | 2000.0000 | - | - | 12.76 MB | 1.00 |
| 'ARX: CreateMultipleAsync per batch, no scope (each commits)' | Batch scope, 5,000 rows, every batch succeeds | 50 | 276.67 ms | 35.11 ms | 27.42 ms | 280.52 ms | 0.06 | 0.01 | - | - | - | 4.34 MB | 0.34 |
| 'ARX: RunBatchAsync, savepoints off (default)' | Batch scope, 5,000 rows, every batch succeeds | 50 | 189.58 ms | 34.69 ms | 27.08 ms | 200.84 ms | 0.04 | 0.01 | - | - | - | 4.37 MB | 0.34 |
| 'ARX: RunBatchAsync, savepoints on' | Batch scope, 5,000 rows, every batch succeeds | 50 | 195.37 ms | 50.02 ms | 39.05 ms | 194.26 ms | 0.04 | 0.01 | - | - | - | 4.39 MB | 0.34 |
| 'ARX: one CreateMultipleAsync of all 5,000 rows' | Batch scope, 5,000 rows, every batch succeeds | 50 | 121.48 ms | 28.98 ms | 22.63 ms | 115.28 ms | 0.02 | 0.00 | - | - | - | 2.95 MB | 0.23 |
| 'EF Core: BeginTransaction, SaveChanges per batch' | Batch scope, 5,000 rows, every batch succeeds | 50 | 5,070.35 ms | 55.48 ms | 43.31 ms | 5,076.63 ms | 1.01 | 0.01 | 13000.0000 | 7000.0000 | - | 69.96 MB | 5.49 |
| 'Raw: one transaction, multi-row INSERT per batch' | Batch scope, 5,000 rows, every batch succeeds | 500 | 500.68 ms | 41.56 ms | 32.44 ms | 496.91 ms | 1.00 | 0.09 | 2000.0000 | 1000.0000 | - | 12 MB | 1.00 |
| 'Raw: one transaction, SAVEPOINT + INSERT + RELEASE per batch' | Batch scope, 5,000 rows, every batch succeeds | 500 | 492.35 ms | 40.89 ms | 31.93 ms | 477.97 ms | 0.99 | 0.09 | 2000.0000 | 1000.0000 | - | 12.01 MB | 1.00 |
| 'Raw: no transaction, each batch commits' | Batch scope, 5,000 rows, every batch succeeds | 500 | 443.29 ms | 119.22 ms | 93.08 ms | 429.92 ms | 0.89 | 0.19 | 2000.0000 | 1000.0000 | - | 12.01 MB | 1.00 |
| 'ARX: CreateMultipleAsync per batch, no scope (each commits)' | Batch scope, 5,000 rows, every batch succeeds | 500 | 159.41 ms | 141.82 ms | 110.73 ms | 103.42 ms | 0.32 | 0.21 | - | - | - | 2.97 MB | 0.25 |
| 'ARX: RunBatchAsync, savepoints off (default)' | Batch scope, 5,000 rows, every batch succeeds | 500 | 467.32 ms | 129.43 ms | 101.05 ms | 473.11 ms | 0.94 | 0.20 | - | - | - | 2.97 MB | 0.25 |
| 'ARX: RunBatchAsync, savepoints on' | Batch scope, 5,000 rows, every batch succeeds | 500 | 427.08 ms | 102.20 ms | 79.79 ms | 468.62 ms | 0.86 | 0.16 | - | - | - | 2.98 MB | 0.25 |
| 'ARX: one CreateMultipleAsync of all 5,000 rows' | Batch scope, 5,000 rows, every batch succeeds | 500 | 126.94 ms | 73.92 ms | 57.71 ms | 107.75 ms | 0.25 | 0.11 | - | - | - | 2.95 MB | 0.25 |
| 'EF Core: BeginTransaction, SaveChanges per batch' | Batch scope, 5,000 rows, every batch succeeds | 500 | 615.04 ms | 174.22 ms | 136.02 ms | 550.41 ms | 1.23 | 0.27 | 10000.0000 | 9000.0000 | - | 70.32 MB | 5.86 |
| 'Raw: one transaction, multi-row INSERT per batch' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 139.57 ms | 47.76 ms | 37.29 ms | 125.41 ms | 1.05 | 0.34 | 1000.0000 | - | - | 12.59 MB | 1.00 |
| 'Raw: one transaction, SAVEPOINT + INSERT + RELEASE per batch' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 144.51 ms | 30.64 ms | 23.92 ms | 138.46 ms | 1.09 | 0.28 | 1000.0000 | - | - | 12.59 MB | 1.00 |
| 'Raw: no transaction, each batch commits' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 142.28 ms | 24.87 ms | 19.42 ms | 144.21 ms | 1.07 | 0.25 | 1000.0000 | - | - | 12.59 MB | 1.00 |
| 'ARX: CreateMultipleAsync per batch, no scope (each commits)' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 118.26 ms | 31.43 ms | 24.54 ms | 114.24 ms | 0.89 | 0.25 | - | - | - | 2.95 MB | 0.23 |
| 'ARX: RunBatchAsync, savepoints off (default)' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 110.93 ms | 22.87 ms | 17.86 ms | 110.42 ms | 0.84 | 0.21 | - | - | - | 2.95 MB | 0.23 |
| 'ARX: RunBatchAsync, savepoints on' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 129.03 ms | 32.40 ms | 25.29 ms | 122.35 ms | 0.97 | 0.27 | - | - | - | 2.95 MB | 0.23 |
| 'ARX: one CreateMultipleAsync of all 5,000 rows' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 106.74 ms | 39.21 ms | 30.61 ms | 105.49 ms | 0.80 | 0.27 | - | - | - | 2.95 MB | 0.23 |
| 'EF Core: BeginTransaction, SaveChanges per batch' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 654.07 ms | 179.55 ms | 140.18 ms | 614.23 ms | 4.93 | 1.41 | 10000.0000 | 5000.0000 | 1000.0000 | 70.07 MB | 5.56 |
| 'Raw: savepoints, failed batch undone, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 4,994.48 ms | 31.74 ms | 24.78 ms | 4,986.03 ms | 1.00 | 0.01 | 2000.0000 | - | - | 12.77 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints on, failed batch caught, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 185.82 ms | 53.66 ms | 41.89 ms | 185.26 ms | 0.04 | 0.01 | - | - | - | 4.41 MB | 0.35 |
| 'Raw: no savepoints, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 4,030.52 ms | 36.02 ms | 28.12 ms | 4,032.56 ms | 0.81 | 0.01 | 2000.0000 | - | - | 10.34 MB | 0.81 |
| 'ARX: RunBatchAsync, savepoints off, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 157.21 ms | 26.20 ms | 20.46 ms | 163.60 ms | 0.03 | 0.00 | - | - | - | 3.59 MB | 0.28 |
| 'Raw: savepoints, failed batch undone, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 501.51 ms | 42.57 ms | 33.23 ms | 491.65 ms | 1.00 | 0.09 | 2000.0000 | 1000.0000 | - | 12.02 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints on, failed batch caught, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 448.49 ms | 101.18 ms | 78.99 ms | 476.23 ms | 0.90 | 0.16 | - | - | - | 2.97 MB | 0.25 |
| 'Raw: no savepoints, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 478.46 ms | 40.65 ms | 31.74 ms | 465.75 ms | 0.96 | 0.08 | 1000.0000 | - | - | 10.82 MB | 0.90 |
| 'ARX: RunBatchAsync, savepoints off, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 391.32 ms | 52.32 ms | 40.85 ms | 406.38 ms | 0.78 | 0.09 | - | - | - | 2.68 MB | 0.22 |
| 'Raw: savepoints, failed batch undone, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 170.44 ms | 60.80 ms | 47.47 ms | 161.20 ms | 1.07 | 0.39 | 1000.0000 | - | - | 12.6 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints on, failed batch caught, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 98.19 ms | 17.23 ms | 13.45 ms | 93.52 ms | 0.61 | 0.17 | - | - | - | 2.74 MB | 0.22 |
| 'Raw: no savepoints, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 118.95 ms | 23.45 ms | 18.31 ms | 111.36 ms | 0.74 | 0.21 | 1000.0000 | - | - | 12.61 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints off, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 86.77 ms | 39.00 ms | 30.45 ms | 96.30 ms | 0.54 | 0.23 | - | - | - | 2.75 MB | 0.22 |
Create.CreateMultipleBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw binary COPY' | CreateMultiple, ids not needed | 1 | 49.484 ms | 0.2064 ms | 0.0736 ms | 1.00 | 0.00 | - | - | - | 4.04 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 1 | 1.075 ms | 0.1102 ms | 0.0489 ms | 0.02 | 0.00 | - | - | - | 6.05 KB | 1.50 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 1 | 1.089 ms | 0.1212 ms | 0.0538 ms | 0.02 | 0.00 | - | - | - | 6.1 KB | 1.51 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 1 | 1.111 ms | 0.0794 ms | 0.0415 ms | 0.02 | 0.00 | 1.9531 | - | - | 13.22 KB | 3.28 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 10 | 50.159 ms | 1.5104 ms | 0.7900 ms | 1.00 | 0.02 | - | - | - | 4.43 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 10 | 1.456 ms | 0.3476 ms | 0.1818 ms | 0.03 | 0.00 | 5.8594 | - | - | 28.45 KB | 6.42 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 10 | 10.188 ms | 1.7372 ms | 0.7713 ms | 0.20 | 0.01 | - | - | - | 38.19 KB | 8.62 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 10 | 1.583 ms | 0.2556 ms | 0.1337 ms | 0.03 | 0.00 | 7.8125 | - | - | 40.8 KB | 9.21 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 100 | 53.036 ms | 4.6209 ms | 2.4168 ms | 1.00 | 0.06 | - | - | - | 8.62 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 100 | 3.729 ms | 0.5273 ms | 0.2758 ms | 0.07 | 0.01 | 46.8750 | 19.5313 | - | 259.54 KB | 30.11 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 100 | 122.600 ms | 19.3379 ms | 8.5862 ms | 2.32 | 0.18 | - | - | - | 359.54 KB | 41.71 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 100 | 2.600 ms | 0.2116 ms | 0.0940 ms | 0.05 | 0.00 | 15.6250 | - | - | 73.36 KB | 8.51 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 1000 | 50.923 ms | 1.6911 ms | 0.8845 ms | 1.00 | 0.02 | - | - | - | 50.95 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 1000 | 56.145 ms | 8.2695 ms | 4.3251 ms | 1.10 | 0.08 | 300.0000 | 200.0000 | - | 2450.96 KB | 48.10 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 1000 | 1,092.660 ms | 432.9896 ms | 192.2501 ms | 21.46 | 3.55 | - | - | - | 3573.4 KB | 70.13 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 1000 | 24.531 ms | 5.7800 ms | 3.0231 ms | 0.48 | 0.06 | 93.7500 | 31.2500 | - | 590.12 KB | 11.58 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 10000 | 66.844 ms | 7.8801 ms | 3.4988 ms | 1.00 | 0.07 | - | - | - | 473.08 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 10000 | 241.875 ms | 45.2567 ms | 23.6701 ms | 3.63 | 0.38 | 3000.0000 | 1500.0000 | - | 25066.2 KB | 52.98 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 10000 | 10,987.477 ms | 2,566.5535 ms | 1,342.3571 ms | 164.78 | 20.79 | 7000.0000 | - | - | 35706.21 KB | 75.48 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 10000 | 120.153 ms | 33.4587 ms | 14.8558 ms | 1.80 | 0.23 | 666.6667 | 333.3333 | - | 5819.58 KB | 12.30 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 1 | 1.304 ms | 0.3386 ms | 0.1771 ms | 1.02 | 0.19 | - | - | - | 5.91 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 1 | 1.398 ms | 0.0691 ms | 0.0361 ms | 1.09 | 0.15 | 1.9531 | - | - | 9.91 KB | 1.68 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 1 | 1.102 ms | 0.0349 ms | 0.0124 ms | 0.86 | 0.12 | - | - | - | 4.13 KB | 0.70 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 1 | 1.149 ms | 0.1387 ms | 0.0725 ms | 0.90 | 0.13 | 1.9531 | - | - | 13.25 KB | 2.24 |
| 'Dapper one unnest statement ... RETURNING id' | CreateMultiple, returns ids | 1 | 1.599 ms | 0.3107 ms | 0.1625 ms | 1.25 | 0.21 | - | - | - | 8.19 KB | 1.38 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 1 | 1.944 ms | 0.5124 ms | 0.2275 ms | 1.52 | 0.26 | 11.7188 | - | - | 54 KB | 9.14 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 1 | 2.185 ms | 1.0021 ms | 0.5241 ms | 1.70 | 0.45 | 11.7188 | - | - | 62.2 KB | 10.52 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 10 | 1.604 ms | 0.2791 ms | 0.1460 ms | 1.01 | 0.12 | 5.8594 | - | - | 28.39 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 10 | 1.741 ms | 0.2401 ms | 0.1256 ms | 1.09 | 0.12 | 1.9531 | - | - | 11.14 KB | 0.39 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 10 | 2.846 ms | 1.2140 ms | 0.5390 ms | 1.79 | 0.35 | 3.9063 | - | - | 25.62 KB | 0.90 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 10 | 1.414 ms | 0.1332 ms | 0.0591 ms | 0.89 | 0.08 | 7.8125 | - | - | 40.83 KB | 1.44 |
| 'Dapper one unnest statement ... RETURNING id' | CreateMultiple, returns ids | 10 | 1.413 ms | 0.1202 ms | 0.0534 ms | 0.89 | 0.08 | 1.9531 | - | - | 9.88 KB | 0.35 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 10 | 4.596 ms | 2.3647 ms | 1.2368 ms | 2.89 | 0.78 | 39.0625 | 7.8125 | - | 190.59 KB | 6.71 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 10 | 3.544 ms | 0.7319 ms | 0.3828 ms | 2.23 | 0.30 | 39.0625 | 7.8125 | - | 210.24 KB | 7.41 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 100 | 3.508 ms | 0.2791 ms | 0.1239 ms | 1.00 | 0.05 | 46.8750 | 19.5313 | - | 260.24 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 100 | 2.511 ms | 0.4652 ms | 0.2433 ms | 0.72 | 0.07 | 3.9063 | - | - | 24.27 KB | 0.09 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 100 | 9.687 ms | 1.6514 ms | 0.7332 ms | 2.76 | 0.22 | 46.8750 | 15.6250 | - | 242.55 KB | 0.93 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 100 | 3.348 ms | 0.6255 ms | 0.3272 ms | 0.96 | 0.09 | 15.6250 | - | - | 73.34 KB | 0.28 |
| 'Dapper one unnest statement ... RETURNING id' | CreateMultiple, returns ids | 100 | 2.869 ms | 0.9610 ms | 0.5026 ms | 0.82 | 0.14 | 3.9063 | - | - | 26.14 KB | 0.10 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 100 | 30.473 ms | 10.0368 ms | 4.4564 ms | 8.70 | 1.22 | 250.0000 | 125.0000 | - | 1530.8 KB | 5.88 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 100 | 69.924 ms | 50.4598 ms | 26.3914 ms | 19.96 | 7.14 | 200.0000 | - | - | 1665.77 KB | 6.40 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 1000 | 64.859 ms | 11.3005 ms | 5.0175 ms | 1.01 | 0.11 | 333.3333 | 222.2222 | - | 2459 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 1000 | 47.521 ms | 8.8087 ms | 3.9111 ms | 0.74 | 0.08 | - | - | - | 157.08 KB | 0.06 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 1000 | 76.754 ms | 5.4887 ms | 2.4370 ms | 1.19 | 0.10 | 333.3333 | 166.6667 | - | 2406.64 KB | 0.98 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 1000 | 23.764 ms | 9.4436 ms | 4.9392 ms | 0.37 | 0.08 | 66.6667 | - | - | 589.53 KB | 0.24 |
| 'Dapper one unnest statement ... RETURNING id' | CreateMultiple, returns ids | 1000 | 38.251 ms | 13.5127 ms | 7.0674 ms | 0.59 | 0.11 | - | - | - | 186.68 KB | 0.08 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 1000 | 171.523 ms | 40.0289 ms | 17.7731 ms | 2.66 | 0.34 | 2333.3333 | 1333.3333 | 333.3333 | 15111.24 KB | 6.15 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 1000 | 170.785 ms | 68.8577 ms | 36.0139 ms | 2.65 | 0.57 | 2000.0000 | 1000.0000 | - | 16352.64 KB | 6.65 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 10000 | 256.220 ms | 49.6944 ms | 25.9911 ms | 1.01 | 0.13 | 3000.0000 | 1000.0000 | - | 25147.55 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 10000 | 112.382 ms | 19.7406 ms | 8.7650 ms | 0.44 | 0.05 | - | - | - | 1532.35 KB | 0.06 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 10000 | 701.606 ms | 24.8262 ms | 11.0230 ms | 2.76 | 0.26 | 3000.0000 | 1000.0000 | - | 24012.97 KB | 0.95 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 10000 | 121.996 ms | 19.0447 ms | 6.7915 ms | 0.48 | 0.05 | 666.6667 | 333.3333 | - | 5819.74 KB | 0.23 |
| 'Dapper one unnest statement ... RETURNING id' | CreateMultiple, returns ids | 10000 | 109.472 ms | 22.3192 ms | 9.9099 ms | 0.43 | 0.05 | - | - | - | 1941.86 KB | 0.08 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 10000 | 1,137.710 ms | 230.1081 ms | 120.3510 ms | 4.48 | 0.61 | 20000.0000 | 10000.0000 | 1000.0000 | 142770.55 KB | 5.68 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 10000 | 1,623.650 ms | 508.0857 ms | 265.7386 ms | 6.39 | 1.15 | 22000.0000 | 11000.0000 | 1000.0000 | 155435.18 KB | 6.18 |
Create.CreateMultipleMatrixBenchmarks
Job=LargeLoad InvocationCount=1 IterationCount=3
| Method | Shape | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw multi-row VALUES ... RETURNING id' | 1000c x 1000r | 4,137.209 ms | 10,601.783 ms | 581.1195 ms | 4,191.342 ms | 1.01 | 0.18 | 36000.0000 | 20000.0000 | 5000.0000 | 238587.63 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1000c x 1000r | 821.607 ms | 3,421.779 ms | 187.5592 ms | 768.375 ms | 0.20 | 0.05 | - | - | - | 4537.68 KB | 0.019 |
| 'ARX CreateMultipleAsync' | 1000c x 1000r | 986.880 ms | 8,454.003 ms | 463.3924 ms | 815.701 ms | 0.24 | 0.10 | 2000.0000 | 1000.0000 | - | 12588.16 KB | 0.053 |
| 'Raw binary COPY (no ids)' | 1000c x 1000r | 249.243 ms | 460.287 ms | 25.2299 ms | 243.147 ms | 0.06 | 0.01 | - | - | - | 312.75 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 1000c x 5000r | 19,576.136 ms | 68,208.191 ms | 3,738.7211 ms | 17,588.997 ms | 1.02 | 0.23 | 168000.0000 | 90000.0000 | 12000.0000 | 1192236.73 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1000c x 5000r | 3,172.075 ms | 5,826.387 ms | 319.3639 ms | 3,300.880 ms | 0.17 | 0.03 | 3000.0000 | 1000.0000 | - | 20475.41 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 1000c x 5000r | 3,336.641 ms | 4,751.494 ms | 260.4454 ms | 3,309.218 ms | 0.17 | 0.03 | 9000.0000 | 4000.0000 | - | 61599.09 KB | 0.052 |
| 'Raw binary COPY (no ids)' | 1000c x 5000r | 875.904 ms | 123.222 ms | 6.7542 ms | 878.021 ms | 0.05 | 0.01 | - | - | - | 333.89 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 10000r | 2,822.921 ms | 2,851.950 ms | 156.3250 ms | 2,903.633 ms | 1.00 | 0.07 | 33000.0000 | 17000.0000 | 2000.0000 | 237842.41 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 100c x 10000r | 558.860 ms | 2,765.765 ms | 151.6009 ms | 494.200 ms | 0.20 | 0.05 | - | - | - | 4083.88 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 100c x 10000r | 706.395 ms | 3,685.529 ms | 202.0163 ms | 598.966 ms | 0.25 | 0.06 | 2000.0000 | 1000.0000 | - | 14058.06 KB | 0.059 |
| 'Raw binary COPY (no ids)' | 100c x 10000r | 258.668 ms | 137.110 ms | 7.5155 ms | 256.674 ms | 0.09 | 0.01 | - | - | - | 34.3 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 1000r | 356.522 ms | 278.726 ms | 15.2779 ms | 354.725 ms | 1.00 | 0.05 | 4000.0000 | 2000.0000 | 1000.0000 | 23757.17 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 100c x 1000r | 114.021 ms | 20.095 ms | 1.1015 ms | 114.260 ms | 0.32 | 0.01 | - | - | - | 522 KB | 0.022 |
| 'ARX CreateMultipleAsync' | 100c x 1000r | 152.829 ms | 781.193 ms | 42.8198 ms | 159.027 ms | 0.43 | 0.11 | - | - | - | 1532.08 KB | 0.064 |
| 'Raw binary COPY (no ids)' | 100c x 1000r | 116.546 ms | 119.650 ms | 6.5584 ms | 118.943 ms | 0.33 | 0.02 | - | - | - | 31 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 50000r | 12,494.293 ms | 7,513.302 ms | 411.8294 ms | 12,495.628 ms | 1.00 | 0.04 | 158000.0000 | 80000.0000 | 2000.0000 | 1189612.81 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 100c x 50000r | 2,373.018 ms | 3,174.316 ms | 173.9949 ms | 2,300.925 ms | 0.19 | 0.01 | 3000.0000 | 2000.0000 | - | 19699.45 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 100c x 50000r | 3,090.978 ms | 3,926.110 ms | 215.2033 ms | 3,021.314 ms | 0.25 | 0.02 | 10000.0000 | 5000.0000 | - | 69406.73 KB | 0.058 |
| 'Raw binary COPY (no ids)' | 100c x 50000r | 870.442 ms | 1,683.133 ms | 92.2582 ms | 840.508 ms | 0.07 | 0.01 | - | - | - | 50.95 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 100000r | 2,266.242 ms | 2,679.252 ms | 146.8589 ms | 2,181.475 ms | 1.00 | 0.08 | 32000.0000 | 16000.0000 | 1000.0000 | 239351.88 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 100000r | 911.495 ms | 2,595.130 ms | 142.2478 ms | 885.113 ms | 0.40 | 0.06 | - | - | - | 6979.56 KB | 0.029 |
| 'ARX CreateMultipleAsync' | 10c x 100000r | 1,125.947 ms | 704.033 ms | 38.5904 ms | 1,133.367 ms | 0.50 | 0.03 | 4000.0000 | 2000.0000 | - | 36429.36 KB | 0.152 |
| 'Raw binary COPY (no ids)' | 10c x 100000r | 341.962 ms | 256.486 ms | 14.0588 ms | 334.342 ms | 0.15 | 0.01 | - | - | - | 11.3 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 10000r | 338.670 ms | 730.087 ms | 40.0185 ms | 355.445 ms | 1.01 | 0.15 | 4000.0000 | 2000.0000 | 1000.0000 | 23889.3 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 10000r | 123.192 ms | 46.751 ms | 2.5626 ms | 124.047 ms | 0.37 | 0.04 | - | - | - | 1226.5 KB | 0.051 |
| 'ARX CreateMultipleAsync' | 10c x 10000r | 161.667 ms | 313.908 ms | 17.2064 ms | 169.246 ms | 0.48 | 0.07 | - | - | - | 3694.88 KB | 0.155 |
| 'Raw binary COPY (no ids)' | 10c x 10000r | 123.275 ms | 268.670 ms | 14.7267 ms | 117.447 ms | 0.37 | 0.06 | - | - | - | 5.55 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 1000r | 68.259 ms | 103.827 ms | 5.6911 ms | 66.896 ms | 1.00 | 0.10 | - | - | - | 2385.7 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 1000r | 55.783 ms | 54.702 ms | 2.9984 ms | 54.772 ms | 0.82 | 0.07 | - | - | - | 124 KB | 0.052 |
| 'ARX CreateMultipleAsync' | 10c x 1000r | 66.009 ms | 91.572 ms | 5.0193 ms | 63.325 ms | 0.97 | 0.09 | - | - | - | 424.36 KB | 0.178 |
| 'Raw binary COPY (no ids)' | 10c x 1000r | 58.237 ms | 65.391 ms | 3.5843 ms | 56.178 ms | 0.86 | 0.08 | - | - | - | 5.04 KB | 0.002 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 500000r | 11,307.193 ms | 3,988.104 ms | 218.6015 ms | 11,308.742 ms | 1.00 | 0.02 | 158000.0000 | 79000.0000 | 1000.0000 | 1196823.01 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 500000r | 4,032.916 ms | 1,799.699 ms | 98.6476 ms | 4,085.342 ms | 0.36 | 0.01 | - | - | - | 30759.88 KB | 0.026 |
| 'ARX CreateMultipleAsync' | 10c x 500000r | 5,331.896 ms | 3,072.304 ms | 168.4034 ms | 5,335.220 ms | 0.47 | 0.02 | 21000.0000 | 10000.0000 | - | 178393.91 KB | 0.149 |
| 'Raw binary COPY (no ids)' | 10c x 500000r | 1,665.467 ms | 1,316.151 ms | 72.1427 ms | 1,638.911 ms | 0.15 | 0.01 | - | - | - | 39.12 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 1000r | 4,078.517 ms | 1,022.536 ms | 56.0487 ms | 4,080.969 ms | 1.00 | 0.02 | 53000.0000 | 28000.0000 | 3000.0000 | 382433.14 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1599c x 1000r | 891.988 ms | 968.368 ms | 53.0795 ms | 901.307 ms | 0.22 | 0.01 | 1000.0000 | - | - | 8233.02 KB | 0.022 |
| 'ARX CreateMultipleAsync' | 1599c x 1000r | 1,191.423 ms | 2,722.766 ms | 149.2440 ms | 1,145.434 ms | 0.29 | 0.03 | 3000.0000 | 1000.0000 | - | 21226.22 KB | 0.056 |
| 'Raw binary COPY (no ids)' | 1599c x 1000r | 328.074 ms | 116.529 ms | 6.3873 ms | 328.039 ms | 0.08 | 0.00 | - | - | - | 518.63 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 3126r | 13,172.907 ms | 4,749.025 ms | 260.3101 ms | 13,157.137 ms | 1.00 | 0.02 | 158000.0000 | 80000.0000 | 2000.0000 | 1195404.41 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1599c x 3126r | 2,821.757 ms | 4,527.643 ms | 248.1754 ms | 2,711.813 ms | 0.21 | 0.02 | 4000.0000 | 2000.0000 | - | 23349.7 KB | 0.020 |
| 'ARX CreateMultipleAsync' | 1599c x 3126r | 3,250.791 ms | 2,570.411 ms | 140.8929 ms | 3,213.499 ms | 0.25 | 0.01 | 10000.0000 | 5000.0000 | - | 65197.23 KB | 0.055 |
| 'Raw binary COPY (no ids)' | 1599c x 3126r | 935.865 ms | 1,449.785 ms | 79.4676 ms | 898.847 ms | 0.07 | 0.01 | - | - | - | 470.48 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 100000r | 608.742 ms | 2,024.569 ms | 110.9734 ms | 626.736 ms | 1.02 | 0.24 | 3000.0000 | 1000.0000 | - | 25322.02 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 100000r | 433.745 ms | 333.395 ms | 18.2745 ms | 440.364 ms | 0.73 | 0.12 | - | - | - | 1213.34 KB | 0.048 |
| 'ARX CreateMultipleAsync' | 1c x 100000r | 609.522 ms | 2,369.943 ms | 129.9046 ms | 600.355 ms | 1.03 | 0.26 | 3000.0000 | 1000.0000 | - | 23639.52 KB | 0.934 |
| 'Raw binary COPY (no ids)' | 1c x 100000r | 213.812 ms | 102.472 ms | 5.6168 ms | 215.726 ms | 0.36 | 0.06 | - | - | - | 2.14 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 10000r | 97.084 ms | 82.044 ms | 4.4971 ms | 99.592 ms | 1.00 | 0.06 | - | - | - | 2944.15 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 10000r | 85.017 ms | 127.504 ms | 6.9889 ms | 89.015 ms | 0.88 | 0.07 | - | - | - | 591.25 KB | 0.201 |
| 'ARX CreateMultipleAsync' | 1c x 10000r | 91.492 ms | 235.169 ms | 12.8904 ms | 85.710 ms | 0.94 | 0.12 | - | - | - | 2824.1 KB | 0.959 |
| 'Raw binary COPY (no ids)' | 1c x 10000r | 62.105 ms | 30.528 ms | 1.6734 ms | 62.985 ms | 0.64 | 0.03 | - | - | - | 2.45 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 1000r | 7.191 ms | 13.732 ms | 0.7527 ms | 6.925 ms | 1.01 | 0.13 | - | - | - | 309.29 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 1000r | 6.119 ms | 15.855 ms | 0.8690 ms | 5.951 ms | 0.86 | 0.13 | - | - | - | 63.36 KB | 0.205 |
| 'ARX CreateMultipleAsync' | 1c x 1000r | 8.899 ms | 27.665 ms | 1.5164 ms | 8.748 ms | 1.25 | 0.21 | - | - | - | 291.7 KB | 0.943 |
| 'Raw binary COPY (no ids)' | 1c x 1000r | 51.881 ms | 54.943 ms | 3.0116 ms | 50.193 ms | 7.27 | 0.73 | - | - | - | 2.45 KB | 0.008 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 500000r | 2,375.009 ms | 1,278.044 ms | 70.0539 ms | 2,409.327 ms | 1.00 | 0.04 | 16000.0000 | 8000.0000 | - | 127336.55 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 500000r | 1,803.301 ms | 2,352.070 ms | 128.9249 ms | 1,731.094 ms | 0.76 | 0.05 | - | - | - | 6050.57 KB | 0.048 |
| 'ARX CreateMultipleAsync' | 1c x 500000r | 2,171.501 ms | 1,480.480 ms | 81.1501 ms | 2,129.289 ms | 0.91 | 0.04 | 16000.0000 | 6000.0000 | - | 118501.8 KB | 0.931 |
| 'Raw binary COPY (no ids)' | 1c x 500000r | 901.789 ms | 197.539 ms | 10.8278 ms | 907.753 ms | 0.38 | 0.01 | - | - | - | 2.45 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 250c x 10000r | 6,357.644 ms | 3,563.382 ms | 195.3210 ms | 6,253.736 ms | 1.00 | 0.04 | 81000.0000 | 42000.0000 | 3000.0000 | 594816.84 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 250c x 10000r | 1,197.216 ms | 2,909.263 ms | 159.4665 ms | 1,121.369 ms | 0.19 | 0.02 | 1000.0000 | - | - | 9608.84 KB | 0.016 |
| 'ARX CreateMultipleAsync' | 250c x 10000r | 1,413.209 ms | 972.295 ms | 53.2948 ms | 1,411.886 ms | 0.22 | 0.01 | 5000.0000 | 2000.0000 | - | 31464.07 KB | 0.053 |
| 'Raw binary COPY (no ids)' | 250c x 10000r | 385.833 ms | 639.253 ms | 35.0396 ms | 380.637 ms | 0.06 | 0.01 | - | - | - | 65.72 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 250c x 1000r | 679.966 ms | 702.835 ms | 38.5247 ms | 663.029 ms | 1.00 | 0.07 | 8000.0000 | 4000.0000 | 1000.0000 | 59717.73 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 250c x 1000r | 256.175 ms | 944.029 ms | 51.7454 ms | 245.608 ms | 0.38 | 0.07 | - | - | - | 1092.81 KB | 0.018 |
| 'ARX CreateMultipleAsync' | 250c x 1000r | 384.097 ms | 2,519.384 ms | 138.0959 ms | 319.787 ms | 0.57 | 0.18 | - | - | - | 3315.77 KB | 0.056 |
| 'Raw binary COPY (no ids)' | 250c x 1000r | 229.368 ms | 1,174.444 ms | 64.3752 ms | 239.531 ms | 0.34 | 0.08 | - | - | - | 64.99 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 250c x 20000r | 13,049.044 ms | 16,356.369 ms | 896.5478 ms | 13,268.340 ms | 1.00 | 0.09 | 158000.0000 | 80000.0000 | 2000.0000 | 1189666.37 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 250c x 20000r | 2,110.696 ms | 2,117.489 ms | 116.0667 ms | 2,061.285 ms | 0.16 | 0.01 | 3000.0000 | 1000.0000 | - | 19050.84 KB | 0.016 |
| 'ARX CreateMultipleAsync' | 250c x 20000r | 2,807.023 ms | 1,099.796 ms | 60.2835 ms | 2,788.691 ms | 0.22 | 0.01 | 10000.0000 | 5000.0000 | - | 62724.72 KB | 0.053 |
| 'Raw binary COPY (no ids)' | 250c x 20000r | 754.177 ms | 380.585 ms | 20.8612 ms | 755.819 ms | 0.06 | 0.00 | - | - | - | 67.48 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 500c x 10000r | 12,342.883 ms | 6,783.175 ms | 371.8087 ms | 12,410.309 ms | 1.00 | 0.04 | 158000.0000 | 80000.0000 | 2000.0000 | 1190203.8 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 500c x 10000r | 2,136.359 ms | 2,162.448 ms | 118.5311 ms | 2,087.227 ms | 0.17 | 0.01 | 3000.0000 | 1000.0000 | - | 19517.81 KB | 0.016 |
| 'ARX CreateMultipleAsync' | 500c x 10000r | 2,868.026 ms | 2,565.075 ms | 140.6004 ms | 2,799.805 ms | 0.23 | 0.01 | 9000.0000 | 4000.0000 | - | 61231.47 KB | 0.051 |
| 'Raw binary COPY (no ids)' | 500c x 10000r | 738.543 ms | 756.872 ms | 41.4867 ms | 749.104 ms | 0.06 | 0.00 | - | - | - | 217.05 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 500c x 1000r | 1,218.165 ms | 135.563 ms | 7.4307 ms | 1,215.053 ms | 1.00 | 0.01 | 17000.0000 | 9000.0000 | 2000.0000 | 119471.33 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 500c x 1000r | 477.576 ms | 2,992.262 ms | 164.0160 ms | 464.828 ms | 0.39 | 0.12 | - | - | - | 2186.78 KB | 0.018 |
| 'ARX CreateMultipleAsync' | 500c x 1000r | 442.145 ms | 3,374.366 ms | 184.9604 ms | 382.051 ms | 0.36 | 0.13 | 1000.0000 | - | - | 6396.58 KB | 0.054 |
| 'Raw binary COPY (no ids)' | 500c x 1000r | 190.094 ms | 1,584.695 ms | 86.8625 ms | 159.430 ms | 0.16 | 0.06 | - | - | - | 141.48 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 50c x 100000r | 12,134.843 ms | 4,100.963 ms | 224.7876 ms | 12,243.322 ms | 1.00 | 0.02 | 156000.0000 | 78000.0000 | - | 1191241.37 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 50c x 100000r | 2,596.742 ms | 5,869.480 ms | 321.7260 ms | 2,455.547 ms | 0.21 | 0.02 | 1000.0000 | - | - | 19662.8 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 50c x 100000r | 3,274.851 ms | 3,736.585 ms | 204.8148 ms | 3,221.890 ms | 0.27 | 0.02 | 10000.0000 | 5000.0000 | - | 80440.23 KB | 0.068 |
| 'Raw binary COPY (no ids)' | 50c x 100000r | 928.450 ms | 2,648.616 ms | 145.1796 ms | 855.561 ms | 0.08 | 0.01 | - | - | - | 58.1 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 50c x 10000r | 1,243.108 ms | 372.781 ms | 20.4334 ms | 1,253.117 ms | 1.00 | 0.02 | 17000.0000 | 9000.0000 | 2000.0000 | 119572.84 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 50c x 10000r | 342.048 ms | 1,286.774 ms | 70.5324 ms | 327.974 ms | 0.28 | 0.05 | - | - | - | 1990.73 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 50c x 10000r | 481.128 ms | 3,252.353 ms | 178.2725 ms | 523.340 ms | 0.39 | 0.12 | 1000.0000 | - | - | 8062.88 KB | 0.067 |
| 'Raw binary COPY (no ids)' | 50c x 10000r | 175.736 ms | 1,953.614 ms | 107.0842 ms | 120.251 ms | 0.14 | 0.07 | - | - | - | 19.85 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 50c x 1000r | 145.563 ms | 414.176 ms | 22.7024 ms | 140.613 ms | 1.02 | 0.19 | 1000.0000 | - | - | 12257.41 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 50c x 1000r | 77.034 ms | 77.293 ms | 4.2367 ms | 78.069 ms | 0.54 | 0.07 | - | - | - | 277.39 KB | 0.023 |
| 'ARX CreateMultipleAsync' | 50c x 1000r | 65.730 ms | 450.089 ms | 24.6709 ms | 58.322 ms | 0.46 | 0.16 | - | - | - | 900.87 KB | 0.073 |
| 'Raw binary COPY (no ids)' | 50c x 1000r | 78.324 ms | 32.781 ms | 1.7968 ms | 78.360 ms | 0.55 | 0.07 | - | - | - | 14.67 KB | 0.001 |
Create.CreateMultipleSpecialCaseBenchmarks
Job=SingleOperation InvocationCount=1 IterationCount=12
| Method | Categories | Mean | Error | StdDev | Median | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw multi-row, text param ::jsonb' | JSONB column (1,000 rows, 11 columns) | 61.06 ms | 24.85 ms | 19.40 ms | 67.32 ms | 1.12 | 0.55 | 2872.57 KB | 1.00 |
| 'ARX, ArxJsonB' | JSONB column (1,000 rows, 11 columns) | 49.51 ms | 30.89 ms | 24.11 ms | 64.16 ms | 0.91 | 0.56 | 654.84 KB | 0.23 |
| 'Raw multi-row, all columns' | Row shapes (1,000 rows) | 59.27 ms | 31.06 ms | 24.25 ms | 66.69 ms | 1.33 | 1.08 | 2463.16 KB | 1.00 |
| 'ARX, same columns, same order (1 statement)' | Row shapes (1,000 rows) | 64.19 ms | 25.58 ms | 19.97 ms | 65.66 ms | 1.45 | 1.08 | 590.64 KB | 0.24 |
| 'ARX, same columns, shuffled order per row' | Row shapes (1,000 rows) | 98.66 ms | 21.90 ms | 17.09 ms | 95.69 ms | 2.22 | 1.53 | 5822.16 KB | 2.36 |
| 'ARX, two shapes alternating (10 / 9 columns)' | Row shapes (1,000 rows) | 110.72 ms | 32.06 ms | 25.03 ms | 104.04 ms | 2.49 | 1.76 | 5693.42 KB | 2.31 |
| 'ARX, random column subset per row' | Row shapes (1,000 rows) | 79.81 ms | 25.52 ms | 19.92 ms | 74.47 ms | 1.80 | 1.29 | 3652.45 KB | 1.48 |
| 'Raw multi-row, option codes written directly' | Selection sets (1,000 rows, 11 columns) | 75.92 ms | 13.94 ms | 10.88 ms | 78.98 ms | 1.02 | 0.20 | 2846.45 KB | 1.00 |
| 'ARX, 1 distinct option value' | Selection sets (1,000 rows, 11 columns) | 66.56 ms | 21.49 ms | 16.78 ms | 70.35 ms | 0.89 | 0.25 | 896.48 KB | 0.31 |
| 'ARX, 50 distinct option values' | Selection sets (1,000 rows, 11 columns) | 73.79 ms | 32.10 ms | 25.06 ms | 73.80 ms | 0.99 | 0.35 | 896.66 KB | 0.32 |
Create.CreateMultipleStatementSplitBenchmarks
Job=SingleOperation InvocationCount=1 IterationCount=12
| Method | Shape | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 655r | 177.28 ms | 48.46 ms | 37.83 ms | 1.04 | 0.28 | 2000.0000 | 1000.0000 | 15584.97 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 100c x 655r | 97.93 ms | 36.29 ms | 28.33 ms | 0.57 | 0.19 | - | - | 996.07 KB | 0.06 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 656r | 165.81 ms | 32.35 ms | 25.26 ms | 1.02 | 0.21 | 2000.0000 | 1000.0000 | 15612.43 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 100c x 656r | 102.11 ms | 23.01 ms | 17.96 ms | 0.63 | 0.14 | - | - | 996.62 KB | 0.06 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 6553r | 164.09 ms | 36.40 ms | 28.42 ms | 1.02 | 0.23 | 2000.0000 | 1000.0000 | 15688.19 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 10c x 6553r | 113.08 ms | 36.13 ms | 28.20 ms | 0.71 | 0.20 | - | - | 2266.84 KB | 0.14 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 6554r | 146.49 ms | 38.33 ms | 29.93 ms | 1.04 | 0.28 | 2000.0000 | 1000.0000 | 15692.39 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 10c x 6554r | 110.08 ms | 18.25 ms | 14.25 ms | 0.78 | 0.17 | - | - | 2266.25 KB | 0.14 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 40r | 160.76 ms | 21.35 ms | 16.67 ms | 1.01 | 0.14 | 2000.0000 | 1000.0000 | 15322.83 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 1599c x 40r | 127.49 ms | 27.63 ms | 21.57 ms | 0.80 | 0.15 | - | - | 2096.99 KB | 0.14 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 41r | 194.06 ms | 32.06 ms | 25.03 ms | 1.01 | 0.17 | 2000.0000 | 1000.0000 | 15765.74 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 1599c x 41r | 130.67 ms | 32.82 ms | 25.62 ms | 0.68 | 0.15 | - | - | 2121.88 KB | 0.13 |
Update.UpdateBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed, $n)' | Update by id (10 columns) | 1.188 ms | 0.1382 ms | 0.0723 ms | 1.00 | 0.08 | - | 4.47 KB | 1.00 |
| 'ARX UpdateAsync' | Update by id (10 columns) | 1.195 ms | 0.0673 ms | 0.0299 ms | 1.01 | 0.06 | 1.9531 | 16.51 KB | 3.69 |
| 'Dapper (POCO)' | Update by id (10 columns) | 1.289 ms | 0.1938 ms | 0.1013 ms | 1.09 | 0.10 | - | 6.39 KB | 1.43 |
| 'EF Core Attach + Modified + SaveChanges' | Update by id (10 columns) | 1.450 ms | 0.2092 ms | 0.0746 ms | 1.22 | 0.09 | 11.7188 | 54.85 KB | 12.27 |
| 'EF Core ExecuteUpdateAsync' | Update by id (10 columns) | 1.894 ms | 0.6674 ms | 0.3491 ms | 1.60 | 0.29 | 11.7188 | 64.29 KB | 14.38 |
| 'Raw Npgsql: SELECT then UPDATE' | Update, load then save (2 round trips) | 1.804 ms | 0.1176 ms | 0.0522 ms | 1.00 | 0.04 | - | 6.63 KB | 1.00 |
| 'EF Core tracked: Find, modify, SaveChanges' | Update, load then save (2 round trips) | 3.127 ms | 0.3848 ms | 0.2013 ms | 1.73 | 0.12 | 7.8125 | 56.83 KB | 8.57 |
Update.UpdateMultipleBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw UPDATE ... FROM (VALUES ...)' | 1 | 1.577 ms | 0.4273 ms | 0.2235 ms | 1.02 | 0.19 | - | - | - | 8.35 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 1 | 1.734 ms | 0.6384 ms | 0.3339 ms | 1.12 | 0.25 | 1.9531 | - | - | 9.85 KB | 1.18 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 1 | 1.173 ms | 0.0362 ms | 0.0129 ms | 0.76 | 0.10 | - | - | - | 4.55 KB | 0.55 |
| 'ARX UpdateMultipleAsync' | 1 | 1.234 ms | 0.1736 ms | 0.0908 ms | 0.80 | 0.12 | 1.9531 | - | - | 16.51 KB | 1.98 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 1 | 1.456 ms | 0.7040 ms | 0.3682 ms | 0.94 | 0.26 | - | - | - | 6.48 KB | 0.78 |
| 'EF Core AttachRange + Modified + SaveChanges' | 1 | 1.958 ms | 0.7213 ms | 0.3773 ms | 1.26 | 0.28 | 11.7188 | - | - | 54.79 KB | 6.56 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 10 | 2.191 ms | 0.2386 ms | 0.0851 ms | 1.00 | 0.05 | 7.8125 | - | - | 38.8 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 10 | 2.000 ms | 0.5180 ms | 0.2709 ms | 0.91 | 0.12 | - | - | - | 11.15 KB | 0.29 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 10 | 2.698 ms | 0.2176 ms | 0.1138 ms | 1.23 | 0.07 | 3.9063 | - | - | 29.09 KB | 0.75 |
| 'ARX UpdateMultipleAsync' | 10 | 2.158 ms | 0.1869 ms | 0.0978 ms | 0.99 | 0.06 | 3.9063 | - | - | 27.4 KB | 0.71 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 10 | 10.691 ms | 1.6171 ms | 0.7180 ms | 4.89 | 0.36 | - | - | - | 41.09 KB | 1.06 |
| 'EF Core AttachRange + Modified + SaveChanges' | 10 | 3.532 ms | 0.8681 ms | 0.4540 ms | 1.61 | 0.21 | 39.0625 | 7.8125 | - | 200.92 KB | 5.18 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 100 | 3.744 ms | 0.2001 ms | 0.0889 ms | 1.00 | 0.03 | 62.5000 | 46.8750 | - | 377.02 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 100 | 2.420 ms | 0.1797 ms | 0.0798 ms | 0.65 | 0.02 | 3.9063 | - | - | 24.25 KB | 0.06 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 100 | 13.404 ms | 2.4440 ms | 1.2783 ms | 3.58 | 0.33 | 46.8750 | 15.6250 | - | 276.22 KB | 0.73 |
| 'ARX UpdateMultipleAsync' | 100 | 2.916 ms | 0.2237 ms | 0.1170 ms | 0.78 | 0.03 | 15.6250 | - | - | 87.32 KB | 0.23 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 100 | 112.924 ms | 22.3441 ms | 11.6864 ms | 30.18 | 3.02 | - | - | - | 387.04 KB | 1.03 |
| 'EF Core AttachRange + Modified + SaveChanges' | 100 | 18.099 ms | 4.7133 ms | 2.0927 ms | 4.84 | 0.53 | 166.6667 | - | - | 1655.29 KB | 4.39 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 1000 | 63.556 ms | 11.2936 ms | 5.9068 ms | 1.01 | 0.13 | 625.0000 | 375.0000 | 125.0000 | 4000.92 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 1000 | 40.993 ms | 11.3848 ms | 5.9545 ms | 0.65 | 0.11 | - | - | - | 156.59 KB | 0.04 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 1000 | 123.953 ms | 17.2691 ms | 7.6676 ms | 1.97 | 0.22 | 250.0000 | - | - | 2740.73 KB | 0.69 |
| 'ARX UpdateMultipleAsync' | 1000 | 45.835 ms | 8.3496 ms | 3.7073 ms | 0.73 | 0.09 | 100.0000 | - | - | 683.56 KB | 0.17 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 1000 | 1,138.820 ms | 249.4344 ms | 130.4590 ms | 18.07 | 2.60 | - | - | - | 3846.71 KB | 0.96 |
| 'EF Core AttachRange + Modified + SaveChanges' | 1000 | 170.090 ms | 29.6545 ms | 13.1668 ms | 2.70 | 0.32 | 2000.0000 | 1000.0000 | - | 16408.65 KB | 4.10 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 10000 | 330.881 ms | 55.0108 ms | 28.7717 ms | 1.01 | 0.11 | 5000.0000 | 2000.0000 | - | 43090.96 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 10000 | 162.807 ms | 40.5476 ms | 21.2072 ms | 0.50 | 0.07 | - | - | - | 1550.74 KB | 0.04 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 10000 | 1,206.069 ms | 78.1667 ms | 40.8827 ms | 3.67 | 0.31 | 4000.0000 | 2000.0000 | - | 27353.89 KB | 0.63 |
| 'ARX UpdateMultipleAsync' | 10000 | 183.615 ms | 34.1087 ms | 17.8395 ms | 0.56 | 0.07 | 500.0000 | - | - | 6779.97 KB | 0.16 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 10000 | 11,082.026 ms | 752.1162 ms | 333.9443 ms | 33.71 | 2.83 | 8000.0000 | - | - | 38440.77 KB | 0.89 |
| 'EF Core AttachRange + Modified + SaveChanges' | 10000 | 1,708.374 ms | 162.0283 ms | 71.9416 ms | 5.20 | 0.46 | 22000.0000 | 11000.0000 | 1000.0000 | 153386.27 KB | 3.56 |
Delete.DeleteBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed, $1)' | 1.192 ms | 0.1898 ms | 0.0993 ms | 1.01 | 0.11 | - | 2.15 KB | 1.00 |
| 'ARX DeleteAsync' | 1.058 ms | 0.0414 ms | 0.0184 ms | 0.89 | 0.07 | - | 5.06 KB | 2.35 |
| 'Dapper ExecuteAsync' | 1.070 ms | 0.0556 ms | 0.0291 ms | 0.90 | 0.08 | - | 2.71 KB | 1.26 |
| 'EF Core ExecuteDeleteAsync' | 1.676 ms | 0.3886 ms | 0.2032 ms | 1.41 | 0.20 | 7.8125 | 41.27 KB | 19.17 |
| 'EF Core Remove + SaveChanges (stub entity)' | 1.343 ms | 0.1725 ms | 0.0766 ms | 1.13 | 0.11 | 9.7656 | 44.88 KB | 20.84 |
Delete.DeleteMultipleBenchmarks
Job=SingleOperation InvocationCount=1 IterationCount=12
| Method | Rows | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw IN ($1, $2, …), chunked' | 1 | 1.950 ms | 0.3735 ms | 0.2916 ms | 1.920 ms | 1.02 | 0.20 | - | - | 3.06 KB | 1.00 |
| 'Raw = ANY($1::bigint[])' | 1 | 1.886 ms | 0.3768 ms | 0.2942 ms | 1.843 ms | 0.98 | 0.19 | - | - | 2.97 KB | 0.97 |
| 'ARX DeleteMultipleAsync' | 1 | 2.173 ms | 0.4099 ms | 0.3200 ms | 2.166 ms | 1.13 | 0.22 | - | - | 5.55 KB | 1.81 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 1 | 2.392 ms | 0.3675 ms | 0.2869 ms | 2.351 ms | 1.25 | 0.22 | - | - | 5.48 KB | 1.79 |
| 'Dapper = ANY(@Ids)' | 1 | 2.327 ms | 0.3846 ms | 0.3002 ms | 2.189 ms | 1.22 | 0.22 | - | - | 3.5 KB | 1.14 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 1 | 8.294 ms | 24.6166 ms | 19.2190 ms | 2.772 ms | 4.33 | 9.73 | - | - | 47.92 KB | 15.65 |
| 'Raw IN ($1, $2, …), chunked' | 100 | 2.304 ms | 0.8486 ms | 0.6625 ms | 2.170 ms | 1.05 | 0.34 | - | - | 28.47 KB | 1.00 |
| 'Raw = ANY($1::bigint[])' | 100 | 2.072 ms | 0.3271 ms | 0.2554 ms | 2.023 ms | 0.94 | 0.19 | - | - | 2.79 KB | 0.10 |
| 'ARX DeleteMultipleAsync' | 100 | 2.452 ms | 0.9635 ms | 0.7522 ms | 2.286 ms | 1.11 | 0.38 | - | - | 5.49 KB | 0.19 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 100 | 2.377 ms | 0.4421 ms | 0.3452 ms | 2.315 ms | 1.08 | 0.24 | - | - | 6.44 KB | 0.23 |
| 'Dapper = ANY(@Ids)' | 100 | 2.065 ms | 0.1721 ms | 0.1343 ms | 2.083 ms | 0.94 | 0.17 | - | - | 3.8 KB | 0.13 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 100 | 8.344 ms | 23.3255 ms | 18.2110 ms | 2.770 ms | 3.79 | 8.09 | - | - | 49.47 KB | 1.74 |
| 'Raw IN ($1, $2, …), chunked' | 1000 | 21.357 ms | 32.7065 ms | 25.5351 ms | 4.990 ms | 3.14 | 4.66 | - | - | 257.93 KB | 1.00 |
| 'Raw = ANY($1::bigint[])' | 1000 | 4.267 ms | 3.9239 ms | 3.0636 ms | 3.371 ms | 0.63 | 0.64 | - | - | 2.84 KB | 0.01 |
| 'ARX DeleteMultipleAsync' | 1000 | 4.785 ms | 4.4510 ms | 3.4750 ms | 3.465 ms | 0.70 | 0.72 | - | - | 5.8 KB | 0.02 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 1000 | 5.171 ms | 6.5606 ms | 5.1221 ms | 3.668 ms | 0.76 | 0.97 | - | - | 13.52 KB | 0.05 |
| 'Dapper = ANY(@Ids)' | 1000 | 4.430 ms | 3.1814 ms | 2.4838 ms | 3.822 ms | 0.65 | 0.58 | - | - | 3.5 KB | 0.01 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 1000 | 11.655 ms | 28.6956 ms | 22.4037 ms | 4.240 ms | 1.71 | 3.87 | - | - | 63.53 KB | 0.25 |
| 'Raw IN ($1, $2, …), chunked' | 10000 | 67.082 ms | 5.2683 ms | 4.1131 ms | 65.352 ms | 1.00 | 0.08 | - | - | 2526.93 KB | 1.000 |
| 'Raw = ANY($1::bigint[])' | 10000 | 51.748 ms | 23.5184 ms | 18.3616 ms | 59.359 ms | 0.77 | 0.27 | - | - | 2.45 KB | 0.001 |
| 'ARX DeleteMultipleAsync' | 10000 | 51.176 ms | 22.9490 ms | 17.9170 ms | 55.401 ms | 0.77 | 0.26 | - | - | 5.52 KB | 0.002 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 10000 | 44.669 ms | 30.7355 ms | 23.9963 ms | 60.501 ms | 0.67 | 0.35 | - | - | 83.14 KB | 0.033 |
| 'Dapper = ANY(@Ids)' | 10000 | 44.832 ms | 31.5167 ms | 24.6062 ms | 56.342 ms | 0.67 | 0.36 | - | - | 3.29 KB | 0.001 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 10000 | 69.353 ms | 27.5625 ms | 21.5190 ms | 61.867 ms | 1.04 | 0.31 | - | - | 203.15 KB | 0.080 |
| 'Raw IN ($1, $2, …), chunked' | 100000 | 255.754 ms | 33.3887 ms | 26.0677 ms | 256.111 ms | 1.01 | 0.14 | 3000.0000 | 1000.0000 | 26052.88 KB | 1.000 |
| 'Raw = ANY($1::bigint[])' | 100000 | 160.908 ms | 22.7241 ms | 17.7415 ms | 158.300 ms | 0.63 | 0.09 | - | - | 2.09 KB | 0.000 |
| 'ARX DeleteMultipleAsync' | 100000 | 143.173 ms | 40.7893 ms | 31.8456 ms | 149.472 ms | 0.56 | 0.13 | - | - | 5.1 KB | 0.000 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 100000 | 147.867 ms | 30.6902 ms | 23.9609 ms | 153.285 ms | 0.58 | 0.11 | - | - | 786.39 KB | 0.030 |
| 'Dapper = ANY(@Ids)' | 100000 | 138.813 ms | 34.5741 ms | 26.9932 ms | 152.415 ms | 0.55 | 0.11 | - | - | 2.98 KB | 0.000 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 100000 | 178.187 ms | 91.1131 ms | 71.1351 ms | 164.678 ms | 0.70 | 0.28 | - | - | 1609.4 KB | 0.062 |
Delete.DeleteMultipleSmallBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Ids | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw = ANY($1::bigint[])' | 1 | 1.058 ms | 0.0609 ms | 0.0270 ms | 1.00 | 0.03 | 2.25 KB | 1.00 |
| 'ARX DeleteMultipleAsync' | 1 | 1.116 ms | 0.2006 ms | 0.0890 ms | 1.06 | 0.08 | 4.97 KB | 2.21 |
| 'Raw = ANY($1::bigint[])' | 10 | 1.123 ms | 0.1307 ms | 0.0684 ms | 1.00 | 0.08 | 2.38 KB | 1.00 |
| 'ARX DeleteMultipleAsync' | 10 | 1.141 ms | 0.1107 ms | 0.0492 ms | 1.02 | 0.07 | 5.11 KB | 2.15 |
| 'Raw = ANY($1::bigint[])' | 50 | 1.257 ms | 0.1470 ms | 0.0769 ms | 1.00 | 0.08 | 2.65 KB | 1.00 |
| 'ARX DeleteMultipleAsync' | 50 | 1.201 ms | 0.0418 ms | 0.0186 ms | 0.96 | 0.06 | 5.38 KB | 2.03 |
Retrieve.RetrieveBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed row)' | 709.0 μs | 55.81 μs | 24.78 μs | 1.00 | 0.05 | - | 2.77 KB | 1.00 |
| 'Raw Npgsql (dictionary)' | 723.1 μs | 100.07 μs | 52.34 μs | 1.02 | 0.08 | - | 3.3 KB | 1.19 |
| 'ARX RetrieveAsync' | 827.9 μs | 167.87 μs | 87.80 μs | 1.17 | 0.12 | 0.9766 | 7.04 KB | 2.54 |
| 'Dapper (POCO)' | 828.3 μs | 225.56 μs | 117.97 μs | 1.17 | 0.16 | - | 3.94 KB | 1.42 |
| 'Dapper (dynamic)' | 761.2 μs | 91.29 μs | 47.75 μs | 1.07 | 0.07 | - | 3.88 KB | 1.40 |
| 'EF Core AsNoTracking FirstOrDefault' | 1,045.8 μs | 325.87 μs | 170.44 μs | 1.48 | 0.23 | 7.8125 | 41.72 KB | 15.07 |
| 'EF Core Find (tracked)' | 1,125.3 μs | 216.35 μs | 113.16 μs | 1.59 | 0.16 | 9.7656 | 46.47 KB | 16.79 |
Retrieve.RetrieveComplexQueryBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (dictionaries)' | Deep join (7 tables, 17 columns): page 1 of 100 | 52.229 ms | 7.7400 ms | 4.0482 ms | 1.01 | 0.10 | - | - | 134.8 KB | 1.00 |
| 'Dapper (dynamic)' | Deep join (7 tables, 17 columns): page 1 of 100 | 48.314 ms | 2.1390 ms | 0.9497 ms | 0.93 | 0.07 | - | - | 91.54 KB | 0.68 |
| 'EF Core (typed, navigations)' | Deep join (7 tables, 17 columns): page 1 of 100 | 47.347 ms | 6.5804 ms | 3.4417 ms | 0.91 | 0.09 | - | - | 160.59 KB | 1.19 |
| 'ARX ArxQueryExpression' | Deep join (7 tables, 17 columns): page 1 of 100 | 50.591 ms | 3.2316 ms | 1.4348 ms | 0.97 | 0.07 | - | - | 150.33 KB | 1.12 |
| 'Raw Npgsql (dictionaries)' | Deep join: every matching row | 65.582 ms | 4.2771 ms | 2.2370 ms | 1.00 | 0.04 | 666.6667 | 500.0000 | 4211.72 KB | 1.00 |
| 'Dapper (dynamic)' | Deep join: every matching row | 65.504 ms | 5.3159 ms | 2.7803 ms | 1.00 | 0.05 | 375.0000 | 125.0000 | 2809.58 KB | 0.67 |
| 'EF Core (typed, navigations)' | Deep join: every matching row | 72.523 ms | 10.6390 ms | 4.7238 ms | 1.11 | 0.08 | 500.0000 | 166.6667 | 2860.2 KB | 0.68 |
| 'ARX ArxQueryExpression' | Deep join: every matching row | 61.514 ms | 3.4600 ms | 1.8096 ms | 0.94 | 0.04 | 500.0000 | 375.0000 | 3366.09 KB | 0.80 |
| 'Raw Npgsql page + count, one round trip' | Deep join: page 20 of 100 + total | 89.321 ms | 6.8197 ms | 3.5669 ms | 1.00 | 0.05 | - | - | 137.92 KB | 1.00 |
| 'Dapper QueryMultiple (page; count)' | Deep join: page 20 of 100 + total | 90.232 ms | 3.9324 ms | 2.0567 ms | 1.01 | 0.04 | - | - | 93.92 KB | 0.68 |
| 'EF Core Skip/Take + CountAsync' | Deep join: page 20 of 100 + total | 87.473 ms | 5.3293 ms | 2.7873 ms | 0.98 | 0.05 | - | - | 185.62 KB | 1.35 |
| 'ARX PageInfo + ReturnTotalRecordCount' | Deep join: page 20 of 100 + total | 90.514 ms | 4.7267 ms | 2.4721 ms | 1.01 | 0.05 | - | - | 155.44 KB | 1.13 |
| 'Raw Npgsql (dictionaries)' | Report: 7 aggregates over 5 tables, grouped by 2 linked columns | 204.607 ms | 31.8080 ms | 16.6362 ms | 1.01 | 0.11 | - | - | 61.96 KB | 1.00 |
| 'Dapper (dynamic)' | Report: 7 aggregates over 5 tables, grouped by 2 linked columns | 188.869 ms | 8.6316 ms | 4.5145 ms | 0.93 | 0.07 | - | - | 36.88 KB | 0.60 |
| 'EF Core GroupBy over navigations' | Report: 7 aggregates over 5 tables, grouped by 2 linked columns | 567.653 ms | 42.9860 ms | 22.4825 ms | 2.79 | 0.24 | - | - | 111.95 KB | 1.81 |
| 'ARX AggregateInfo' | Report: 7 aggregates over 5 tables, grouped by 2 linked columns | 194.647 ms | 10.1348 ms | 5.3007 ms | 0.96 | 0.08 | - | - | 73.65 KB | 1.19 |
| 'Raw Npgsql (dictionaries)' | Search: nested filters, link criteria, distinct, _lk, Top 500 | 9.881 ms | 0.6175 ms | 0.3230 ms | 1.00 | 0.04 | 31.2500 | - | 168.26 KB | 1.00 |
| 'Dapper (dynamic)' | Search: nested filters, link criteria, distinct, _lk, Top 500 | 9.332 ms | 0.1772 ms | 0.0632 ms | 0.95 | 0.03 | 15.6250 | - | 97.96 KB | 0.58 |
| 'EF Core (Any() for the orders)' | Search: nested filters, link criteria, distinct, _lk, Top 500 | 5.479 ms | 1.0266 ms | 0.5369 ms | 0.55 | 0.05 | 31.2500 | - | 174.79 KB | 1.04 |
| 'ARX ArxQueryExpression' | Search: nested filters, link criteria, distinct, _lk, Top 500 | 9.352 ms | 0.3219 ms | 0.1683 ms | 0.95 | 0.03 | 31.2500 | - | 160.56 KB | 0.95 |
Retrieve.RetrieveFilterBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql ILIKE (dictionaries)' | Contains '99', case-insensitive | 72.423 ms | 4.3440 ms | 2.2720 ms | 1.00 | 0.04 | 428.5714 | 285.7143 | 2757.63 KB | 1.00 |
| 'ARX Contains' | Contains '99', case-insensitive | 76.032 ms | 6.9552 ms | 3.6377 ms | 1.05 | 0.06 | 333.3333 | 166.6667 | 2252.23 KB | 0.82 |
| 'Dapper ILIKE (dynamic)' | Contains '99', case-insensitive | 72.986 ms | 4.1798 ms | 1.8559 ms | 1.01 | 0.04 | 285.7143 | 142.8571 | 1683.71 KB | 0.61 |
| 'EF Core EF.Functions.ILike' | Contains '99', case-insensitive | 75.239 ms | 11.6772 ms | 6.1074 ms | 1.04 | 0.09 | 166.6667 | - | 1479.92 KB | 0.54 |
| 'Raw Npgsql = ANY($1) (dictionaries)' | In list of 1,000 ids | 5.927 ms | 0.3032 ms | 0.1346 ms | 1.00 | 0.03 | 132.8125 | 85.9375 | 748.42 KB | 1.00 |
| 'ARX In' | In list of 1,000 ids | 5.995 ms | 0.1878 ms | 0.0834 ms | 1.01 | 0.02 | 109.3750 | 46.8750 | 668.63 KB | 0.89 |
| 'Dapper = ANY(@Ids) (dynamic)' | In list of 1,000 ids | 5.785 ms | 0.5447 ms | 0.2419 ms | 0.98 | 0.04 | 85.9375 | 39.0625 | 457.5 KB | 0.61 |
| 'EF Core Where(ids.Contains)' | In list of 1,000 ids | 7.194 ms | 1.2293 ms | 0.6429 ms | 1.21 | 0.11 | 93.7500 | 15.6250 | 448.86 KB | 0.60 |
| 'Raw Npgsql (dictionaries)' | Nested AND/OR (499 rows) | 14.279 ms | 1.0677 ms | 0.5584 ms | 1.00 | 0.05 | 62.5000 | - | 374.5 KB | 1.00 |
| 'ARX nested filters' | Nested AND/OR (499 rows) | 14.077 ms | 0.5252 ms | 0.2332 ms | 0.99 | 0.04 | 62.5000 | - | 321.12 KB | 0.86 |
| 'Dapper (dynamic)' | Nested AND/OR (499 rows) | 14.060 ms | 0.5759 ms | 0.2557 ms | 0.99 | 0.04 | 46.8750 | 15.6250 | 231.09 KB | 0.62 |
| 'EF Core AsNoTracking' | Nested AND/OR (499 rows) | 14.877 ms | 1.1464 ms | 0.5996 ms | 1.04 | 0.05 | 31.2500 | - | 234.5 KB | 0.63 |
Retrieve.RetrieveLinkBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql LEFT JOIN (dictionaries)' | 2.895 ms | 0.2391 ms | 0.1250 ms | 1.00 | 0.06 | 97.6563 | 50.7813 | 519.58 KB | 1.00 |
| 'Dapper LEFT JOIN (dynamic)' | 2.846 ms | 0.4531 ms | 0.2370 ms | 0.98 | 0.09 | 58.5938 | 19.5313 | 301.19 KB | 0.58 |
| 'ARX link entity' | 2.912 ms | 0.4617 ms | 0.2415 ms | 1.01 | 0.09 | 89.8438 | 31.2500 | 462.8 KB | 0.89 |
| 'ARX direct join (_lk)' | 2.931 ms | 0.1585 ms | 0.0704 ms | 1.01 | 0.05 | 89.8438 | 31.2500 | 462.94 KB | 0.89 |
| 'ARX declared lookup + display name' | 2.957 ms | 0.2096 ms | 0.0931 ms | 1.02 | 0.05 | 125.0000 | 46.8750 | 634.83 KB | 1.22 |
Retrieve.RetrieveMultipleBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed rows)' | 1 | 727.2 μs | 34.68 μs | 18.14 μs | 1.00 | 0.03 | - | - | - | 2.83 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 1 | 749.7 μs | 35.14 μs | 15.60 μs | 1.03 | 0.03 | - | - | - | 3.42 KB | 1.21 |
| 'ARX RetrieveMultipleAsync' | 1 | 838.0 μs | 46.52 μs | 20.65 μs | 1.15 | 0.04 | 1.9531 | - | - | 17.55 KB | 6.20 |
| 'Dapper (POCO)' | 1 | 748.6 μs | 33.87 μs | 17.71 μs | 1.03 | 0.03 | - | - | - | 4.1 KB | 1.45 |
| 'Dapper (dynamic)' | 1 | 755.4 μs | 47.63 μs | 24.91 μs | 1.04 | 0.04 | - | - | - | 3.87 KB | 1.37 |
| 'EF Core AsNoTracking ToList' | 1 | 1,066.7 μs | 225.87 μs | 118.14 μs | 1.47 | 0.16 | 9.7656 | - | - | 45.29 KB | 16.00 |
| 'Raw Npgsql (typed rows)' | 100 | 959.4 μs | 46.16 μs | 20.50 μs | 1.00 | 0.03 | 3.9063 | - | - | 22.71 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 100 | 1,138.3 μs | 135.19 μs | 70.70 μs | 1.19 | 0.07 | 15.6250 | 1.9531 | - | 77.33 KB | 3.40 |
| 'ARX RetrieveMultipleAsync' | 100 | 1,027.4 μs | 42.22 μs | 15.06 μs | 1.07 | 0.03 | 15.6250 | - | - | 77.58 KB | 3.42 |
| 'Dapper (POCO)' | 100 | 986.0 μs | 80.52 μs | 35.75 μs | 1.03 | 0.04 | 9.7656 | - | - | 46.28 KB | 2.04 |
| 'Dapper (dynamic)' | 100 | 1,002.3 μs | 112.81 μs | 59.00 μs | 1.05 | 0.06 | 9.7656 | - | - | 49.22 KB | 2.17 |
| 'EF Core AsNoTracking ToList' | 100 | 1,728.6 μs | 675.71 μs | 353.41 μs | 1.80 | 0.35 | 15.6250 | - | - | 83.67 KB | 3.68 |
| 'Raw Npgsql (typed rows)' | 1000 | 3,428.7 μs | 397.87 μs | 208.10 μs | 1.00 | 0.08 | 39.0625 | 7.8125 | - | 200.73 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 1000 | 3,457.8 μs | 147.86 μs | 77.34 μs | 1.01 | 0.06 | 125.0000 | 62.5000 | - | 747.06 KB | 3.72 |
| 'ARX RetrieveMultipleAsync' | 1000 | 3,961.9 μs | 249.68 μs | 130.59 μs | 1.16 | 0.08 | 109.3750 | 62.5000 | - | 620.75 KB | 3.09 |
| 'Dapper (POCO)' | 1000 | 3,294.2 μs | 129.62 μs | 67.80 μs | 0.96 | 0.06 | 85.9375 | 27.3438 | - | 426.27 KB | 2.12 |
| 'Dapper (dynamic)' | 1000 | 3,182.5 μs | 254.21 μs | 132.95 μs | 0.93 | 0.06 | 85.9375 | 42.9688 | - | 457.27 KB | 2.28 |
| 'EF Core AsNoTracking ToList' | 1000 | 4,259.3 μs | 525.48 μs | 233.32 μs | 1.25 | 0.10 | 78.1250 | 15.6250 | - | 431.3 KB | 2.15 |
| 'Raw Npgsql (typed rows)' | 10000 | 26,424.7 μs | 1,529.53 μs | 799.97 μs | 1.00 | 0.04 | 343.7500 | 250.0000 | 93.7500 | 2079.39 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 10000 | 32,829.9 μs | 670.01 μs | 297.49 μs | 1.24 | 0.04 | 1466.6667 | 866.6667 | 266.6667 | 7534.29 KB | 3.62 |
| 'ARX RetrieveMultipleAsync' | 10000 | 28,802.8 μs | 1,212.31 μs | 538.27 μs | 1.09 | 0.04 | 1093.7500 | 750.0000 | 281.2500 | 6146.21 KB | 2.96 |
| 'Dapper (POCO)' | 10000 | 26,085.1 μs | 1,675.74 μs | 876.45 μs | 0.99 | 0.04 | 687.5000 | 312.5000 | 125.0000 | 4324.54 KB | 2.08 |
| 'Dapper (dynamic)' | 10000 | 28,738.8 μs | 2,451.14 μs | 1,281.99 μs | 1.09 | 0.06 | 875.0000 | 562.5000 | 187.5000 | 4637.19 KB | 2.23 |
| 'EF Core AsNoTracking ToList' | 10000 | 30,271.5 μs | 4,074.60 μs | 2,131.09 μs | 1.15 | 0.08 | 666.6667 | 333.3333 | 111.1111 | 4005.03 KB | 1.93 |
| 'Raw Npgsql (typed rows)' | 100000 | 255,282.1 μs | 19,945.19 μs | 8,855.79 μs | 1.00 | 0.05 | 3000.0000 | 1000.0000 | - | 20258.49 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 100000 | 280,317.6 μs | 11,211.40 μs | 5,863.78 μs | 1.10 | 0.04 | 14000.0000 | 8000.0000 | 2000.0000 | 74747.96 KB | 3.69 |
| 'ARX RetrieveMultipleAsync' | 100000 | 242,228.4 μs | 11,674.11 μs | 6,105.78 μs | 0.95 | 0.04 | 10000.0000 | 5000.0000 | 1000.0000 | 60710.92 KB | 3.00 |
| 'Dapper (POCO)' | 100000 | 248,329.8 μs | 12,357.38 μs | 6,463.15 μs | 0.97 | 0.04 | 6000.0000 | 2000.0000 | 1000.0000 | 42699.36 KB | 2.11 |
| 'Dapper (dynamic)' | 100000 | 244,983.7 μs | 15,850.42 μs | 7,037.69 μs | 0.96 | 0.04 | 8000.0000 | 4000.0000 | 1000.0000 | 45816.62 KB | 2.26 |
| 'EF Core AsNoTracking ToList' | 100000 | 264,134.9 μs | 17,189.63 μs | 8,990.51 μs | 1.04 | 0.05 | 7000.0000 | 3000.0000 | 1000.0000 | 39072.94 KB | 1.93 |
Retrieve.RetrievePagingBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Page | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql LIMIT/OFFSET (dictionaries)' | A page of 50 | 1 | 855.0 μs | 38.93 μs | 17.28 μs | 1.00 | 0.03 | 7.8125 | 40.46 KB | 1.00 |
| 'ARX PageInfo' | A page of 50 | 1 | 879.4 μs | 45.77 μs | 23.94 μs | 1.03 | 0.03 | 9.7656 | 47.46 KB | 1.17 |
| 'EF Core Skip/Take' | A page of 50 | 1 | 1,066.3 μs | 243.33 μs | 127.27 μs | 1.25 | 0.14 | 13.6719 | 64.94 KB | 1.60 |
| 'Raw Npgsql LIMIT/OFFSET (dictionaries)' | A page of 50 | 1000 | 11,910.6 μs | 269.30 μs | 119.57 μs | 1.00 | 0.01 | - | 40.49 KB | 1.00 |
| 'ARX PageInfo' | A page of 50 | 1000 | 13,428.0 μs | 2,697.21 μs | 961.85 μs | 1.13 | 0.08 | - | 47.48 KB | 1.17 |
| 'EF Core Skip/Take' | A page of 50 | 1000 | 12,066.7 μs | 274.63 μs | 121.94 μs | 1.01 | 0.01 | - | 64.91 KB | 1.60 |
| 'Raw Npgsql page + count, one batch' | A page of 50 and the total | 1 | 6,703.8 μs | 431.46 μs | 191.57 μs | 1.00 | 0.04 | 7.8125 | 40.56 KB | 1.00 |
| 'ARX PageInfo + ReturnTotalRecordCount' | A page of 50 and the total | 1 | 6,642.2 μs | 205.25 μs | 73.19 μs | 0.99 | 0.03 | - | 48.41 KB | 1.19 |
| 'EF Core Skip/Take + CountAsync' | A page of 50 and the total | 1 | 10,091.4 μs | 1,753.06 μs | 916.89 μs | 1.51 | 0.14 | - | 69.95 KB | 1.72 |
| 'Raw Npgsql page + count, one batch' | A page of 50 and the total | 1000 | 21,598.1 μs | 1,185.99 μs | 620.29 μs | 1.00 | 0.04 | - | 40.62 KB | 1.00 |
| 'ARX PageInfo + ReturnTotalRecordCount' | A page of 50 and the total | 1000 | 25,513.6 μs | 10,083.00 μs | 5,273.60 μs | 1.18 | 0.23 | - | 48.49 KB | 1.19 |
| 'EF Core Skip/Take + CountAsync' | A page of 50 and the total | 1000 | 29,967.9 μs | 6,490.50 μs | 3,394.66 μs | 1.39 | 0.15 | - | 70.15 KB | 1.73 |
Execute.ExecuteCallBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql ExecuteScalar' | Function, one value | 579.7 μs | 66.27 μs | 34.66 μs | 1.00 | 0.08 | - | 2.43 KB | 1.00 |
| 'Dapper ExecuteScalar' | Function, one value | 572.4 μs | 40.34 μs | 21.10 μs | 0.99 | 0.06 | - | 2.95 KB | 1.22 |
| 'EF Core Database.SqlQuery |
Function, one value | 880.1 μs | 226.75 μs | 118.59 μs | 1.52 | 0.21 | 9.7656 | 45.36 KB | 18.67 |
| 'ARX ExecuteAsync + Value |
Function, one value | 691.6 μs | 94.60 μs | 49.48 μs | 1.20 | 0.10 | 1.9531 | 11.88 KB | 4.89 |
| 'Raw Npgsql CALL, the OUT row read' | Procedure, 2 IN and 2 OUT values | 594.1 μs | 28.47 μs | 12.64 μs | 1.00 | 0.03 | - | 2.35 KB | 1.00 |
| 'Npgsql StoredProcedure with Output parameters' | Procedure, 2 IN and 2 OUT values | 631.6 μs | 22.19 μs | 9.85 μs | 1.06 | 0.03 | - | 3.84 KB | 1.63 |
| 'Dapper StoredProcedure, DynamicParameters with outputs' | Procedure, 2 IN and 2 OUT values | 708.4 μs | 87.20 μs | 38.72 μs | 1.19 | 0.07 | - | 5.07 KB | 2.16 |
| 'ARX ExecuteAsync' | Procedure, 2 IN and 2 OUT values | 639.6 μs | 24.51 μs | 10.88 μs | 1.08 | 0.03 | 1.9531 | 9.82 KB | 4.18 |
Execute.ExecuteCursorBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql: BEGIN + CALL, then both FETCH + COMMIT' | 1.817 ms | 0.1096 ms | 0.0391 ms | 1.00 | 0.03 | - | 4.03 KB | 1.00 |
| 'ARX ExecuteAsync, two cursor parameters' | 1.603 ms | 0.3113 ms | 0.1628 ms | 0.88 | 0.09 | 7.8125 | 39.68 KB | 9.84 |
Execute.ExecutePagingBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Page | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw: BEGIN + CALL, then FETCH + COMMIT' | 1. The routine pages itself | 1 | 6.950 ms | 0.1572 ms | 0.0560 ms | 1.00 | 0.01 | 26.93 KB | 1.00 |
| 'ARX PagingParameters' | 1. The routine pages itself | 1 | 6.529 ms | 0.4328 ms | 0.1922 ms | 0.94 | 0.03 | 29.85 KB | 1.11 |
| 'Raw: BEGIN + CALL, then FETCH + COMMIT' | 1. The routine pages itself | 1000 | 10.790 ms | 0.1417 ms | 0.0629 ms | 1.00 | 0.01 | 27.33 KB | 1.00 |
| 'ARX PagingParameters' | 1. The routine pages itself | 1000 | 10.397 ms | 0.1099 ms | 0.0488 ms | 0.96 | 0.01 | 30.16 KB | 1.10 |
| 'Raw: LIMIT/OFFSET + count, one round trip' | 2. ARX pages a SQL function | 1 | 23.811 ms | 1.0889 ms | 0.4835 ms | 1.00 | 0.03 | 26.37 KB | 1.00 |
| 'ARX PageInfo on the function' | 2. ARX pages a SQL function | 1 | 23.866 ms | 0.9368 ms | 0.4900 ms | 1.00 | 0.03 | 29.88 KB | 1.13 |
| 'Raw: LIMIT/OFFSET + count, one round trip' | 2. ARX pages a SQL function | 1000 | 32.174 ms | 3.3346 ms | 1.7441 ms | 1.00 | 0.07 | 26.68 KB | 1.00 |
| 'ARX PageInfo on the function' | 2. ARX pages a SQL function | 1000 | 32.219 ms | 2.2282 ms | 0.7946 ms | 1.00 | 0.05 | 30.23 KB | 1.13 |
| 'Raw: LIMIT/OFFSET + count, one round trip' | 2b. ARX pages a PL/pgSQL function | 1 | 76.761 ms | 7.4804 ms | 3.9124 ms | 1.00 | 0.07 | 26.38 KB | 1.00 |
| 'ARX PageInfo on the function' | 2b. ARX pages a PL/pgSQL function | 1 | 79.209 ms | 4.7736 ms | 2.4967 ms | 1.03 | 0.06 | 30.04 KB | 1.14 |
| 'Raw: LIMIT/OFFSET + count, one round trip' | 2b. ARX pages a PL/pgSQL function | 1000 | 95.569 ms | 3.7379 ms | 1.9550 ms | 1.00 | 0.03 | 26.72 KB | 1.00 |
| 'ARX PageInfo on the function' | 2b. ARX pages a PL/pgSQL function | 1000 | 97.811 ms | 8.1972 ms | 4.2873 ms | 1.02 | 0.05 | 30.48 KB | 1.14 |
| 'Raw: BEGIN + CALL, then MOVE, FETCH, MOVE ALL + COMMIT' | 3. ARX pages a cursor | 1 | 10.582 ms | 1.0073 ms | 0.5268 ms | 1.00 | 0.07 | 26.5 KB | 1.00 |
| 'ARX PageInfo on a cursor parameter' | 3. ARX pages a cursor | 1 | 9.840 ms | 0.7025 ms | 0.3674 ms | 0.93 | 0.05 | 27.56 KB | 1.04 |
| 'Raw: BEGIN + CALL, then MOVE, FETCH, MOVE ALL + COMMIT' | 3. ARX pages a cursor | 1000 | 10.157 ms | 0.1886 ms | 0.0837 ms | 1.00 | 0.01 | 27.13 KB | 1.00 |
| 'ARX PageInfo on a cursor parameter' | 3. ARX pages a cursor | 1000 | 10.061 ms | 1.3501 ms | 0.7061 ms | 0.99 | 0.07 | 28.2 KB | 1.04 |
Execute.ExecuteRowsBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (dictionaries)' | 1 | 688.5 μs | 48.85 μs | 21.69 μs | 1.00 | 0.04 | - | - | - | 2.79 KB | 1.00 |
| 'Dapper (dynamic)' | 1 | 781.6 μs | 133.28 μs | 69.71 μs | 1.14 | 0.10 | - | - | - | 3.08 KB | 1.10 |
| 'EF Core Database.SqlQuery |
1 | 1,020.6 μs | 190.31 μs | 99.54 μs | 1.48 | 0.14 | 7.8125 | - | - | 44.09 KB | 15.80 |
| 'ARX ExecuteAsync' | 1 | 763.2 μs | 80.48 μs | 42.09 μs | 1.11 | 0.07 | 1.9531 | - | - | 11.54 KB | 4.14 |
| 'Raw Npgsql (dictionaries)' | 100 | 859.6 μs | 69.04 μs | 30.66 μs | 1.00 | 0.05 | 9.7656 | - | - | 48.13 KB | 1.00 |
| 'Dapper (dynamic)' | 100 | 841.3 μs | 74.21 μs | 32.95 μs | 0.98 | 0.05 | 3.9063 | - | - | 25.23 KB | 0.52 |
| 'EF Core Database.SqlQuery |
100 | 1,064.1 μs | 126.46 μs | 56.15 μs | 1.24 | 0.07 | 15.6250 | - | - | 74.03 KB | 1.54 |
| 'ARX ExecuteAsync' | 100 | 906.0 μs | 71.96 μs | 31.95 μs | 1.06 | 0.05 | 7.8125 | - | - | 43.73 KB | 0.91 |
| 'Raw Npgsql (dictionaries)' | 1000 | 1,957.4 μs | 309.91 μs | 137.60 μs | 1.00 | 0.09 | 85.9375 | 31.2500 | - | 456.46 KB | 1.00 |
| 'Dapper (dynamic)' | 1000 | 1,841.6 μs | 190.81 μs | 84.72 μs | 0.94 | 0.07 | 39.0625 | 7.8125 | - | 222.39 KB | 0.49 |
| 'EF Core Database.SqlQuery |
1000 | 2,658.0 μs | 662.70 μs | 346.61 μs | 1.36 | 0.19 | 70.3125 | 15.6250 | - | 342.46 KB | 0.75 |
| 'ARX ExecuteAsync' | 1000 | 2,030.4 μs | 367.97 μs | 192.46 μs | 1.04 | 0.11 | 66.4063 | 19.5313 | - | 332.75 KB | 0.73 |
| 'Raw Npgsql (dictionaries)' | 10000 | 17,771.2 μs | 2,023.70 μs | 898.53 μs | 1.00 | 0.07 | 875.0000 | 562.5000 | 187.5000 | 4638.93 KB | 1.00 |
| 'Dapper (dynamic)' | 10000 | 15,365.9 μs | 1,302.21 μs | 578.19 μs | 0.87 | 0.05 | 406.2500 | 281.2500 | 93.7500 | 2291.57 KB | 0.49 |
| 'EF Core Database.SqlQuery |
10000 | 14,765.2 μs | 715.18 μs | 317.54 μs | 0.83 | 0.04 | 515.6250 | 218.7500 | 78.1250 | 3124.21 KB | 0.67 |
| 'ARX ExecuteAsync' | 10000 | 15,793.2 μs | 707.21 μs | 314.01 μs | 0.89 | 0.04 | 625.0000 | 406.2500 | 156.2500 | 3320.11 KB | 0.72 |
Execute.ExecuteScopeBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql: one transaction, a CALL per round trip' | 63.55 ms | 12.570 ms | 6.575 ms | 1.01 | 0.13 | - | 139.46 KB | 1.00 |
| 'ARX ExecuteAsync, each call on its own' | 102.80 ms | 10.899 ms | 4.839 ms | 1.63 | 0.17 | - | 587.38 KB | 4.21 |
| 'ARX in an ArxTransaction' | 55.33 ms | 4.804 ms | 2.133 ms | 0.88 | 0.09 | - | 560.87 KB | 4.02 |
| 'ARX in a batch scope (savepoint per call)' | 55.97 ms | 2.154 ms | 0.957 ms | 0.89 | 0.08 | 125.0000 | 608.51 KB | 4.36 |
Preload.NoCatalogBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'With a catalog' | Create one row | 1,184.9 μs | 15.12 μs | 6.71 μs | 1.00 | 0.01 | 1.9531 | 9.78 KB | 1.00 |
| 'Without a catalog, re-read' | Create one row | 8,812.5 μs | 1,378.25 μs | 720.85 μs | 7.44 | 0.58 | - | 39.23 KB | 4.01 |
| 'Without a catalog, remembered' | Create one row | 1,208.9 μs | 73.89 μs | 32.81 μs | 1.02 | 0.03 | 1.9531 | 10.47 KB | 1.07 |
| 'With a catalog' | CreateMultiple, 100 rows | 3,454.7 μs | 26.18 μs | 11.63 μs | 1.00 | 0.00 | 23.4375 | 117.99 KB | 1.00 |
| 'Without a catalog, re-read' | CreateMultiple, 100 rows | 10,339.6 μs | 371.97 μs | 194.55 μs | 2.99 | 0.05 | 31.2500 | 146.75 KB | 1.24 |
| 'Without a catalog, remembered' | CreateMultiple, 100 rows | 3,606.4 μs | 224.66 μs | 117.50 μs | 1.04 | 0.03 | 23.4375 | 118.75 KB | 1.01 |
| 'With a catalog' | Retrieve one row by id | 744.1 μs | 58.17 μs | 30.42 μs | 1.00 | 0.05 | 0.9766 | 6.22 KB | 1.00 |
| 'Without a catalog, re-read' | Retrieve one row by id | 7,990.0 μs | 1,376.17 μs | 719.76 μs | 10.75 | 1.00 | - | 40.68 KB | 6.54 |
| 'Without a catalog, remembered' | Retrieve one row by id | 799.5 μs | 80.06 μs | 41.87 μs | 1.08 | 0.07 | 1.9531 | 11.9 KB | 1.91 |
| 'With a catalog' | Update one row by id | 1,091.7 μs | 89.05 μs | 39.54 μs | 1.00 | 0.05 | 1.9531 | 9.5 KB | 1.00 |
| 'Without a catalog, re-read' | Update one row by id | 8,894.5 μs | 2,044.15 μs | 1,069.13 μs | 8.16 | 0.97 | - | 39.07 KB | 4.11 |
| 'Without a catalog, remembered' | Update one row by id | 1,092.8 μs | 88.00 μs | 39.07 μs | 1.00 | 0.05 | 1.9531 | 10.24 KB | 1.08 |
Preload.PreloadCreateBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql INSERT … RETURNING id' | 1.214 ms | 0.0578 ms | 0.0206 ms | 1.00 | 0.02 | - | 3.12 KB | 1.00 |
| 'ARX, schema declared by hand' | 1.278 ms | 0.1602 ms | 0.0838 ms | 1.05 | 0.07 | 1.9531 | 9.75 KB | 3.13 |
| 'ARX, preloaded KeysOnly' | 1.246 ms | 0.1116 ms | 0.0495 ms | 1.03 | 0.04 | 1.9531 | 9.75 KB | 3.13 |
| 'ARX, preloaded DataTypes' | 1.411 ms | 0.3685 ms | 0.1927 ms | 1.16 | 0.15 | 1.9531 | 9.75 KB | 3.13 |
| 'ARX, preloaded DataTypes, Strict' | 1.235 ms | 0.1651 ms | 0.0733 ms | 1.02 | 0.06 | 1.9531 | 9.76 KB | 3.13 |
Preload.PreloadReadBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql, mood::text, rows into dictionaries' | 100 rows with an enum, same service | 906.9 μs | 163.69 μs | 85.62 μs | 1.01 | 0.13 | 9.7656 | 51.67 KB | 1.00 |
| 'ARX, schema declared by hand' | 100 rows with an enum, same service | 917.8 μs | 94.51 μs | 49.43 μs | 1.02 | 0.10 | 11.7188 | 54.34 KB | 1.05 |
| 'ARX, preloaded DataTypes' | 100 rows with an enum, same service | 886.8 μs | 63.69 μs | 33.31 μs | 0.99 | 0.09 | 11.7188 | 54.43 KB | 1.05 |
| 'ARX, preloaded DataTypes, Strict' | 100 rows with an enum, same service | 913.1 μs | 64.76 μs | 28.75 μs | 1.01 | 0.10 | 11.7188 | 54.49 KB | 1.05 |
| 'Raw Npgsql, mood::text, rows into dictionaries' | First read of 100 rows with an enum, new service | 805.4 μs | 18.58 μs | 9.72 μs | 1.00 | 0.02 | 9.7656 | 51.69 KB | 1.00 |
| 'ARX, schema declared by hand' | First read of 100 rows with an enum, new service | 2,393.5 μs | 92.93 μs | 48.60 μs | 2.97 | 0.07 | 15.6250 | 75.68 KB | 1.46 |
| 'ARX, preloaded DataTypes' | First read of 100 rows with an enum, new service | 928.2 μs | 47.80 μs | 21.22 μs | 1.15 | 0.03 | 13.6719 | 65.65 KB | 1.27 |
| 'ARX, schema declared by hand' | One row by id, all columns, same service | 748.9 μs | 75.60 μs | 33.57 μs | 1.00 | 0.06 | 0.9766 | 6.25 KB | 1.00 |
| 'ARX, preloaded DataTypes' | One row by id, all columns, same service | 752.5 μs | 79.44 μs | 35.27 μs | 1.01 | 0.06 | 0.9766 | 6.21 KB | 0.99 |
| 'ARX, preloaded DataTypes, Strict' | One row by id, all columns, same service | 743.5 μs | 48.55 μs | 25.39 μs | 0.99 | 0.05 | - | 6.24 KB | 1.00 |
Preload.PreloadStartupBenchmarks
Job=Standard IterationCount=8 LaunchCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Declared by hand (no database)' | 2.240 μs | 0.0257 μs | 0.0092 μs | 1.00 | 0.01 | 1.3123 | 0.0076 | 6.03 KB | 1.00 |
| 'Preload, KeysOnly' | 14,179.317 μs | 3,701.7385 μs | 1,936.0808 μs | 6,330.53 | 817.47 | - | - | 38.05 KB | 6.31 |
| 'Preload, DataTypes' | 12,964.966 μs | 1,583.3597 μs | 828.1278 μs | 5,788.37 | 350.19 | - | - | 40.32 KB | 6.68 |
| 'From a saved preload's JSON (no database)' | 20.330 μs | 2.5174 μs | 1.3166 μs | 9.08 | 0.56 | 2.5635 | - | 11.84 KB | 1.96 |
2026-11-08: security ab
Does the injection check cost anything? A/B, 2026-11-08
Question: did adding ARX1017 SuspectedInjection (ArxInjectionCheck) slow down the write operations?
How: the same write benchmark classes, run one after the other on the same machine and database, from two git worktrees:
| Commit | Library code | |
|---|---|---|
| A, before | fa6ba08 |
Create, Update, Delete hardened; no injection check |
| B, after | fa54ee3 |
The same plus the check: ArxInjectionCheck and its call from QuoteIdentifier. Nothing else in the library changed between the two |
Classes: CreateBenchmarks, CreateMultipleBenchmarks, UpdateBenchmarks, UpdateMultipleBenchmarks,
DeleteBenchmarks, DeleteMultipleSmallBenchmarks (106 measurements each run). Run A 16:03 to 16:27, run B 16:28 to
16:52, straight after the full run (2026-11-08-full-run.md), with nothing else running.
Result: no measurable cost
| ARX rows (22) | Rows ARX doesn't run: raw Npgsql, Dapper, EF Core (84) | |
|---|---|---|
| Change in mean time, B vs A | median +0.4%, from −24.1% to +33.7% | median +0.0%, from −17.8% to +31.3% |
| Median size of the change | 3.4% | 3.8% |
| Within ±5% | 15 of 22 | 51 of 84 |
| Change in memory per call | at most 0.05 KB on a single-row call (12.11 → 12.13 KB), 0.4 KB on 5.5 MB at 10,000 rows | the same |
- The time changes are noise. The code the check doesn't touch (raw Npgsql, Dapper, EF Core) moved as much as ARX did, in both directions. The largest ARX change (UpdateMultiple at 1,000 rows, 32.0 → 42.8 ms) measured 27.4 ms in the full run, also with the check, 2 minutes earlier: faster than A.
- Memory is the precise signal, and it didn't move. Allocations are deterministic; ARX's are within 0.05 KB of run A on every single-row call.
- Why it costs nothing: valid names take the same path as before.
ArxInjectionCheck.Inspectruns only on a name that has already failed validation, to choose between ARX1003 and ARX1017, so a normal call never reaches it. The other change, theQuoteIdentifiercall, is the existing validation.
Reads weren't in the A/B: Retrieve was rewritten after the check was added, so there's no "before" with the same read engine. Every
read validates its names through the same QuoteIdentifier path.
Every measurement (mean in ms, B vs A, and memory)
| Class | Method | Parameters | A (before) | B (after) | Change | Memory A → B |
|---|---|---|---|---|---|---|
| CreateBenchmarks | Raw Npgsql (typed, $n) | Create (10 columns, returns id) | 1.171 | 1.042 | -11.0% | 3.96 KB → 3.93 KB |
| CreateBenchmarks | ARX CreateAsync | Create (10 columns, returns id) | 1.102 | 1.106 | +0.4% | 12.11 KB → 12.13 KB |
| CreateBenchmarks | Dapper (POCO) | Create (10 columns, returns id) | 1.136 | 1.096 | -3.5% | 5.87 KB → 5.91 KB |
| CreateBenchmarks | Dapper (dynamic: DynamicParameters) | Create (10 columns, returns id) | 1.103 | 1.078 | -2.3% | 8.47 KB → 8.47 KB |
| CreateBenchmarks | EF Core (typed, new context) | Create (10 columns, returns id) | 1.388 | 1.661 | +19.7% | 52.87 KB → 52.86 KB |
| CreateBenchmarks | EF Core (property bag, new context) | Create (10 columns, returns id) | 1.589 | 1.762 | +10.9% | 59.68 KB → 59.63 KB |
| CreateBenchmarks | Raw Npgsql, option code written directly | Create with selection set (11 columns) | 1.060 | 1.028 | -3.0% | 4.31 KB → 4.32 KB |
| CreateBenchmarks | ARX CreateAsync with ArxSelectionSetValue (catalog check) | Create with selection set (11 columns) | 1.099 | 1.070 | -2.6% | 12.95 KB → 13 KB |
| CreateMultipleBenchmarks | Raw binary COPY | CreateMultiple, ids not needed, 1 | 49.497 | 50.022 | +1.1% | 3.74 KB → 3.82 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES (no RETURNING) | CreateMultiple, ids not needed, 1 | 1.125 | 1.043 | -7.3% | 5.84 KB → 5.79 KB |
| CreateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | CreateMultiple, ids not needed, 1 | 1.027 | 1.040 | +1.3% | 5.89 KB → 5.89 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync (still returns ids) | CreateMultiple, ids not needed, 1 | 1.068 | 1.122 | +5.1% | 12.56 KB → 12.59 KB |
| CreateMultipleBenchmarks | Raw binary COPY | CreateMultiple, ids not needed, 10 | 49.480 | 49.470 | -0.0% | 4.13 KB → 4.11 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES (no RETURNING) | CreateMultiple, ids not needed, 10 | 1.259 | 1.211 | -3.8% | 26.86 KB → 26.85 KB |
| CreateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | CreateMultiple, ids not needed, 10 | 9.665 | 9.256 | -4.2% | 36.29 KB → 36.31 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync (still returns ids) | CreateMultiple, ids not needed, 10 | 1.454 | 1.355 | -6.8% | 38.57 KB → 38.58 KB |
| CreateMultipleBenchmarks | Raw binary COPY | CreateMultiple, ids not needed, 100 | 49.894 | 50.123 | +0.5% | 8.46 KB → 8.42 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES (no RETURNING) | CreateMultiple, ids not needed, 100 | 3.863 | 3.850 | -0.3% | 243.83 KB → 243.83 KB |
| CreateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | CreateMultiple, ids not needed, 100 | 100.585 | 89.786 | -10.7% | 340.9 KB → 340.83 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync (still returns ids) | CreateMultiple, ids not needed, 100 | 2.382 | 2.400 | +0.8% | 70.63 KB → 70.61 KB |
| CreateMultipleBenchmarks | Raw binary COPY | CreateMultiple, ids not needed, 1000 | 50.962 | 50.653 | -0.6% | 50.63 KB → 50.81 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES (no RETURNING) | CreateMultiple, ids not needed, 1000 | 49.515 | 53.281 | +7.6% | 2294.61 KB → 2294.7 KB |
| CreateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | CreateMultiple, ids not needed, 1000 | 1016.010 | 938.488 | -7.6% | 3385.88 KB → 3385.88 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync (still returns ids) | CreateMultiple, ids not needed, 1000 | 22.104 | 22.763 | +3.0% | 565.75 KB → 565.77 KB |
| CreateMultipleBenchmarks | Raw binary COPY | CreateMultiple, ids not needed, 10000 | 63.685 | 65.078 | +2.2% | 472.86 KB → 472.83 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES (no RETURNING) | CreateMultiple, ids not needed, 10000 | 215.736 | 224.406 | +4.0% | 23503.35 KB → 23503.35 KB |
| CreateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | CreateMultiple, ids not needed, 10000 | 9499.754 | 9518.486 | +0.2% | 33831.02 KB → 33831.2 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync (still returns ids) | CreateMultiple, ids not needed, 10000 | 123.507 | 126.939 | +2.8% | 5499.09 KB → 5498.97 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES ... RETURNING id | CreateMultiple, returns ids, 1 | 1.131 | 1.108 | -2.0% | 5.74 KB → 5.76 KB |
| CreateMultipleBenchmarks | Raw unnest arrays ... RETURNING id | CreateMultiple, returns ids, 1 | 1.352 | 1.514 | +12.0% | 9.91 KB → 9.93 KB |
| CreateMultipleBenchmarks | Raw NpgsqlBatch of single-row INSERTs | CreateMultiple, returns ids, 1 | 1.140 | 1.082 | -5.1% | 3.94 KB → 3.91 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync | CreateMultiple, returns ids, 1 | 1.090 | 1.086 | -0.4% | 12.56 KB → 12.61 KB |
| CreateMultipleBenchmarks | EF Core AddRange (typed) | CreateMultiple, returns ids, 1 | 1.512 | 1.544 | +2.1% | 52.96 KB → 52.89 KB |
| CreateMultipleBenchmarks | EF Core AddRange (property bag) | CreateMultiple, returns ids, 1 | 1.548 | 1.571 | +1.5% | 59.65 KB → 59.64 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES ... RETURNING id | CreateMultiple, returns ids, 10 | 1.335 | 1.288 | -3.5% | 26.83 KB → 26.8 KB |
| CreateMultipleBenchmarks | Raw unnest arrays ... RETURNING id | CreateMultiple, returns ids, 10 | 1.430 | 1.480 | +3.5% | 11.19 KB → 11.23 KB |
| CreateMultipleBenchmarks | Raw NpgsqlBatch of single-row INSERTs | CreateMultiple, returns ids, 10 | 1.880 | 1.898 | +1.0% | 24.03 KB → 23.99 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync | CreateMultiple, returns ids, 10 | 1.379 | 1.388 | +0.7% | 38.51 KB → 38.54 KB |
| CreateMultipleBenchmarks | EF Core AddRange (typed) | CreateMultiple, returns ids, 10 | 3.532 | 3.212 | -9.1% | 190.01 KB → 189.95 KB |
| CreateMultipleBenchmarks | EF Core AddRange (property bag) | CreateMultiple, returns ids, 10 | 3.651 | 3.416 | -6.4% | 203.29 KB → 203.3 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES ... RETURNING id | CreateMultiple, returns ids, 100 | 4.426 | 3.804 | -14.1% | 244.52 KB → 244.56 KB |
| CreateMultipleBenchmarks | Raw unnest arrays ... RETURNING id | CreateMultiple, returns ids, 100 | 2.602 | 2.497 | -4.0% | 24.27 KB → 24.29 KB |
| CreateMultipleBenchmarks | Raw NpgsqlBatch of single-row INSERTs | CreateMultiple, returns ids, 100 | 9.969 | 8.304 | -16.7% | 226.81 KB → 226.9 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync | CreateMultiple, returns ids, 100 | 3.289 | 2.497 | -24.1% | 70.62 KB → 70.58 KB |
| CreateMultipleBenchmarks | EF Core AddRange (typed) | CreateMultiple, returns ids, 100 | 13.074 | 10.743 | -17.8% | 1537.7 KB → 1532.62 KB |
| CreateMultipleBenchmarks | EF Core AddRange (property bag) | CreateMultiple, returns ids, 100 | 13.037 | 11.058 | -15.2% | 1613.39 KB → 1611.49 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES ... RETURNING id | CreateMultiple, returns ids, 1000 | 54.439 | 55.464 | +1.9% | 2302.53 KB → 2302.44 KB |
| CreateMultipleBenchmarks | Raw unnest arrays ... RETURNING id | CreateMultiple, returns ids, 1000 | 22.118 | 21.709 | -1.8% | 155.53 KB → 155.49 KB |
| CreateMultipleBenchmarks | Raw NpgsqlBatch of single-row INSERTs | CreateMultiple, returns ids, 1000 | 72.965 | 68.654 | -5.9% | 2250.11 KB → 2250.08 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync | CreateMultiple, returns ids, 1000 | 20.486 | 19.893 | -2.9% | 565.75 KB → 565.74 KB |
| CreateMultipleBenchmarks | EF Core AddRange (typed) | CreateMultiple, returns ids, 1000 | 103.794 | 117.793 | +13.5% | 15126.12 KB → 15124.5 KB |
| CreateMultipleBenchmarks | EF Core AddRange (property bag) | CreateMultiple, returns ids, 1000 | 117.592 | 118.288 | +0.6% | 15857.87 KB → 15858.17 KB |
| CreateMultipleBenchmarks | Raw multi-row VALUES ... RETURNING id | CreateMultiple, returns ids, 10000 | 222.869 | 228.785 | +2.7% | 23582.27 KB → 23582.71 KB |
| CreateMultipleBenchmarks | Raw unnest arrays ... RETURNING id | CreateMultiple, returns ids, 10000 | 105.507 | 99.543 | -5.7% | 1467.34 KB → 1467.4 KB |
| CreateMultipleBenchmarks | Raw NpgsqlBatch of single-row INSERTs | CreateMultiple, returns ids, 10000 | 677.546 | 671.428 | -0.9% | 22447.62 KB → 22447.38 KB |
| CreateMultipleBenchmarks | ARX CreateMultipleAsync | CreateMultiple, returns ids, 10000 | 113.717 | 117.819 | +3.6% | 5498.97 KB → 5498.57 KB |
| CreateMultipleBenchmarks | EF Core AddRange (typed) | CreateMultiple, returns ids, 10000 | 1038.338 | 983.994 | -5.2% | 142640.06 KB → 142639.83 KB |
| CreateMultipleBenchmarks | EF Core AddRange (property bag) | CreateMultiple, returns ids, 10000 | 1023.539 | 1038.405 | +1.5% | 149911.3 KB → 149911.7 KB |
| UpdateBenchmarks | Raw Npgsql (typed, $n) | Update by id (10 columns) | 1.086 | 1.189 | +9.5% | 4.28 KB → 4.24 KB |
| UpdateBenchmarks | ARX UpdateAsync | Update by id (10 columns) | 1.136 | 1.111 | -2.2% | 15.8 KB → 15.8 KB |
| UpdateBenchmarks | Dapper (POCO) | Update by id (10 columns) | 1.109 | 1.206 | +8.7% | 6.26 KB → 6.23 KB |
| UpdateBenchmarks | EF Core Attach + Modified + SaveChanges | Update by id (10 columns) | 1.562 | 1.446 | -7.4% | 53.73 KB → 53.68 KB |
| UpdateBenchmarks | EF Core ExecuteUpdateAsync | Update by id (10 columns) | 1.915 | 1.951 | +1.9% | 65.34 KB → 65.81 KB |
| UpdateBenchmarks | Raw Npgsql: SELECT then UPDATE | Update, load then save (2 round trips) | 1.802 | 1.667 | -7.5% | 6.37 KB → 6.37 KB |
| UpdateBenchmarks | EF Core tracked: Find, modify, SaveChanges | Update, load then save (2 round trips) | 2.675 | 2.463 | -7.9% | 55.22 KB → 54.97 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM (VALUES ...) | 1 | 1.269 | 1.174 | -7.5% | 8.07 KB → 8.09 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM unnest(arrays) | 1 | 1.385 | 1.408 | +1.7% | 9.91 KB → 9.9 KB |
| UpdateMultipleBenchmarks | Raw NpgsqlBatch of single-row UPDATEs | 1 | 1.127 | 1.113 | -1.2% | 4.37 KB → 4.34 KB |
| UpdateMultipleBenchmarks | ARX UpdateMultipleAsync | 1 | 1.147 | 1.056 | -7.9% | 15.76 KB → 15.75 KB |
| UpdateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | 1 | 1.129 | 1.119 | -0.9% | 6.34 KB → 6.31 KB |
| UpdateMultipleBenchmarks | EF Core AttachRange + Modified + SaveChanges | 1 | 1.673 | 1.381 | -17.5% | 53.76 KB → 53.74 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM (VALUES ...) | 10 | 1.550 | 1.634 | +5.4% | 37.05 KB → 37.07 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM unnest(arrays) | 10 | 1.554 | 1.542 | -0.8% | 11.2 KB → 11.23 KB |
| UpdateMultipleBenchmarks | Raw NpgsqlBatch of single-row UPDATEs | 10 | 2.218 | 2.256 | +1.7% | 27.34 KB → 27.31 KB |
| UpdateMultipleBenchmarks | ARX UpdateMultipleAsync | 10 | 1.978 | 1.910 | -3.4% | 26.78 KB → 26.75 KB |
| UpdateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | 10 | 10.258 | 10.276 | +0.2% | 39.08 KB → 39.04 KB |
| UpdateMultipleBenchmarks | EF Core AttachRange + Modified + SaveChanges | 10 | 3.378 | 3.252 | -3.7% | 200.61 KB → 200.59 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM (VALUES ...) | 100 | 3.673 | 3.904 | +6.3% | 359.71 KB → 359.66 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM unnest(arrays) | 100 | 2.402 | 2.299 | -4.3% | 24.27 KB → 24.27 KB |
| UpdateMultipleBenchmarks | Raw NpgsqlBatch of single-row UPDATEs | 100 | 11.417 | 10.765 | -5.7% | 258.99 KB → 258.97 KB |
| UpdateMultipleBenchmarks | ARX UpdateMultipleAsync | 100 | 2.588 | 2.684 | +3.7% | 86.72 KB → 86.69 KB |
| UpdateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | 100 | 97.205 | 100.927 | +3.8% | 366.8 KB → 366.88 KB |
| UpdateMultipleBenchmarks | EF Core AttachRange + Modified + SaveChanges | 100 | 13.664 | 13.785 | +0.9% | 1656.31 KB → 1656.33 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM (VALUES ...) | 1000 | 58.159 | 59.023 | +1.5% | 3764.58 KB → 3764.59 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM unnest(arrays) | 1000 | 36.898 | 38.331 | +3.9% | 155.09 KB → 155.23 KB |
| UpdateMultipleBenchmarks | Raw NpgsqlBatch of single-row UPDATEs | 1000 | 104.153 | 102.987 | -1.1% | 2568.76 KB → 2568.7 KB |
| UpdateMultipleBenchmarks | ARX UpdateMultipleAsync | 1000 | 32.003 | 42.781 | +33.7% | 680.84 KB → 680.92 KB |
| UpdateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | 1000 | 1125.753 | 1129.137 | +0.3% | 3643.88 KB → 3643.57 KB |
| UpdateMultipleBenchmarks | EF Core AttachRange + Modified + SaveChanges | 1000 | 141.294 | 145.327 | +2.9% | 16495.19 KB → 16495.19 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM (VALUES ...) | 10000 | 287.163 | 279.830 | -2.6% | 38298.53 KB → 38299.01 KB |
| UpdateMultipleBenchmarks | Raw UPDATE ... FROM unnest(arrays) | 10000 | 125.202 | 138.175 | +10.4% | 1465.13 KB → 1465.02 KB |
| UpdateMultipleBenchmarks | Raw NpgsqlBatch of single-row UPDATEs | 10000 | 1067.554 | 1092.062 | +2.3% | 25635.09 KB → 25635.09 KB |
| UpdateMultipleBenchmarks | ARX UpdateMultipleAsync | 10000 | 159.779 | 165.171 | +3.4% | 6649.11 KB → 6648.79 KB |
| UpdateMultipleBenchmarks | Dapper ExecuteAsync(sql, list): one statement per row | 10000 | 10021.160 | 10036.475 | +0.2% | 36409.5 KB → 36409.5 KB |
| UpdateMultipleBenchmarks | EF Core AttachRange + Modified + SaveChanges | 10000 | 1373.501 | 1391.897 | +1.3% | 154241.9 KB → 154241.85 KB |
| DeleteBenchmarks | Raw Npgsql (typed, $1) | 1.012 | 1.062 | +4.9% | 2.12 KB → 2.09 KB | |
| DeleteBenchmarks | ARX DeleteAsync | 1.132 | 1.000 | -11.7% | 4.64 KB → 4.66 KB | |
| DeleteBenchmarks | Dapper ExecuteAsync | 1.032 | 1.050 | +1.7% | 2.63 KB → 2.62 KB | |
| DeleteBenchmarks | EF Core ExecuteDeleteAsync | 1.214 | 1.594 | +31.3% | 38.89 KB → 38.89 KB | |
| DeleteBenchmarks | EF Core Remove + SaveChanges (stub entity) | 1.358 | 1.275 | -6.1% | 43.71 KB → 43.75 KB | |
| DeleteMultipleSmallBenchmarks | Raw = ANY($1::bigint[]) | 1 | 1.096 | 1.096 | +0.0% | 2.23 KB → 2.26 KB |
| DeleteMultipleSmallBenchmarks | ARX DeleteMultipleAsync | 1 | 1.095 | 1.078 | -1.6% | 4.54 KB → 4.54 KB |
| DeleteMultipleSmallBenchmarks | Raw = ANY($1::bigint[]) | 10 | 1.244 | 1.110 | -10.8% | 2.29 KB → 2.31 KB |
| DeleteMultipleSmallBenchmarks | ARX DeleteMultipleAsync | 10 | 1.152 | 1.222 | +6.1% | 4.7 KB → 4.75 KB |
| DeleteMultipleSmallBenchmarks | Raw = ANY($1::bigint[]) | 50 | 1.273 | 1.214 | -4.6% | 2.62 KB → 2.66 KB |
| DeleteMultipleSmallBenchmarks | ARX DeleteMultipleAsync | 50 | 1.201 | 1.193 | -0.7% | 5.04 KB → 5.03 KB |
The full BenchmarkDotNet reports of both runs are in the worktrees' BenchmarkDotNet.Artifacts/results/ (not
committed); the table above is every row of them.
2026-11-08: full run
Full run, every operation (2026-11-08)
All 352 benchmarks in one run (--filter '*', 14:54 to 16:02), at commit 230104f (Retrieve hardened and tuned, injection check in place), after --verify passed. The summary of these numbers is SUMMARY.md. The large-command caveat (Windows Docker port forwarding) applies: the raw binary COPY rows at ~50 ms and the raw batch-scope rows at 50 per batch (~5 s) are the 50 ms stall per round trip on a reused connection, not the cost of the approach.
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2), Intel Core i7-8750H 2.20GHz, 6 cores / 12 threads
.NET SDK 10.0.403, .NET 10.0.14 X64 RyuJIT x86-64-v3; PostgreSQL 16 (postgres:16-alpine) in Docker Desktop; Npgsql 8.0.3
Standard = 3 warmups, 8 iterations; LargeLoad = 1 warmup, 3 single-operation iterations; SingleOperation = 1 warmup, 12
Create.CreateBenchmarks
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed, $n)' | Create (10 columns, returns id) | 1.115 ms | 0.3428 ms | 0.1522 ms | 1.01 | 0.17 | - | 3.92 KB | 1.00 |
| 'ARX CreateAsync' | Create (10 columns, returns id) | 1.127 ms | 0.1129 ms | 0.0591 ms | 1.02 | 0.12 | 1.9531 | 12.08 KB | 3.08 |
| 'Dapper (POCO)' | Create (10 columns, returns id) | 1.166 ms | 0.2190 ms | 0.0972 ms | 1.06 | 0.14 | - | 5.89 KB | 1.50 |
| 'Dapper (dynamic: DynamicParameters)' | Create (10 columns, returns id) | 1.087 ms | 0.1052 ms | 0.0467 ms | 0.99 | 0.11 | - | 8.48 KB | 2.16 |
| 'EF Core (typed, new context)' | Create (10 columns, returns id) | 1.939 ms | 0.7203 ms | 0.3767 ms | 1.76 | 0.38 | 7.8125 | 52.92 KB | 13.50 |
| 'EF Core (property bag, new context)' | Create (10 columns, returns id) | 1.561 ms | 0.4069 ms | 0.2128 ms | 1.42 | 0.24 | 11.7188 | 59.61 KB | 15.21 |
| 'Raw Npgsql, option code written directly' | Create with selection set (11 columns) | 1.142 ms | 0.2959 ms | 0.1314 ms | 1.01 | 0.15 | - | 4.3 KB | 1.00 |
| 'ARX CreateAsync with ArxSelectionSetValue (catalog check)' | Create with selection set (11 columns) | 1.114 ms | 0.1848 ms | 0.0820 ms | 0.98 | 0.12 | 1.9531 | 12.95 KB | 3.01 |
Create.CreateMultipleBenchmarks
| Method | Categories | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw binary COPY' | CreateMultiple, ids not needed | 1 | 49.445 ms | 0.1393 ms | 0.0619 ms | 1.00 | 0.00 | - | - | - | 3.72 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 1 | 1.031 ms | 0.0692 ms | 0.0362 ms | 0.02 | 0.00 | - | - | - | 5.82 KB | 1.56 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 1 | 1.029 ms | 0.1347 ms | 0.0598 ms | 0.02 | 0.00 | - | - | - | 5.91 KB | 1.59 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 1 | 1.388 ms | 0.4711 ms | 0.2464 ms | 0.03 | 0.00 | 1.9531 | - | - | 12.53 KB | 3.37 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 10 | 49.838 ms | 0.8062 ms | 0.4216 ms | 1.00 | 0.01 | - | - | - | 4.16 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 10 | 1.405 ms | 0.2138 ms | 0.1118 ms | 0.03 | 0.00 | 3.9063 | - | - | 26.81 KB | 6.45 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 10 | 9.292 ms | 0.6805 ms | 0.3559 ms | 0.19 | 0.01 | - | - | - | 36.31 KB | 8.73 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 10 | 1.360 ms | 0.0836 ms | 0.0437 ms | 0.03 | 0.00 | 7.8125 | - | - | 38.56 KB | 9.27 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 100 | 49.752 ms | 0.9241 ms | 0.4833 ms | 1.00 | 0.01 | - | - | - | 8.38 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 100 | 3.822 ms | 0.5178 ms | 0.2708 ms | 0.08 | 0.01 | 39.0625 | 23.4375 | - | 243.89 KB | 29.12 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 100 | 89.302 ms | 8.3693 ms | 4.3773 ms | 1.80 | 0.08 | - | - | - | 340.7 KB | 40.68 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 100 | 2.373 ms | 0.0907 ms | 0.0474 ms | 0.05 | 0.00 | 11.7188 | - | - | 70.6 KB | 8.43 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 1000 | 50.187 ms | 0.2407 ms | 0.0858 ms | 1.00 | 0.00 | - | - | - | 50.69 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 1000 | 57.165 ms | 7.9716 ms | 4.1693 ms | 1.14 | 0.08 | 300.0000 | 200.0000 | - | 2294.61 KB | 45.27 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 1000 | 939.121 ms | 150.6958 ms | 78.8168 ms | 18.71 | 1.48 | - | - | - | 3385.58 KB | 66.79 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 1000 | 23.400 ms | 8.2251 ms | 4.3019 ms | 0.47 | 0.08 | 93.7500 | 62.5000 | - | 565.77 KB | 11.16 |
| 'Raw binary COPY' | CreateMultiple, ids not needed | 10000 | 68.056 ms | 7.4692 ms | 3.3164 ms | 1.00 | 0.07 | - | - | - | 472.69 KB | 1.00 |
| 'Raw multi-row VALUES (no RETURNING)' | CreateMultiple, ids not needed | 10000 | 215.277 ms | 28.4223 ms | 14.8654 ms | 3.17 | 0.26 | 3000.0000 | 1500.0000 | - | 23503.2 KB | 49.72 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | CreateMultiple, ids not needed | 10000 | 9,587.557 ms | 447.5517 ms | 198.7157 ms | 141.18 | 7.27 | 7000.0000 | - | - | 33831.2 KB | 71.57 |
| 'ARX CreateMultipleAsync (still returns ids)' | CreateMultiple, ids not needed | 10000 | 126.763 ms | 18.6855 ms | 9.7729 ms | 1.87 | 0.16 | 666.6667 | 333.3333 | - | 5498.72 KB | 11.63 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 1 | 1.084 ms | 0.1508 ms | 0.0789 ms | 1.00 | 0.10 | - | - | - | 5.76 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 1 | 1.422 ms | 0.1499 ms | 0.0784 ms | 1.32 | 0.11 | 1.9531 | - | - | 9.89 KB | 1.72 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 1 | 1.080 ms | 0.0594 ms | 0.0212 ms | 1.00 | 0.07 | - | - | - | 3.9 KB | 0.68 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 1 | 1.047 ms | 0.0964 ms | 0.0428 ms | 0.97 | 0.07 | 1.9531 | - | - | 12.58 KB | 2.19 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 1 | 1.350 ms | 0.1306 ms | 0.0683 ms | 1.25 | 0.10 | 9.7656 | - | - | 52.88 KB | 9.18 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 1 | 1.642 ms | 0.6161 ms | 0.3222 ms | 1.52 | 0.30 | 11.7188 | - | - | 59.67 KB | 10.36 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 10 | 1.476 ms | 0.3532 ms | 0.1847 ms | 1.01 | 0.17 | 3.9063 | - | - | 26.83 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 10 | 1.430 ms | 0.0916 ms | 0.0479 ms | 0.98 | 0.12 | 1.9531 | - | - | 11.21 KB | 0.42 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 10 | 1.815 ms | 0.0528 ms | 0.0234 ms | 1.25 | 0.15 | 3.9063 | - | - | 24.02 KB | 0.90 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 10 | 1.343 ms | 0.0714 ms | 0.0374 ms | 0.92 | 0.11 | 7.8125 | - | - | 38.58 KB | 1.44 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 10 | 3.194 ms | 0.7868 ms | 0.4115 ms | 2.19 | 0.38 | 39.0625 | 7.8125 | - | 190.04 KB | 7.08 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 10 | 3.168 ms | 0.7775 ms | 0.4066 ms | 2.18 | 0.37 | 39.0625 | 7.8125 | - | 203.31 KB | 7.58 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 100 | 3.977 ms | 1.8090 ms | 0.9461 ms | 1.05 | 0.32 | 39.0625 | 31.2500 | - | 244.59 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 100 | 2.224 ms | 0.0638 ms | 0.0228 ms | 0.58 | 0.12 | 3.9063 | - | - | 24.26 KB | 0.10 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 100 | 8.120 ms | 0.6482 ms | 0.2878 ms | 2.13 | 0.43 | 31.2500 | - | - | 226.79 KB | 0.93 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 100 | 2.484 ms | 0.2843 ms | 0.1487 ms | 0.65 | 0.13 | 11.7188 | - | - | 70.62 KB | 0.29 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 100 | 11.657 ms | 1.2091 ms | 0.5368 ms | 3.06 | 0.62 | 250.0000 | 125.0000 | - | 1535.02 KB | 6.28 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 100 | 14.137 ms | 3.5247 ms | 1.8435 ms | 3.72 | 0.87 | 222.2222 | 111.1111 | - | 1616.59 KB | 6.61 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 1000 | 55.329 ms | 7.9352 ms | 4.1503 ms | 1.00 | 0.10 | 272.7273 | 181.8182 | - | 2302.54 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 1000 | 26.079 ms | 7.2260 ms | 3.7793 ms | 0.47 | 0.07 | 31.2500 | - | - | 155.5 KB | 0.07 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 1000 | 67.560 ms | 2.2815 ms | 0.8136 ms | 1.23 | 0.09 | 285.7143 | 142.8571 | - | 2250.04 KB | 0.98 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 1000 | 23.881 ms | 11.5601 ms | 6.0462 ms | 0.43 | 0.11 | 93.7500 | 31.2500 | - | 565.72 KB | 0.25 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 1000 | 122.316 ms | 16.2448 ms | 7.2128 ms | 2.22 | 0.20 | 2333.3333 | 1333.3333 | 333.3333 | 15124.65 KB | 6.57 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 1000 | 112.180 ms | 21.2139 ms | 9.4191 ms | 2.04 | 0.22 | 2333.3333 | 1333.3333 | 333.3333 | 15858.07 KB | 6.89 |
| 'Raw multi-row VALUES ... RETURNING id' | CreateMultiple, returns ids | 10000 | 213.829 ms | 38.4811 ms | 20.1263 ms | 1.01 | 0.13 | 3000.0000 | 1000.0000 | - | 23583.43 KB | 1.00 |
| 'Raw unnest arrays ... RETURNING id' | CreateMultiple, returns ids | 10000 | 112.254 ms | 28.6330 ms | 12.7132 ms | 0.53 | 0.07 | - | - | - | 1467.91 KB | 0.06 |
| 'Raw NpgsqlBatch of single-row INSERTs' | CreateMultiple, returns ids | 10000 | 713.384 ms | 62.5639 ms | 32.7221 ms | 3.36 | 0.33 | 3000.0000 | 1000.0000 | - | 22447.62 KB | 0.95 |
| 'ARX CreateMultipleAsync' | CreateMultiple, returns ids | 10000 | 118.556 ms | 25.5445 ms | 13.3603 ms | 0.56 | 0.08 | 666.6667 | 333.3333 | - | 5499.03 KB | 0.23 |
| 'EF Core AddRange (typed)' | CreateMultiple, returns ids | 10000 | 1,106.282 ms | 200.3387 ms | 88.9516 ms | 5.21 | 0.61 | 20000.0000 | 10000.0000 | 1000.0000 | 142640.17 KB | 6.05 |
| 'EF Core AddRange (property bag)' | CreateMultiple, returns ids | 10000 | 1,003.249 ms | 48.2017 ms | 25.2104 ms | 4.73 | 0.43 | 21000.0000 | 10000.0000 | 1000.0000 | 149911.56 KB | 6.36 |
Create.CreateMultipleMatrixBenchmarks
| Method | Shape | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw multi-row VALUES ... RETURNING id' | 1000c x 1000r | 2,351.613 ms | 664.569 ms | 36.4273 ms | 2,331.687 ms | 1.00 | 0.02 | 30000.0000 | 16000.0000 | 2000.0000 | 222956.38 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1000c x 1000r | 540.209 ms | 1,875.409 ms | 102.7975 ms | 507.045 ms | 0.23 | 0.04 | - | - | - | 4401.09 KB | 0.020 |
| 'ARX CreateMultipleAsync' | 1000c x 1000r | 665.355 ms | 3,084.020 ms | 169.0456 ms | 670.952 ms | 0.28 | 0.06 | 2000.0000 | 1000.0000 | - | 12555.04 KB | 0.056 |
| 'Raw binary COPY (no ids)' | 1000c x 1000r | 224.707 ms | 213.065 ms | 11.6788 ms | 231.288 ms | 0.10 | 0.00 | - | - | - | 265.14 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 1000c x 5000r | 11,776.134 ms | 8,475.665 ms | 464.5798 ms | 11,699.814 ms | 1.00 | 0.05 | 145000.0000 | 73000.0000 | 2000.0000 | 1114093.12 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1000c x 5000r | 2,161.122 ms | 1,664.522 ms | 91.2381 ms | 2,149.595 ms | 0.18 | 0.01 | 3000.0000 | 1000.0000 | - | 20353.89 KB | 0.018 |
| 'ARX CreateMultipleAsync' | 1000c x 5000r | 2,762.898 ms | 4,291.495 ms | 235.2313 ms | 2,738.344 ms | 0.23 | 0.02 | 9000.0000 | 4000.0000 | - | 61486.23 KB | 0.055 |
| 'Raw binary COPY (no ids)' | 1000c x 5000r | 819.721 ms | 777.279 ms | 42.6053 ms | 827.517 ms | 0.07 | 0.00 | - | - | - | 286.59 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 10000r | 2,613.798 ms | 4,723.484 ms | 258.9101 ms | 2,560.381 ms | 1.01 | 0.12 | 30000.0000 | 16000.0000 | 2000.0000 | 222215.41 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 100c x 10000r | 488.208 ms | 1,525.207 ms | 83.6017 ms | 478.785 ms | 0.19 | 0.03 | - | - | - | 3810.36 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 100c x 10000r | 764.617 ms | 6,632.041 ms | 363.5245 ms | 569.838 ms | 0.29 | 0.12 | 2000.0000 | 1000.0000 | - | 13567.74 KB | 0.061 |
| 'Raw binary COPY (no ids)' | 100c x 10000r | 195.533 ms | 304.734 ms | 16.7035 ms | 201.389 ms | 0.08 | 0.01 | - | - | - | 29.13 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 1000r | 294.136 ms | 700.102 ms | 38.3750 ms | 290.174 ms | 1.01 | 0.16 | 3000.0000 | 2000.0000 | 1000.0000 | 22194.05 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 100c x 1000r | 126.728 ms | 396.826 ms | 21.7514 ms | 115.414 ms | 0.44 | 0.08 | - | - | - | 488.55 KB | 0.022 |
| 'ARX CreateMultipleAsync' | 100c x 1000r | 148.074 ms | 343.597 ms | 18.8337 ms | 149.791 ms | 0.51 | 0.08 | - | - | - | 1491.62 KB | 0.067 |
| 'Raw binary COPY (no ids)' | 100c x 1000r | 126.113 ms | 125.404 ms | 6.8738 ms | 125.095 ms | 0.43 | 0.05 | - | - | - | 25.83 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 50000r | 11,393.456 ms | 4,897.384 ms | 268.4422 ms | 11,320.770 ms | 1.00 | 0.03 | 144000.0000 | 72000.0000 | 1000.0000 | 1111481.84 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 100c x 50000r | 2,030.714 ms | 2,160.822 ms | 118.4419 ms | 2,052.153 ms | 0.18 | 0.01 | 3000.0000 | 2000.0000 | - | 18918.88 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 100c x 50000r | 2,676.892 ms | 1,118.469 ms | 61.3071 ms | 2,675.867 ms | 0.24 | 0.01 | 10000.0000 | 5000.0000 | - | 67723.16 KB | 0.061 |
| 'Raw binary COPY (no ids)' | 100c x 50000r | 766.948 ms | 632.164 ms | 34.6511 ms | 784.382 ms | 0.07 | 0.00 | - | - | - | 45.77 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 100000r | 2,045.983 ms | 616.329 ms | 33.7831 ms | 2,038.159 ms | 1.00 | 0.02 | 30000.0000 | 15000.0000 | 1000.0000 | 223725.04 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 100000r | 868.916 ms | 1,648.336 ms | 90.3508 ms | 870.350 ms | 0.42 | 0.04 | - | - | - | 4930.51 KB | 0.022 |
| 'ARX CreateMultipleAsync' | 10c x 100000r | 993.255 ms | 1,578.745 ms | 86.5363 ms | 1,034.404 ms | 0.49 | 0.04 | 3000.0000 | 1000.0000 | - | 32050.2 KB | 0.143 |
| 'Raw binary COPY (no ids)' | 10c x 100000r | 315.411 ms | 205.102 ms | 11.2423 ms | 314.505 ms | 0.15 | 0.01 | - | - | - | 10.4 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 10000r | 308.652 ms | 187.393 ms | 10.2716 ms | 304.083 ms | 1.00 | 0.04 | 3000.0000 | 2000.0000 | 1000.0000 | 22327.34 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 10000r | 111.195 ms | 106.071 ms | 5.8141 ms | 108.848 ms | 0.36 | 0.02 | - | - | - | 968.01 KB | 0.043 |
| 'ARX CreateMultipleAsync' | 10c x 10000r | 146.068 ms | 251.336 ms | 13.7765 ms | 143.731 ms | 0.47 | 0.04 | - | - | - | 3202.77 KB | 0.143 |
| 'Raw binary COPY (no ids)' | 10c x 10000r | 122.928 ms | 278.035 ms | 15.2400 ms | 117.894 ms | 0.40 | 0.04 | - | - | - | 5.14 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 1000r | 63.324 ms | 84.258 ms | 4.6185 ms | 64.501 ms | 1.00 | 0.09 | - | - | - | 2228.75 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 1000r | 56.507 ms | 38.584 ms | 2.1149 ms | 57.531 ms | 0.90 | 0.07 | - | - | - | 105.51 KB | 0.047 |
| 'ARX CreateMultipleAsync' | 10c x 1000r | 58.751 ms | 72.862 ms | 3.9938 ms | 58.295 ms | 0.93 | 0.08 | - | - | - | 382.89 KB | 0.172 |
| 'Raw binary COPY (no ids)' | 10c x 1000r | 51.544 ms | 96.081 ms | 5.2665 ms | 48.876 ms | 0.82 | 0.09 | - | - | - | 4.32 KB | 0.002 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 500000r | 10,648.891 ms | 9,544.840 ms | 523.1849 ms | 10,455.446 ms | 1.00 | 0.06 | 145000.0000 | 73000.0000 | 1000.0000 | 1118689.45 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 10c x 500000r | 3,735.714 ms | 1,222.920 ms | 67.0324 ms | 3,738.178 ms | 0.35 | 0.02 | - | - | - | 26673.02 KB | 0.024 |
| 'ARX CreateMultipleAsync' | 10c x 500000r | 4,968.490 ms | 11,519.009 ms | 631.3957 ms | 5,043.552 ms | 0.47 | 0.06 | 19000.0000 | 9000.0000 | - | 160524.39 KB | 0.143 |
| 'Raw binary COPY (no ids)' | 10c x 500000r | 1,498.419 ms | 963.733 ms | 52.8254 ms | 1,496.024 ms | 0.14 | 0.01 | - | - | - | 37.08 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 1000r | 3,715.213 ms | 1,662.955 ms | 91.1522 ms | 3,700.587 ms | 1.00 | 0.03 | 49000.0000 | 26000.0000 | 3000.0000 | 357447.07 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1599c x 1000r | 768.075 ms | 812.244 ms | 44.5219 ms | 783.270 ms | 0.21 | 0.01 | 1000.0000 | - | - | 7977.81 KB | 0.022 |
| 'ARX CreateMultipleAsync' | 1599c x 1000r | 930.292 ms | 1,435.120 ms | 78.6638 ms | 965.192 ms | 0.25 | 0.02 | 3000.0000 | 1000.0000 | - | 21201.42 KB | 0.059 |
| 'Raw binary COPY (no ids)' | 1599c x 1000r | 338.365 ms | 522.176 ms | 28.6222 ms | 329.210 ms | 0.09 | 0.01 | - | - | - | 429.94 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 3126r | 11,841.074 ms | 13,942.389 ms | 764.2294 ms | 12,070.311 ms | 1.00 | 0.08 | 147000.0000 | 75000.0000 | 3000.0000 | 1117298.5 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1599c x 3126r | 2,343.722 ms | 1,917.023 ms | 105.0785 ms | 2,291.874 ms | 0.20 | 0.01 | 4000.0000 | 2000.0000 | - | 23424.1 KB | 0.021 |
| 'ARX CreateMultipleAsync' | 1599c x 3126r | 3,458.399 ms | 11,030.681 ms | 604.6288 ms | 3,372.480 ms | 0.29 | 0.05 | 10000.0000 | 5000.0000 | - | 65200.08 KB | 0.058 |
| 'Raw binary COPY (no ids)' | 1599c x 3126r | 1,007.823 ms | 3,934.467 ms | 215.6614 ms | 895.143 ms | 0.09 | 0.02 | - | - | - | 445.27 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 100000r | 509.085 ms | 860.508 ms | 47.1674 ms | 503.399 ms | 1.01 | 0.11 | 3000.0000 | 1000.0000 | - | 23763.52 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 100000r | 393.647 ms | 217.622 ms | 11.9286 ms | 393.192 ms | 0.78 | 0.06 | - | - | - | 1216.34 KB | 0.051 |
| 'ARX CreateMultipleAsync' | 1c x 100000r | 510.881 ms | 355.883 ms | 19.5072 ms | 508.237 ms | 1.01 | 0.09 | 2000.0000 | 1000.0000 | - | 21305.95 KB | 0.897 |
| 'Raw binary COPY (no ids)' | 1c x 100000r | 215.330 ms | 110.207 ms | 6.0408 ms | 212.299 ms | 0.43 | 0.04 | - | - | - | 2.39 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 10000r | 86.395 ms | 99.020 ms | 5.4276 ms | 83.545 ms | 1.00 | 0.08 | - | - | - | 2787.85 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 10000r | 87.624 ms | 25.250 ms | 1.3840 ms | 87.417 ms | 1.02 | 0.06 | - | - | - | 591.52 KB | 0.212 |
| 'ARX CreateMultipleAsync' | 1c x 10000r | 93.411 ms | 199.094 ms | 10.9130 ms | 89.398 ms | 1.08 | 0.12 | - | - | - | 2589.13 KB | 0.929 |
| 'Raw binary COPY (no ids)' | 1c x 10000r | 67.872 ms | 83.655 ms | 4.5854 ms | 68.823 ms | 0.79 | 0.06 | - | - | - | 2.39 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 1000r | 8.544 ms | 6.996 ms | 0.3835 ms | 8.346 ms | 1.00 | 0.05 | - | - | - | 293.62 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 1000r | 6.731 ms | 12.318 ms | 0.6752 ms | 6.460 ms | 0.79 | 0.07 | - | - | - | 63.32 KB | 0.216 |
| 'ARX CreateMultipleAsync' | 1c x 1000r | 6.900 ms | 19.603 ms | 1.0745 ms | 6.723 ms | 0.81 | 0.11 | - | - | - | 267.66 KB | 0.912 |
| 'Raw binary COPY (no ids)' | 1c x 1000r | 51.023 ms | 29.362 ms | 1.6095 ms | 50.325 ms | 5.98 | 0.28 | - | - | - | 2.21 KB | 0.008 |
| 'Raw multi-row VALUES ... RETURNING id' | 1c x 500000r | 2,255.518 ms | 1,759.718 ms | 96.4561 ms | 2,270.029 ms | 1.00 | 0.05 | 14000.0000 | 7000.0000 | - | 119522.71 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 1c x 500000r | 1,617.122 ms | 1,700.604 ms | 93.2159 ms | 1,591.957 ms | 0.72 | 0.04 | - | - | - | 6051.64 KB | 0.051 |
| 'ARX CreateMultipleAsync' | 1c x 500000r | 1,873.405 ms | 616.523 ms | 33.7937 ms | 1,878.287 ms | 0.83 | 0.03 | 14000.0000 | 7000.0000 | - | 106798.87 KB | 0.894 |
| 'Raw binary COPY (no ids)' | 1c x 500000r | 805.544 ms | 72.190 ms | 3.9570 ms | 803.800 ms | 0.36 | 0.01 | - | - | - | 2.21 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 250c x 10000r | 5,862.994 ms | 3,870.192 ms | 212.1383 ms | 5,850.928 ms | 1.00 | 0.04 | 73000.0000 | 37000.0000 | 2000.0000 | 555752.8 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 250c x 10000r | 964.259 ms | 434.614 ms | 23.8227 ms | 972.664 ms | 0.16 | 0.01 | 1000.0000 | - | - | 9614.94 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 250c x 10000r | 1,253.000 ms | 2,403.669 ms | 131.7532 ms | 1,178.210 ms | 0.21 | 0.02 | 5000.0000 | 2000.0000 | - | 31234.87 KB | 0.056 |
| 'Raw binary COPY (no ids)' | 250c x 10000r | 359.216 ms | 595.627 ms | 32.6483 ms | 376.518 ms | 0.06 | 0.01 | - | - | - | 62.08 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 250c x 1000r | 605.313 ms | 279.870 ms | 15.3406 ms | 597.230 ms | 1.00 | 0.03 | 8000.0000 | 4000.0000 | 1000.0000 | 55811.25 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 250c x 1000r | 213.168 ms | 443.017 ms | 24.2833 ms | 204.927 ms | 0.35 | 0.04 | - | - | - | 1100.63 KB | 0.020 |
| 'ARX CreateMultipleAsync' | 250c x 1000r | 320.490 ms | 844.990 ms | 46.3168 ms | 309.236 ms | 0.53 | 0.07 | - | - | - | 3293.67 KB | 0.059 |
| 'Raw binary COPY (no ids)' | 250c x 1000r | 181.794 ms | 1,574.424 ms | 86.2995 ms | 181.082 ms | 0.30 | 0.12 | - | - | - | 60.74 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 250c x 20000r | 11,789.179 ms | 6,097.724 ms | 334.2368 ms | 11,757.834 ms | 1.00 | 0.03 | 145000.0000 | 73000.0000 | 2000.0000 | 1111537.39 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 250c x 20000r | 2,157.046 ms | 1,128.598 ms | 61.8623 ms | 2,140.341 ms | 0.18 | 0.01 | 3000.0000 | 1000.0000 | - | 19084.32 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 250c x 20000r | 2,750.280 ms | 3,950.003 ms | 216.5130 ms | 2,786.770 ms | 0.23 | 0.02 | 10000.0000 | 5000.0000 | - | 62262.66 KB | 0.056 |
| 'Raw binary COPY (no ids)' | 250c x 20000r | 825.166 ms | 2,365.920 ms | 129.6841 ms | 774.292 ms | 0.07 | 0.01 | - | - | - | 63.53 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 500c x 10000r | 11,466.195 ms | 2,870.160 ms | 157.3232 ms | 11,534.165 ms | 1.00 | 0.02 | 146000.0000 | 74000.0000 | 2000.0000 | 1112066.98 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 500c x 10000r | 1,992.086 ms | 1,596.661 ms | 87.5184 ms | 1,953.781 ms | 0.17 | 0.01 | 3000.0000 | 1000.0000 | - | 19409.09 KB | 0.017 |
| 'ARX CreateMultipleAsync' | 500c x 10000r | 3,141.333 ms | 5,492.300 ms | 301.0515 ms | 3,086.860 ms | 0.27 | 0.02 | 9000.0000 | 4000.0000 | - | 60950.95 KB | 0.055 |
| 'Raw binary COPY (no ids)' | 500c x 10000r | 711.727 ms | 335.648 ms | 18.3980 ms | 720.061 ms | 0.06 | 0.00 | - | - | - | 193.27 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 500c x 1000r | 1,315.480 ms | 224.808 ms | 12.3225 ms | 1,319.681 ms | 1.00 | 0.01 | 16000.0000 | 9000.0000 | 2000.0000 | 111658.2 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 500c x 1000r | 360.927 ms | 1,836.705 ms | 100.6760 ms | 381.532 ms | 0.27 | 0.07 | - | - | - | 2190.95 KB | 0.020 |
| 'ARX CreateMultipleAsync' | 500c x 1000r | 448.400 ms | 2,883.082 ms | 158.0315 ms | 521.994 ms | 0.34 | 0.10 | 1000.0000 | - | - | 6376.44 KB | 0.057 |
| 'Raw binary COPY (no ids)' | 500c x 1000r | 257.898 ms | 2,612.971 ms | 143.2258 ms | 220.165 ms | 0.20 | 0.09 | - | - | - | 133.63 KB | 0.001 |
| 'Raw multi-row VALUES ... RETURNING id' | 50c x 100000r | 11,252.870 ms | 950.967 ms | 52.1257 ms | 11,245.872 ms | 1.00 | 0.01 | 145000.0000 | 73000.0000 | 2000.0000 | 1113115.19 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 50c x 100000r | 2,318.088 ms | 1,381.227 ms | 75.7097 ms | 2,333.797 ms | 0.21 | 0.01 | 1000.0000 | - | - | 19664.73 KB | 0.018 |
| 'ARX CreateMultipleAsync' | 50c x 100000r | 2,890.898 ms | 440.245 ms | 24.1313 ms | 2,882.728 ms | 0.26 | 0.00 | 10000.0000 | 5000.0000 | - | 78101.47 KB | 0.070 |
| 'Raw binary COPY (no ids)' | 50c x 100000r | 857.132 ms | 149.260 ms | 8.1814 ms | 853.115 ms | 0.08 | 0.00 | - | - | - | 57.28 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 50c x 10000r | 1,245.841 ms | 990.439 ms | 54.2893 ms | 1,265.581 ms | 1.00 | 0.05 | 15000.0000 | 8000.0000 | 1000.0000 | 111758.3 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 50c x 10000r | 317.661 ms | 1,105.263 ms | 60.5832 ms | 351.635 ms | 0.26 | 0.04 | - | - | - | 1991.02 KB | 0.018 |
| 'ARX CreateMultipleAsync' | 50c x 10000r | 396.049 ms | 213.595 ms | 11.7079 ms | 392.501 ms | 0.32 | 0.01 | 1000.0000 | - | - | 7828.28 KB | 0.070 |
| 'Raw binary COPY (no ids)' | 50c x 10000r | 213.615 ms | 2,804.006 ms | 153.6970 ms | 125.620 ms | 0.17 | 0.11 | - | - | - | 19.03 KB | 0.000 |
| 'Raw multi-row VALUES ... RETURNING id' | 50c x 1000r | 129.667 ms | 578.685 ms | 31.7197 ms | 113.711 ms | 1.04 | 0.30 | 1000.0000 | - | - | 11476.09 KB | 1.000 |
| 'Raw unnest arrays ... RETURNING id' | 50c x 1000r | 85.167 ms | 31.528 ms | 1.7281 ms | 85.388 ms | 0.68 | 0.13 | - | - | - | 278.04 KB | 0.024 |
| 'ARX CreateMultipleAsync' | 50c x 1000r | 48.562 ms | 54.326 ms | 2.9778 ms | 47.908 ms | 0.39 | 0.08 | - | - | - | 877.21 KB | 0.076 |
| 'Raw binary COPY (no ids)' | 50c x 1000r | 72.561 ms | 37.585 ms | 2.0602 ms | 72.665 ms | 0.58 | 0.11 | - | - | - | 13.85 KB | 0.001 |
Create.CreateMultipleSpecialCaseBenchmarks
| Method | Categories | Mean | Error | StdDev | Median | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw multi-row, text param ::jsonb' | JSONB column (1,000 rows, 11 columns) | 54.11 ms | 28.682 ms | 22.393 ms | 42.58 ms | 1.16 | 0.65 | 2747.22 KB | 1.00 |
| 'ARX, ArxJsonB' | JSONB column (1,000 rows, 11 columns) | 41.77 ms | 30.144 ms | 23.535 ms | 37.65 ms | 0.90 | 0.61 | 701.02 KB | 0.26 |
| 'Raw multi-row, all columns' | Row shapes (1,000 rows) | 70.98 ms | 7.553 ms | 5.897 ms | 68.62 ms | 1.01 | 0.11 | 2306.91 KB | 1.00 |
| 'ARX, same columns, same order (1 statement)' | Row shapes (1,000 rows) | 50.66 ms | 27.610 ms | 21.556 ms | 59.53 ms | 0.72 | 0.30 | 683.64 KB | 0.30 |
| 'ARX, same columns, shuffled order per row' | Row shapes (1,000 rows) | 90.46 ms | 22.262 ms | 17.380 ms | 84.78 ms | 1.28 | 0.26 | 5642.21 KB | 2.45 |
| 'ARX, two shapes alternating (10 / 9 columns)' | Row shapes (1,000 rows) | 100.29 ms | 39.991 ms | 31.222 ms | 90.00 ms | 1.42 | 0.44 | 5590.98 KB | 2.42 |
| 'ARX, random column subset per row' | Row shapes (1,000 rows) | 94.07 ms | 30.773 ms | 24.026 ms | 82.81 ms | 1.33 | 0.34 | 3551.01 KB | 1.54 |
| 'Raw multi-row, option codes written directly' | Selection sets (1,000 rows, 11 columns) | 70.36 ms | 6.699 ms | 5.230 ms | 68.56 ms | 1.00 | 0.10 | 2674.52 KB | 1.00 |
| 'ARX, 1 distinct option value' | Selection sets (1,000 rows, 11 columns) | 64.08 ms | 22.963 ms | 17.928 ms | 65.02 ms | 0.92 | 0.25 | 872.83 KB | 0.33 |
| 'ARX, 50 distinct option values' | Selection sets (1,000 rows, 11 columns) | 62.66 ms | 22.580 ms | 17.629 ms | 64.61 ms | 0.90 | 0.25 | 872.83 KB | 0.33 |
Create.CreateMultipleStatementSplitBenchmarks
| Method | Shape | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 655r | 174.19 ms | 54.59 ms | 42.62 ms | 1.05 | 0.33 | 2000.0000 | 1000.0000 | 14561.48 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 100c x 655r | 98.49 ms | 24.79 ms | 19.36 ms | 0.59 | 0.17 | - | - | 980.94 KB | 0.07 |
| 'Raw multi-row VALUES ... RETURNING id' | 100c x 656r | 165.44 ms | 34.68 ms | 27.08 ms | 1.02 | 0.21 | 2000.0000 | 1000.0000 | 14587.52 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 100c x 656r | 91.49 ms | 29.12 ms | 22.73 ms | 0.57 | 0.16 | - | - | 981.67 KB | 0.07 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 6553r | 170.34 ms | 30.46 ms | 23.79 ms | 1.02 | 0.19 | 2000.0000 | 1000.0000 | 14663.81 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 10c x 6553r | 101.15 ms | 35.65 ms | 27.83 ms | 0.60 | 0.18 | - | - | 2111.23 KB | 0.14 |
| 'Raw multi-row VALUES ... RETURNING id' | 10c x 6554r | 165.18 ms | 20.61 ms | 16.09 ms | 1.01 | 0.14 | 2000.0000 | 1000.0000 | 14668.45 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 10c x 6554r | 112.58 ms | 29.31 ms | 22.89 ms | 0.69 | 0.15 | - | - | 2111.34 KB | 0.14 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 40r | 173.78 ms | 34.86 ms | 27.21 ms | 1.02 | 0.22 | 2000.0000 | 1000.0000 | 14323.41 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 1599c x 40r | 132.95 ms | 19.25 ms | 15.03 ms | 0.78 | 0.15 | - | - | 2108.24 KB | 0.15 |
| 'Raw multi-row VALUES ... RETURNING id' | 1599c x 41r | 185.82 ms | 53.35 ms | 41.65 ms | 1.04 | 0.28 | 2000.0000 | 1000.0000 | 14741.3 KB | 1.00 |
| 'ARX CreateMultipleAsync' | 1599c x 41r | 121.12 ms | 27.86 ms | 21.75 ms | 0.67 | 0.16 | - | - | 2132.52 KB | 0.14 |
Create.CreateMultipleBatchScopeBenchmarks
| Method | Categories | BatchSize | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw: one transaction, multi-row INSERT per batch' | Batch scope, 5,000 rows, every batch succeeds | 50 | 4,996.33 ms | 29.01 ms | 22.65 ms | 4,986.90 ms | 1.00 | 0.01 | 2000.0000 | - | - | 11.97 MB | 1.00 |
| 'Raw: one transaction, SAVEPOINT + INSERT + RELEASE per batch' | Batch scope, 5,000 rows, every batch succeeds | 50 | 4,996.66 ms | 36.33 ms | 28.36 ms | 4,994.55 ms | 1.00 | 0.01 | 2000.0000 | - | - | 11.99 MB | 1.00 |
| 'Raw: no transaction, each batch commits' | Batch scope, 5,000 rows, every batch succeeds | 50 | 260.48 ms | 47.72 ms | 37.26 ms | 244.44 ms | 0.05 | 0.01 | 2000.0000 | - | - | 11.99 MB | 1.00 |
| 'ARX: CreateMultipleAsync per batch, no scope (each commits)' | Batch scope, 5,000 rows, every batch succeeds | 50 | 240.45 ms | 57.31 ms | 44.74 ms | 244.12 ms | 0.05 | 0.01 | - | - | - | 4.18 MB | 0.35 |
| 'ARX: RunBatchAsync, savepoints off' | Batch scope, 5,000 rows, every batch succeeds | 50 | 182.99 ms | 45.94 ms | 35.87 ms | 172.80 ms | 0.04 | 0.01 | - | - | - | 4.21 MB | 0.35 |
| 'ARX: RunBatchAsync, savepoints on (default)' | Batch scope, 5,000 rows, every batch succeeds | 50 | 193.05 ms | 18.90 ms | 14.76 ms | 194.13 ms | 0.04 | 0.00 | - | - | - | 4.24 MB | 0.35 |
| 'ARX: one CreateMultipleAsync of all 5,000 rows' | Batch scope, 5,000 rows, every batch succeeds | 50 | 106.44 ms | 19.98 ms | 15.60 ms | 104.74 ms | 0.02 | 0.00 | - | - | - | 2.71 MB | 0.23 |
| 'EF Core: BeginTransaction, SaveChanges per batch' | Batch scope, 5,000 rows, every batch succeeds | 50 | 5,046.36 ms | 46.38 ms | 36.21 ms | 5,039.75 ms | 1.01 | 0.01 | 12000.0000 | 9000.0000 | - | 70.2 MB | 5.86 |
| 'Raw: one transaction, multi-row INSERT per batch' | Batch scope, 5,000 rows, every batch succeeds | 500 | 488.40 ms | 29.72 ms | 23.20 ms | 485.29 ms | 1.00 | 0.06 | 2000.0000 | 1000.0000 | - | 11.24 MB | 1.00 |
| 'Raw: one transaction, SAVEPOINT + INSERT + RELEASE per batch' | Batch scope, 5,000 rows, every batch succeeds | 500 | 504.16 ms | 44.22 ms | 34.52 ms | 512.67 ms | 1.03 | 0.08 | 2000.0000 | 1000.0000 | - | 11.24 MB | 1.00 |
| 'Raw: no transaction, each batch commits' | Batch scope, 5,000 rows, every batch succeeds | 500 | 319.28 ms | 118.57 ms | 92.58 ms | 311.02 ms | 0.66 | 0.18 | 2000.0000 | 1000.0000 | - | 11.24 MB | 1.00 |
| 'ARX: CreateMultipleAsync per batch, no scope (each commits)' | Batch scope, 5,000 rows, every batch succeeds | 500 | 145.66 ms | 167.15 ms | 130.50 ms | 96.03 ms | 0.30 | 0.26 | - | - | - | 2.83 MB | 0.25 |
| 'ARX: RunBatchAsync, savepoints off' | Batch scope, 5,000 rows, every batch succeeds | 500 | 439.79 ms | 46.49 ms | 36.29 ms | 455.17 ms | 0.90 | 0.08 | - | - | - | 2.83 MB | 0.25 |
| 'ARX: RunBatchAsync, savepoints on (default)' | Batch scope, 5,000 rows, every batch succeeds | 500 | 455.54 ms | 20.00 ms | 15.62 ms | 456.69 ms | 0.93 | 0.05 | - | - | - | 2.83 MB | 0.25 |
| 'ARX: one CreateMultipleAsync of all 5,000 rows' | Batch scope, 5,000 rows, every batch succeeds | 500 | 97.85 ms | 29.26 ms | 22.85 ms | 98.78 ms | 0.20 | 0.05 | - | - | - | 2.71 MB | 0.24 |
| 'EF Core: BeginTransaction, SaveChanges per batch' | Batch scope, 5,000 rows, every batch succeeds | 500 | 547.60 ms | 160.70 ms | 125.46 ms | 500.20 ms | 1.12 | 0.25 | 10000.0000 | 9000.0000 | - | 70.58 MB | 6.28 |
| 'Raw: one transaction, multi-row INSERT per batch' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 132.36 ms | 25.63 ms | 20.01 ms | 131.82 ms | 1.02 | 0.21 | 1000.0000 | - | - | 11.83 MB | 1.00 |
| 'Raw: one transaction, SAVEPOINT + INSERT + RELEASE per batch' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 154.62 ms | 20.15 ms | 15.73 ms | 156.33 ms | 1.19 | 0.20 | 1000.0000 | - | - | 11.83 MB | 1.00 |
| 'Raw: no transaction, each batch commits' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 134.52 ms | 19.77 ms | 15.43 ms | 132.74 ms | 1.04 | 0.19 | 1000.0000 | - | - | 11.83 MB | 1.00 |
| 'ARX: CreateMultipleAsync per batch, no scope (each commits)' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 108.18 ms | 29.25 ms | 22.84 ms | 105.16 ms | 0.83 | 0.21 | - | - | - | 2.71 MB | 0.23 |
| 'ARX: RunBatchAsync, savepoints off' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 103.56 ms | 31.40 ms | 24.51 ms | 101.62 ms | 0.80 | 0.21 | - | - | - | 2.71 MB | 0.23 |
| 'ARX: RunBatchAsync, savepoints on (default)' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 107.87 ms | 19.54 ms | 15.26 ms | 104.62 ms | 0.83 | 0.16 | - | - | - | 2.71 MB | 0.23 |
| 'ARX: one CreateMultipleAsync of all 5,000 rows' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 104.38 ms | 44.18 ms | 34.49 ms | 117.00 ms | 0.80 | 0.28 | - | - | - | 2.71 MB | 0.23 |
| 'EF Core: BeginTransaction, SaveChanges per batch' | Batch scope, 5,000 rows, every batch succeeds | 5000 | 585.28 ms | 175.00 ms | 136.63 ms | 518.10 ms | 4.51 | 1.20 | 10000.0000 | 5000.0000 | 1000.0000 | 70.14 MB | 5.93 |
| 'Raw: savepoints, failed batch undone, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 4,993.32 ms | 34.55 ms | 26.98 ms | 4,996.46 ms | 1.00 | 0.01 | 2000.0000 | - | - | 12 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints on, failed batch caught, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 179.56 ms | 42.29 ms | 33.02 ms | 176.36 ms | 0.04 | 0.01 | - | - | - | 4.25 MB | 0.35 |
| 'Raw: no savepoints, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 4,026.59 ms | 26.62 ms | 20.78 ms | 4,029.24 ms | 0.81 | 0.01 | 2000.0000 | - | - | 9.71 MB | 0.81 |
| 'ARX: RunBatchAsync, savepoints off, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 50 | 141.25 ms | 33.58 ms | 26.22 ms | 136.66 ms | 0.03 | 0.01 | - | - | - | 3.44 MB | 0.29 |
| 'Raw: savepoints, failed batch undone, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 499.51 ms | 44.13 ms | 34.46 ms | 502.45 ms | 1.00 | 0.09 | 2000.0000 | 1000.0000 | - | 11.25 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints on, failed batch caught, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 446.53 ms | 47.16 ms | 36.82 ms | 455.46 ms | 0.90 | 0.09 | - | - | - | 2.83 MB | 0.25 |
| 'Raw: no savepoints, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 455.98 ms | 48.12 ms | 37.57 ms | 455.10 ms | 0.92 | 0.09 | 1000.0000 | - | - | 10.13 MB | 0.90 |
| 'ARX: RunBatchAsync, savepoints off, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 500 | 355.59 ms | 123.47 ms | 96.40 ms | 404.50 ms | 0.71 | 0.19 | - | - | - | 2.55 MB | 0.23 |
| 'Raw: savepoints, failed batch undone, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 128.40 ms | 17.76 ms | 13.86 ms | 129.55 ms | 1.01 | 0.15 | 1000.0000 | - | - | 11.84 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints on, failed batch caught, load continues' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 93.26 ms | 15.79 ms | 12.33 ms | 96.87 ms | 0.73 | 0.12 | - | - | - | 2.5 MB | 0.21 |
| 'Raw: no savepoints, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 124.24 ms | 19.63 ms | 15.33 ms | 124.81 ms | 0.98 | 0.16 | 1000.0000 | - | - | 11.84 MB | 1.00 |
| 'ARX: RunBatchAsync, savepoints off, failure rolls back everything' | Batch scope, 5,000 rows, the batch at 80% fails | 5000 | 81.69 ms | 33.99 ms | 26.54 ms | 86.97 ms | 0.64 | 0.21 | - | - | - | 2.51 MB | 0.21 |
Update.UpdateBenchmarks
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed, $n)' | Update by id (10 columns) | 1.102 ms | 0.0954 ms | 0.0423 ms | 1.00 | 0.05 | - | 4.24 KB | 1.00 |
| 'ARX UpdateAsync' | Update by id (10 columns) | 1.114 ms | 0.0789 ms | 0.0350 ms | 1.01 | 0.05 | 1.9531 | 15.8 KB | 3.72 |
| 'Dapper (POCO)' | Update by id (10 columns) | 1.068 ms | 0.0593 ms | 0.0263 ms | 0.97 | 0.04 | - | 6.23 KB | 1.47 |
| 'EF Core Attach + Modified + SaveChanges' | Update by id (10 columns) | 1.468 ms | 0.3839 ms | 0.2008 ms | 1.33 | 0.18 | 11.7188 | 53.77 KB | 12.67 |
| 'EF Core ExecuteUpdateAsync' | Update by id (10 columns) | 1.891 ms | 0.6766 ms | 0.3539 ms | 1.72 | 0.31 | 11.7188 | 65.46 KB | 15.42 |
| 'Raw Npgsql: SELECT then UPDATE' | Update, load then save (2 round trips) | 1.762 ms | 0.3052 ms | 0.1596 ms | 1.01 | 0.12 | - | 6.41 KB | 1.00 |
| 'EF Core tracked: Find, modify, SaveChanges' | Update, load then save (2 round trips) | 2.597 ms | 0.7657 ms | 0.4005 ms | 1.48 | 0.25 | 11.7188 | 55.04 KB | 8.58 |
Update.UpdateMultipleBenchmarks
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw UPDATE ... FROM (VALUES ...)' | 1 | 1.317 ms | 0.4345 ms | 0.2273 ms | 1.02 | 0.22 | - | - | - | 8.11 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 1 | 1.452 ms | 0.2047 ms | 0.1070 ms | 1.13 | 0.18 | 1.9531 | - | - | 9.93 KB | 1.22 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 1 | 1.108 ms | 0.1481 ms | 0.0657 ms | 0.86 | 0.13 | - | - | - | 4.37 KB | 0.54 |
| 'ARX UpdateMultipleAsync' | 1 | 1.186 ms | 0.1403 ms | 0.0734 ms | 0.92 | 0.14 | 1.9531 | - | - | 15.8 KB | 1.95 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 1 | 1.112 ms | 0.1529 ms | 0.0800 ms | 0.86 | 0.14 | - | - | - | 6.31 KB | 0.78 |
| 'EF Core AttachRange + Modified + SaveChanges' | 1 | 1.587 ms | 0.4672 ms | 0.2444 ms | 1.23 | 0.25 | 11.7188 | - | - | 53.79 KB | 6.63 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 10 | 1.551 ms | 0.2816 ms | 0.1250 ms | 1.01 | 0.10 | 7.8125 | - | - | 37.02 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 10 | 1.495 ms | 0.1026 ms | 0.0537 ms | 0.97 | 0.08 | 1.9531 | - | - | 11.17 KB | 0.30 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 10 | 2.217 ms | 0.0711 ms | 0.0316 ms | 1.44 | 0.10 | 3.9063 | - | - | 27.34 KB | 0.74 |
| 'ARX UpdateMultipleAsync' | 10 | 1.864 ms | 0.0778 ms | 0.0345 ms | 1.21 | 0.09 | 3.9063 | - | - | 26.77 KB | 0.72 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 10 | 10.281 ms | 0.7852 ms | 0.4107 ms | 6.66 | 0.53 | - | - | - | 39.06 KB | 1.05 |
| 'EF Core AttachRange + Modified + SaveChanges' | 10 | 3.448 ms | 0.5902 ms | 0.3087 ms | 2.24 | 0.25 | 39.0625 | 7.8125 | - | 200.58 KB | 5.42 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 100 | 3.784 ms | 0.8331 ms | 0.4357 ms | 1.01 | 0.15 | 54.6875 | 39.0625 | - | 359.66 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 100 | 2.279 ms | 0.0782 ms | 0.0347 ms | 0.61 | 0.06 | 3.9063 | - | - | 24.28 KB | 0.07 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 100 | 10.707 ms | 0.3383 ms | 0.1502 ms | 2.86 | 0.29 | 31.2500 | 15.6250 | - | 258.99 KB | 0.72 |
| 'ARX UpdateMultipleAsync' | 100 | 2.620 ms | 0.1432 ms | 0.0636 ms | 0.70 | 0.07 | 15.6250 | - | - | 86.7 KB | 0.24 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 100 | 102.563 ms | 15.0986 ms | 7.8969 ms | 27.40 | 3.43 | - | - | - | 366.73 KB | 1.02 |
| 'EF Core AttachRange + Modified + SaveChanges' | 100 | 14.175 ms | 2.5471 ms | 1.3322 ms | 3.79 | 0.51 | 265.6250 | 250.0000 | - | 1656.28 KB | 4.61 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 1000 | 59.606 ms | 10.0585 ms | 5.2608 ms | 1.01 | 0.12 | 625.0000 | 375.0000 | 125.0000 | 3764.6 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 1000 | 36.427 ms | 10.3411 ms | 5.4086 ms | 0.62 | 0.10 | - | - | - | 155.22 KB | 0.04 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 1000 | 103.881 ms | 9.8444 ms | 5.1488 ms | 1.75 | 0.17 | 400.0000 | 200.0000 | - | 2568.73 KB | 0.68 |
| 'ARX UpdateMultipleAsync' | 1000 | 27.380 ms | 9.6558 ms | 5.0502 ms | 0.46 | 0.09 | 125.0000 | 62.5000 | - | 680.94 KB | 0.18 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 1000 | 1,076.040 ms | 212.4197 ms | 111.0996 ms | 18.18 | 2.33 | - | - | - | 3643.57 KB | 0.97 |
| 'EF Core AttachRange + Modified + SaveChanges' | 1000 | 138.086 ms | 17.7704 ms | 9.2942 ms | 2.33 | 0.24 | 2000.0000 | 1000.0000 | - | 16493.41 KB | 4.38 |
| 'Raw UPDATE ... FROM (VALUES ...)' | 10000 | 286.508 ms | 28.0033 ms | 14.6463 ms | 1.00 | 0.07 | 5000.0000 | 2000.0000 | - | 38298.53 KB | 1.00 |
| 'Raw UPDATE ... FROM unnest(arrays)' | 10000 | 129.723 ms | 31.7629 ms | 16.6126 ms | 0.45 | 0.06 | - | - | - | 1465.02 KB | 0.04 |
| 'Raw NpgsqlBatch of single-row UPDATEs' | 10000 | 1,033.699 ms | 35.2172 ms | 15.6367 ms | 3.62 | 0.18 | 4000.0000 | 2000.0000 | - | 25635.09 KB | 0.67 |
| 'ARX UpdateMultipleAsync' | 10000 | 162.009 ms | 20.3644 ms | 10.6510 ms | 0.57 | 0.04 | 666.6667 | 333.3333 | - | 6648.68 KB | 0.17 |
| 'Dapper ExecuteAsync(sql, list): one statement per row' | 10000 | 10,143.401 ms | 661.8305 ms | 346.1502 ms | 35.49 | 2.07 | 7000.0000 | - | - | 36409.2 KB | 0.95 |
| 'EF Core AttachRange + Modified + SaveChanges' | 10000 | 1,391.667 ms | 80.5700 ms | 42.1397 ms | 4.87 | 0.27 | 23000.0000 | 11000.0000 | 2000.0000 | 154241.9 KB | 4.03 |
Delete.DeleteBenchmarks
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed, $1)' | 1.019 ms | 0.0652 ms | 0.0341 ms | 1.00 | 0.04 | - | 2.14 KB | 1.00 |
| 'ARX DeleteAsync' | 1.043 ms | 0.1307 ms | 0.0580 ms | 1.02 | 0.06 | - | 4.68 KB | 2.19 |
| 'Dapper ExecuteAsync' | 1.127 ms | 0.1246 ms | 0.0652 ms | 1.11 | 0.07 | - | 2.58 KB | 1.21 |
| 'EF Core ExecuteDeleteAsync' | 1.683 ms | 0.7385 ms | 0.3863 ms | 1.65 | 0.36 | 7.8125 | 38.87 KB | 18.18 |
| 'EF Core Remove + SaveChanges (stub entity)' | 1.579 ms | 0.3092 ms | 0.1373 ms | 1.55 | 0.13 | 7.8125 | 43.75 KB | 20.47 |
Delete.DeleteMultipleBenchmarks
| Method | Rows | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw IN ($1, $2, …), chunked' | 1 | 2.077 ms | 0.3416 ms | 0.2667 ms | 2.099 ms | 1.02 | 0.18 | - | - | 3.3 KB | 1.00 |
| 'Raw = ANY($1::bigint[])' | 1 | 2.365 ms | 1.2476 ms | 0.9741 ms | 2.120 ms | 1.16 | 0.49 | - | - | 2.93 KB | 0.89 |
| 'ARX DeleteMultipleAsync' | 1 | 2.125 ms | 0.3694 ms | 0.2884 ms | 2.147 ms | 1.04 | 0.19 | - | - | 5.32 KB | 1.61 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 1 | 2.608 ms | 1.4397 ms | 1.1240 ms | 2.419 ms | 1.28 | 0.56 | - | - | 5.1 KB | 1.54 |
| 'Dapper = ANY(@Ids)' | 1 | 2.197 ms | 0.4641 ms | 0.3624 ms | 2.235 ms | 1.07 | 0.22 | - | - | 3.59 KB | 1.09 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 1 | 9.392 ms | 29.5540 ms | 23.0738 ms | 2.747 ms | 4.59 | 10.95 | - | - | 44.52 KB | 13.47 |
| 'Raw IN ($1, $2, …), chunked' | 100 | 2.205 ms | 0.3339 ms | 0.2607 ms | 2.177 ms | 1.01 | 0.16 | - | - | 26.55 KB | 1.00 |
| 'Raw = ANY($1::bigint[])' | 100 | 2.259 ms | 0.7251 ms | 0.5661 ms | 2.184 ms | 1.04 | 0.28 | - | - | 2.93 KB | 0.11 |
| 'ARX DeleteMultipleAsync' | 100 | 2.252 ms | 0.2661 ms | 0.2078 ms | 2.211 ms | 1.03 | 0.15 | - | - | 5.23 KB | 0.20 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 100 | 2.445 ms | 0.4976 ms | 0.3885 ms | 2.365 ms | 1.12 | 0.21 | - | - | 5.96 KB | 0.22 |
| 'Dapper = ANY(@Ids)' | 100 | 2.387 ms | 1.3183 ms | 1.0292 ms | 2.137 ms | 1.10 | 0.47 | - | - | 3.59 KB | 0.14 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 100 | 8.791 ms | 25.7942 ms | 20.1384 ms | 2.813 ms | 4.04 | 8.95 | - | - | 44.99 KB | 1.69 |
| 'Raw IN ($1, $2, …), chunked' | 1000 | 13.887 ms | 29.5708 ms | 23.0869 ms | 4.464 ms | 2.68 | 4.77 | - | - | 242.26 KB | 1.00 |
| 'Raw = ANY($1::bigint[])' | 1000 | 4.534 ms | 3.7593 ms | 2.9350 ms | 3.355 ms | 0.87 | 0.69 | - | - | 2.93 KB | 0.01 |
| 'ARX DeleteMultipleAsync' | 1000 | 4.554 ms | 4.1506 ms | 3.2405 ms | 3.630 ms | 0.88 | 0.75 | - | - | 5.28 KB | 0.02 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 1000 | 5.159 ms | 5.8071 ms | 4.5338 ms | 3.910 ms | 1.00 | 1.00 | - | - | 12.99 KB | 0.05 |
| 'Dapper = ANY(@Ids)' | 1000 | 5.187 ms | 3.7028 ms | 2.8909 ms | 4.388 ms | 1.00 | 0.72 | - | - | 3.46 KB | 0.01 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 1000 | 12.886 ms | 27.8781 ms | 21.7654 ms | 5.026 ms | 2.49 | 4.49 | - | - | 52.33 KB | 0.22 |
| 'Raw IN ($1, $2, …), chunked' | 10000 | 69.219 ms | 6.7543 ms | 5.2733 ms | 67.624 ms | 1.00 | 0.10 | - | - | 2370.94 KB | 1.000 |
| 'Raw = ANY($1::bigint[])' | 10000 | 49.347 ms | 26.3136 ms | 20.5439 ms | 60.064 ms | 0.72 | 0.29 | - | - | 2.41 KB | 0.001 |
| 'ARX DeleteMultipleAsync' | 10000 | 46.774 ms | 31.3096 ms | 24.4445 ms | 61.376 ms | 0.68 | 0.34 | - | - | 4.59 KB | 0.002 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 10000 | 52.991 ms | 30.2916 ms | 23.6497 ms | 63.456 ms | 0.77 | 0.33 | - | - | 83.15 KB | 0.035 |
| 'Dapper = ANY(@Ids)' | 10000 | 46.350 ms | 31.2634 ms | 24.4084 ms | 62.027 ms | 0.67 | 0.34 | - | - | 3.48 KB | 0.001 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 10000 | 60.203 ms | 36.9828 ms | 28.8738 ms | 62.421 ms | 0.87 | 0.41 | - | - | 122.15 KB | 0.052 |
| 'Raw IN ($1, $2, …), chunked' | 100000 | 296.850 ms | 58.3172 ms | 45.5302 ms | 290.082 ms | 1.02 | 0.21 | 3000.0000 | 1000.0000 | 24489.99 KB | 1.000 |
| 'Raw = ANY($1::bigint[])' | 100000 | 178.237 ms | 31.6741 ms | 24.7290 ms | 172.540 ms | 0.61 | 0.12 | - | - | 1.93 KB | 0.000 |
| 'ARX DeleteMultipleAsync' | 100000 | 179.935 ms | 25.1891 ms | 19.6660 ms | 178.492 ms | 0.62 | 0.11 | - | - | 4.71 KB | 0.000 |
| 'ARX DeleteMultipleAsync (legacy ArxDeleteMultipleParameter)' | 100000 | 154.073 ms | 33.9831 ms | 26.5318 ms | 152.912 ms | 0.53 | 0.12 | - | - | 786.04 KB | 0.032 |
| 'Dapper = ANY(@Ids)' | 100000 | 147.852 ms | 32.3475 ms | 25.2548 ms | 151.391 ms | 0.51 | 0.11 | - | - | 3.16 KB | 0.000 |
| 'EF Core Where(ids.Contains).ExecuteDeleteAsync' | 100000 | 176.379 ms | 52.4819 ms | 40.9744 ms | 170.472 ms | 0.61 | 0.16 | - | - | 824.7 KB | 0.034 |
Delete.DeleteMultipleSmallBenchmarks
| Method | Ids | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw = ANY($1::bigint[])' | 1 | 1.365 ms | 0.2958 ms | 0.1547 ms | 1.01 | 0.15 | 2.21 KB | 1.00 |
| 'ARX DeleteMultipleAsync' | 1 | 1.070 ms | 0.0769 ms | 0.0342 ms | 0.79 | 0.09 | 4.56 KB | 2.06 |
| 'Raw = ANY($1::bigint[])' | 10 | 1.116 ms | 0.1263 ms | 0.0561 ms | 1.00 | 0.07 | 2.34 KB | 1.00 |
| 'ARX DeleteMultipleAsync' | 10 | 1.113 ms | 0.0450 ms | 0.0236 ms | 1.00 | 0.05 | 4.7 KB | 2.00 |
| 'Raw = ANY($1::bigint[])' | 50 | 1.343 ms | 0.1822 ms | 0.0953 ms | 1.00 | 0.09 | 2.61 KB | 1.00 |
| 'ARX DeleteMultipleAsync' | 50 | 1.220 ms | 0.0395 ms | 0.0175 ms | 0.91 | 0.06 | 5.02 KB | 1.92 |
Retrieve.RetrieveBenchmarks
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed row)' | 821.4 μs | 196.47 μs | 102.76 μs | 1.01 | 0.16 | - | 2.67 KB | 1.00 |
| 'Raw Npgsql (dictionary)' | 809.8 μs | 98.01 μs | 51.26 μs | 1.00 | 0.12 | - | 3.2 KB | 1.20 |
| 'ARX RetrieveAsync' | 824.6 μs | 80.28 μs | 35.64 μs | 1.02 | 0.12 | - | 6.77 KB | 2.54 |
| 'Dapper (POCO)' | 699.0 μs | 17.65 μs | 9.23 μs | 0.86 | 0.09 | - | 3.93 KB | 1.48 |
| 'Dapper (dynamic)' | 743.1 μs | 100.97 μs | 52.81 μs | 0.92 | 0.12 | - | 3.79 KB | 1.42 |
| 'EF Core AsNoTracking FirstOrDefault' | 957.1 μs | 175.29 μs | 91.68 μs | 1.18 | 0.16 | 7.8125 | 39.87 KB | 14.96 |
| 'EF Core Find (tracked)' | 1,090.7 μs | 231.39 μs | 121.02 μs | 1.34 | 0.20 | 7.8125 | 44.62 KB | 16.74 |
Retrieve.RetrieveMultipleBenchmarks
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql (typed rows)' | 1 | 719.8 μs | 60.42 μs | 26.83 μs | 1.00 | 0.05 | - | - | - | 2.8 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 1 | 779.7 μs | 117.62 μs | 61.52 μs | 1.08 | 0.09 | - | - | - | 3.37 KB | 1.20 |
| 'ARX RetrieveMultipleAsync' | 1 | 769.5 μs | 68.76 μs | 30.53 μs | 1.07 | 0.05 | 1.9531 | - | - | 17.18 KB | 6.14 |
| 'Dapper (POCO)' | 1 | 779.6 μs | 90.57 μs | 47.37 μs | 1.08 | 0.07 | - | - | - | 4.02 KB | 1.44 |
| 'Dapper (dynamic)' | 1 | 711.3 μs | 19.97 μs | 7.12 μs | 0.99 | 0.04 | - | - | - | 3.85 KB | 1.38 |
| 'EF Core AsNoTracking ToList' | 1 | 1,013.8 μs | 232.36 μs | 103.17 μs | 1.41 | 0.14 | 7.8125 | - | - | 42.21 KB | 15.09 |
| 'Raw Npgsql (typed rows)' | 100 | 905.6 μs | 37.19 μs | 19.45 μs | 1.00 | 0.03 | 3.9063 | - | - | 22.58 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 100 | 1,071.4 μs | 169.91 μs | 88.87 μs | 1.18 | 0.10 | 15.6250 | 1.9531 | - | 77.23 KB | 3.42 |
| 'ARX RetrieveMultipleAsync' | 100 | 1,081.6 μs | 92.31 μs | 40.98 μs | 1.19 | 0.05 | 15.6250 | - | - | 80.25 KB | 3.55 |
| 'Dapper (POCO)' | 100 | 955.6 μs | 42.42 μs | 18.84 μs | 1.06 | 0.03 | 9.7656 | - | - | 46.21 KB | 2.05 |
| 'Dapper (dynamic)' | 100 | 941.3 μs | 120.76 μs | 53.62 μs | 1.04 | 0.06 | 9.7656 | - | - | 49.14 KB | 2.18 |
| 'EF Core AsNoTracking ToList' | 100 | 1,597.1 μs | 681.19 μs | 356.27 μs | 1.76 | 0.37 | 15.6250 | - | - | 80.56 KB | 3.57 |
| 'Raw Npgsql (typed rows)' | 1000 | 3,275.0 μs | 294.43 μs | 130.73 μs | 1.00 | 0.05 | 39.0625 | 7.8125 | - | 200.86 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 1000 | 3,209.1 μs | 55.86 μs | 24.80 μs | 0.98 | 0.04 | 125.0000 | 78.1250 | - | 746.36 KB | 3.72 |
| 'ARX RetrieveMultipleAsync' | 1000 | 3,397.0 μs | 152.03 μs | 79.51 μs | 1.04 | 0.04 | 121.0938 | 62.5000 | - | 651.2 KB | 3.24 |
| 'Dapper (POCO)' | 1000 | 3,050.3 μs | 321.40 μs | 142.70 μs | 0.93 | 0.05 | 85.9375 | 27.3438 | - | 426.2 KB | 2.12 |
| 'Dapper (dynamic)' | 1000 | 3,494.0 μs | 290.51 μs | 151.94 μs | 1.07 | 0.06 | 85.9375 | 35.1563 | - | 457.23 KB | 2.28 |
| 'EF Core AsNoTracking ToList' | 1000 | 3,671.4 μs | 373.95 μs | 195.58 μs | 1.12 | 0.07 | 85.9375 | 23.4375 | - | 428.61 KB | 2.13 |
| 'Raw Npgsql (typed rows)' | 10000 | 26,022.3 μs | 1,208.79 μs | 632.22 μs | 1.00 | 0.03 | 375.0000 | 281.2500 | 93.7500 | 2076.11 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 10000 | 32,934.5 μs | 5,449.27 μs | 2,419.51 μs | 1.27 | 0.09 | 1384.6154 | 923.0769 | 307.6923 | 7529.13 KB | 3.63 |
| 'ARX RetrieveMultipleAsync' | 10000 | 33,141.1 μs | 2,285.15 μs | 1,195.18 μs | 1.27 | 0.05 | 1250.0000 | 750.0000 | 250.0000 | 6451.88 KB | 3.11 |
| 'Dapper (POCO)' | 10000 | 25,997.3 μs | 1,516.02 μs | 673.12 μs | 1.00 | 0.03 | 718.7500 | 312.5000 | 93.7500 | 4324.35 KB | 2.08 |
| 'Dapper (dynamic)' | 10000 | 27,933.0 μs | 922.79 μs | 482.64 μs | 1.07 | 0.03 | 875.0000 | 562.5000 | 187.5000 | 4636.66 KB | 2.23 |
| 'EF Core AsNoTracking ToList' | 10000 | 26,731.7 μs | 563.66 μs | 294.81 μs | 1.03 | 0.03 | 718.7500 | 375.0000 | 93.7500 | 3999.08 KB | 1.93 |
| 'Raw Npgsql (typed rows)' | 100000 | 249,215.2 μs | 14,010.71 μs | 7,327.87 μs | 1.00 | 0.04 | 3000.0000 | 1000.0000 | - | 20251.78 KB | 1.00 |
| 'Raw Npgsql (dictionaries)' | 100000 | 300,131.6 μs | 23,097.98 μs | 12,080.69 μs | 1.21 | 0.06 | 13000.0000 | 7000.0000 | 1500.0000 | 74713.73 KB | 3.69 |
| 'ARX RetrieveMultipleAsync' | 100000 | 283,962.2 μs | 32,504.52 μs | 14,432.21 μs | 1.14 | 0.06 | 12000.0000 | 7000.0000 | 2000.0000 | 63820.27 KB | 3.15 |
| 'Dapper (POCO)' | 100000 | 261,125.4 μs | 14,823.32 μs | 7,752.88 μs | 1.05 | 0.04 | 6000.0000 | 2000.0000 | 1000.0000 | 42697.35 KB | 2.11 |
| 'Dapper (dynamic)' | 100000 | 235,387.5 μs | 9,231.14 μs | 4,828.07 μs | 0.95 | 0.03 | 8000.0000 | 4000.0000 | 1000.0000 | 45814.71 KB | 2.26 |
| 'EF Core AsNoTracking ToList' | 100000 | 268,213.8 μs | 47,649.00 μs | 24,921.35 μs | 1.08 | 0.10 | 7000.0000 | 3000.0000 | 1000.0000 | 39057.3 KB | 1.93 |
Retrieve.RetrieveFilterBenchmarks
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql ILIKE (dictionaries)' | Contains '99', case-insensitive | 75.417 ms | 4.0192 ms | 2.1021 ms | 1.00 | 0.04 | 428.5714 | 142.8571 | 2756.86 KB | 1.00 |
| 'ARX Contains' | Contains '99', case-insensitive | 81.208 ms | 17.2031 ms | 6.1348 ms | 1.08 | 0.08 | 333.3333 | 166.6667 | 2366.64 KB | 0.86 |
| 'Dapper ILIKE (dynamic)' | Contains '99', case-insensitive | 74.507 ms | 3.7558 ms | 1.9643 ms | 0.99 | 0.04 | 166.6667 | - | 1683.56 KB | 0.61 |
| 'EF Core EF.Functions.ILike' | Contains '99', case-insensitive | 80.709 ms | 13.6809 ms | 7.1554 ms | 1.07 | 0.09 | 166.6667 | - | 1475.78 KB | 0.54 |
| 'Raw Npgsql = ANY($1) (dictionaries)' | In list of 1,000 ids | 5.634 ms | 0.4293 ms | 0.1906 ms | 1.00 | 0.04 | 132.8125 | 78.1250 | 748.31 KB | 1.00 |
| 'ARX In' | In list of 1,000 ids | 5.961 ms | 0.5831 ms | 0.3050 ms | 1.06 | 0.06 | 125.0000 | 62.5000 | 699.39 KB | 0.93 |
| 'Dapper = ANY(@Ids) (dynamic)' | In list of 1,000 ids | 5.516 ms | 0.8157 ms | 0.3622 ms | 0.98 | 0.07 | 85.9375 | 39.0625 | 457.43 KB | 0.61 |
| 'EF Core Where(ids.Contains)' | In list of 1,000 ids | 6.337 ms | 0.5015 ms | 0.2227 ms | 1.13 | 0.05 | 78.1250 | 15.6250 | 437.42 KB | 0.58 |
| 'Raw Npgsql (dictionaries)' | Nested AND/OR (499 rows) | 14.109 ms | 0.6470 ms | 0.2873 ms | 1.00 | 0.03 | 62.5000 | - | 374.24 KB | 1.00 |
| 'ARX nested filters' | Nested AND/OR (499 rows) | 14.616 ms | 0.9686 ms | 0.5066 ms | 1.04 | 0.04 | 62.5000 | 15.6250 | 336.01 KB | 0.90 |
| 'Dapper (dynamic)' | Nested AND/OR (499 rows) | 14.668 ms | 1.0341 ms | 0.5408 ms | 1.04 | 0.04 | 31.2500 | - | 231 KB | 0.62 |
| 'EF Core AsNoTracking' | Nested AND/OR (499 rows) | 14.914 ms | 1.3535 ms | 0.7079 ms | 1.06 | 0.05 | 31.2500 | - | 232.65 KB | 0.62 |
Retrieve.RetrievePagingBenchmarks
| Method | Categories | Page | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql LIMIT/OFFSET (dictionaries)' | A page of 50 | 1 | 854.5 μs | 39.48 μs | 17.53 μs | 1.00 | 0.03 | 7.8125 | 40.45 KB | 1.00 |
| 'ARX PageInfo' | A page of 50 | 1 | 921.1 μs | 36.46 μs | 19.07 μs | 1.08 | 0.03 | 9.7656 | 48.58 KB | 1.20 |
| 'EF Core Skip/Take' | A page of 50 | 1 | 1,072.1 μs | 177.70 μs | 78.90 μs | 1.26 | 0.09 | 11.7188 | 61.1 KB | 1.51 |
| 'Raw Npgsql LIMIT/OFFSET (dictionaries)' | A page of 50 | 1000 | 12,030.9 μs | 845.77 μs | 442.35 μs | 1.00 | 0.05 | - | 40.36 KB | 1.00 |
| 'ARX PageInfo' | A page of 50 | 1000 | 12,267.3 μs | 506.45 μs | 224.87 μs | 1.02 | 0.04 | - | 48.67 KB | 1.21 |
| 'EF Core Skip/Take' | A page of 50 | 1000 | 12,413.8 μs | 538.88 μs | 239.27 μs | 1.03 | 0.04 | - | 61.09 KB | 1.51 |
| 'Raw Npgsql page + count, one batch' | A page of 50 and the total | 1 | 6,621.1 μs | 246.48 μs | 128.91 μs | 1.00 | 0.03 | 7.8125 | 40.42 KB | 1.00 |
| 'ARX PageInfo + ReturnTotalRecordCount' | A page of 50 and the total | 1 | 6,606.4 μs | 461.90 μs | 205.09 μs | 1.00 | 0.03 | 7.8125 | 49.56 KB | 1.23 |
| 'EF Core Skip/Take + CountAsync' | A page of 50 and the total | 1 | 7,670.1 μs | 709.88 μs | 315.19 μs | 1.16 | 0.05 | - | 65.23 KB | 1.61 |
| 'Raw Npgsql page + count, one batch' | A page of 50 and the total | 1000 | 18,245.0 μs | 1,720.56 μs | 763.94 μs | 1.00 | 0.06 | - | 40.49 KB | 1.00 |
| 'ARX PageInfo + ReturnTotalRecordCount' | A page of 50 and the total | 1000 | 17,418.3 μs | 1,294.03 μs | 676.80 μs | 0.96 | 0.05 | - | 49.65 KB | 1.23 |
| 'EF Core Skip/Take + CountAsync' | A page of 50 and the total | 1000 | 19,275.9 μs | 1,089.73 μs | 483.85 μs | 1.06 | 0.05 | - | 65.26 KB | 1.61 |
Retrieve.RetrieveLinkBenchmarks
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw Npgsql LEFT JOIN (dictionaries)' | 2.734 ms | 0.0772 ms | 0.0343 ms | 1.00 | 0.02 | 93.7500 | 50.7813 | 519.16 KB | 1.00 |
| 'Dapper LEFT JOIN (dynamic)' | 2.621 ms | 0.0695 ms | 0.0309 ms | 0.96 | 0.02 | 58.5938 | 19.5313 | 301.15 KB | 0.58 |
| 'ARX link entity' | 2.731 ms | 0.0497 ms | 0.0221 ms | 1.00 | 0.01 | 93.7500 | 39.0625 | 493.53 KB | 0.95 |
| 'ARX direct join (_lk)' | 2.760 ms | 0.1324 ms | 0.0588 ms | 1.01 | 0.02 | 93.7500 | 35.1563 | 493.5 KB | 0.95 |
| 'ARX declared lookup + display name' | 2.966 ms | 0.1343 ms | 0.0596 ms | 1.09 | 0.02 | 121.0938 | 74.2188 | 688.63 KB | 1.33 |
Run them yourself
The benchmark code is published, so you can check these numbers on your own machine and database: arx-benchmark-postgresql.zip. It builds against the ARX packages on nuget.org; HOW-TO-RUN.md inside says how to point it at a database and run it. Compare the ratios, not the absolute times.