Amazon DynamoDB
Benchmarks
How ARX compares with other ways of doing the same work on Amazon DynamoDB, measured with BenchmarkDotNet.
ARX.SDK's DynamoDB provider against the hand-written low-level client code a developer would write (PutItemRequest,
QueryRequest, TransactWriteItemsRequest: the baseline) and the AWS SDK's object persistence model
(DynamoDBContext). BenchmarkDotNet, Release, on the arx-dynamodb container (DynamoDB Local 2.5.2, Docker Desktop on
Windows), tables arx_bench_product, arx_bench_crm (with GSI1) and arx_bench_events (write-sharded 4 ways). Reports
in results/. Ratios are against the raw client; numbers from one machine, so read the ratios, not the times.
| Operation | ARX against the raw client | Notes |
|---|---|---|
| Create, one item (a conditional put) | 1.00× | DynamoDBContext's save (no condition: it overwrites) 1.01× |
CreateMultiple, 25 and 100 items, one TransactWriteItems |
0.98×, 1.14× (spread ±0.13) | BatchWriteItem (not atomic): 1.28× and 3.99× |
| UpdateMultiple, 1, 25 and 100 items, conditional updates in one transaction | 0.97×, 0.97×, 1.01× | – |
| Update through an index (25 orders found by status, then updated by key) | 1.03× | against a Query of GSI1 and a transaction of conditional updates |
| Delete, 1 item; DeleteMultiple, 25 and 100 | 0.95×, 1.00×, 1.07× | before tuning 1.48×, 1.13×, 1.74× |
Retrieve by key (GetItem) |
1.16× (spread ±0.10) | the same code read 0.90× to 1.39× in five runs; DynamoDBContext 1.01× to 1.48× |
| RetrieveMultiple, 100 and 1,000 items of one partition | 1.01×, 1.18× | the raw baseline only counts the items; DynamoDBContext, which builds objects, 0.94× and 1.16× |
| RetrieveMultiple through GSI1 (200 orders) | 0.98× | – |
Scan of 1,000 items with a filter (AllowScan) |
1.03× | – |
| A write-sharded partition, 100 and 1,000 items over 4 shards, in order | 1.10×, 1.12× | against four parallel queries merged by hand; before tuning 2.26×, 1.88× |
Create and Retrieve against the Document model (Table.PutItemAsync with the same condition, Table.GetItemAsync) |
1.01×, 1.11× | the Document model 1.05×, 1.15× (one run, 2026-11-09) |
| Retrieve by many keys, 25 and 100: ARX has no single call, so one RetrieveAsync per key in parallel | 1.42×, 0.69× against BatchGetItem |
the raw client's parallel GetItem 1.88×, 0.56×; DynamoDBContext batch get 1.11×, 1.00×. On DynamoDB Local a BatchGetItem of 100 is slower than 100 parallel GetItems, which says nothing about AWS; allocations 8× to 10× (one request per key) |
A move (AllowKeyChange): the consistent read, then a delete and a put in one transaction |
1.14× | against the same GetItem and TransactWriteItems by hand |
What the numbers say: writes are level with the raw client, deletes since the tuning; reads cost the dictionary entity, level with the AWS SDK's own mapper. ARX allocates more: 1.1× to 1.5× the raw client on reads, 2× to 4× on writes of 25 to 100 items (each item's key, condition and description kept for the error a failed transaction reports). Single-item timings swing by ±25% between runs on this machine. DynamoDB Local is not DynamoDB: its transactions take 65 to 90 ms whatever their size, so absolute times say nothing about AWS.
Reports
| Class | Report |
|---|---|
CreateBenchmarks |
results/…CreateBenchmarks-report-github.md |
CreateMultipleBenchmarks |
results/…CreateMultipleBenchmarks-report-github.md |
UpdateMultipleBenchmarks |
results/…UpdateMultipleBenchmarks-report-github.md |
UpdateByIndexBenchmarks |
results/…UpdateByIndexBenchmarks-report-github.md |
DeleteMultipleBenchmarks |
results/…DeleteMultipleBenchmarks-report-github.md |
RetrieveBenchmarks |
results/…RetrieveBenchmarks-report-github.md |
IndexAndScanBenchmarks |
results/…IndexAndScanBenchmarks-report-github.md |
ShardedReadBenchmarks |
results/…ShardedReadBenchmarks-report-github.md |
DocumentModelBenchmarks |
results/…DocumentModelBenchmarks-report-github.md |
BatchGetBenchmarks |
results/…BatchGetBenchmarks-report-github.md |
MoveBenchmarks |
results/…MoveBenchmarks-report-github.md |
Not measured yet
Against AWS itself, nothing: these numbers are DynamoDB Local's. A read by many keys in one call has no ARX API yet (a
condition id In (…) gives no partition, ARX8001): the BatchGetBenchmarks row is what an application does today.
A caution about this machine: the client runs on Windows and reaches DynamoDB Local through Docker Desktop's port forwarding, which stalls requests of more than about 8 KB by ~50 ms. The small move transaction above takes 6 ms; the 65 to 90 ms quoted for larger transactions may be that stall rather than DynamoDB Local. Not re-measured from inside the Docker network yet.
The reports
BenchmarkDotNet's own output for the runs the summary cites, as committed: every number above comes from one of these.
CreateBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw client: PutItem with attribute_not_exists' | 6.090 ms | 2.278 ms | 1.0116 ms | 1.02 | 0.21 | - | 28.08 KB | 1.00 |
| 'DynamoDBContext SaveAsync (no condition: overwrites)' | 6.018 ms | 1.729 ms | 0.7678 ms | 1.01 | 0.18 | 7.8125 | 41.55 KB | 1.48 |
| 'ARX CreateAsync' | 5.966 ms | 1.326 ms | 0.4728 ms | 1.00 | 0.15 | - | 32.43 KB | 1.15 |
CreateMultipleBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw client: TransactWriteItems of conditional puts' | 25 | 71.90 ms | 3.636 ms | 1.615 ms | 1.00 | 0.03 | 85.54 KB | 1.00 |
| 'Raw client: BatchWriteItem (no conditions, not atomic)' | 25 | 91.84 ms | 20.504 ms | 9.104 ms | 1.28 | 0.12 | 79.52 KB | 0.93 |
| 'ARX CreateMultipleAsync' | 25 | 70.77 ms | 3.454 ms | 1.807 ms | 0.98 | 0.03 | 194.92 KB | 2.28 |
| 'Raw client: TransactWriteItems of conditional puts' | 100 | 87.20 ms | 9.789 ms | 5.120 ms | 1.00 | 0.08 | 263.24 KB | 1.00 |
| 'Raw client: BatchWriteItem (no conditions, not atomic)' | 100 | 346.88 ms | 52.102 ms | 27.251 ms | 3.99 | 0.37 | 317.04 KB | 1.20 |
| 'ARX CreateMultipleAsync' | 100 | 98.85 ms | 20.054 ms | 10.488 ms | 1.14 | 0.13 | 699.27 KB | 2.66 |
UpdateMultipleBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw client: UpdateItem / TransactWriteItems of conditional updates' | 1 | 5.982 ms | 2.028 ms | 1.0604 ms | 1.03 | 0.24 | 27.02 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 1 | 5.670 ms | 1.051 ms | 0.5498 ms | 0.97 | 0.18 | 32.45 KB | 1.20 |
| 'Raw client: UpdateItem / TransactWriteItems of conditional updates' | 25 | 75.251 ms | 6.132 ms | 3.2071 ms | 1.00 | 0.06 | 52.07 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 25 | 72.985 ms | 4.823 ms | 2.5225 ms | 0.97 | 0.05 | 155.74 KB | 2.99 |
| 'Raw client: UpdateItem / TransactWriteItems of conditional updates' | 100 | 89.421 ms | 15.954 ms | 8.3442 ms | 1.01 | 0.13 | 128.29 KB | 1.00 |
| 'ARX UpdateAsync / UpdateMultipleAsync' | 100 | 89.976 ms | 12.918 ms | 6.7561 ms | 1.01 | 0.12 | 541.55 KB | 4.22 |
UpdateByIndexBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|
| 'Raw client: Query GSI1, then TransactWriteItems of conditional updates' | 81.13 ms | 3.704 ms | 1.644 ms | 1.00 | 0.03 | 149 KB | 1.00 |
| 'ARX UpdateAsync with Match = Columns("status")' | 83.25 ms | 3.178 ms | 1.662 ms | 1.03 | 0.03 | 324.51 KB | 2.18 |
DeleteMultipleBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
SingleOperation : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=SingleOperation InvocationCount=1 IterationCount=12
LaunchCount=1 RunStrategy=Monitoring UnrollFactor=1
WarmupCount=1
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|
| 'Raw client: DeleteItem (ALL_OLD) / TransactWriteItems of conditional deletes' | 1 | 8.520 ms | 4.260 ms | 3.326 ms | 1.08 | 0.47 | 30.04 KB | 1.00 |
| 'Raw client: BatchWriteItem deletes (not atomic, no count)' | 1 | 7.505 ms | 1.788 ms | 1.396 ms | 0.95 | 0.26 | 28.34 KB | 0.94 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 1 | 7.487 ms | 1.327 ms | 1.036 ms | 0.95 | 0.24 | 31.95 KB | 1.06 |
| 'Raw client: DeleteItem (ALL_OLD) / TransactWriteItems of conditional deletes' | 25 | 78.003 ms | 14.213 ms | 11.096 ms | 1.02 | 0.19 | 43.37 KB | 1.00 |
| 'Raw client: BatchWriteItem deletes (not atomic, no count)' | 25 | 87.019 ms | 9.526 ms | 7.437 ms | 1.13 | 0.17 | 37.45 KB | 0.86 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 25 | 76.493 ms | 8.238 ms | 6.432 ms | 1.00 | 0.15 | 90.8 KB | 2.09 |
| 'Raw client: DeleteItem (ALL_OLD) / TransactWriteItems of conditional deletes' | 100 | 91.716 ms | 13.044 ms | 10.184 ms | 1.01 | 0.15 | 90.01 KB | 1.00 |
| 'Raw client: BatchWriteItem deletes (not atomic, no count)' | 100 | 364.180 ms | 42.505 ms | 33.185 ms | 4.01 | 0.55 | 144.13 KB | 1.60 |
| 'ARX DeleteAsync / DeleteMultipleAsync' | 100 | 97.121 ms | 17.458 ms | 13.630 ms | 1.07 | 0.18 | 275.07 KB | 3.06 |
RetrieveBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw client: GetItem / Query pages' | 1 | 1.484 ms | 0.2529 ms | 0.1323 ms | 1.01 | 0.12 | 5.8594 | - | 28.68 KB | 1.00 |
| 'DynamoDBContext LoadAsync / QueryAsync' | 1 | 1.910 ms | 0.2628 ms | 0.1374 ms | 1.30 | 0.14 | 3.9063 | - | 35.24 KB | 1.23 |
| 'ARX RetrieveAsync / RetrieveMultipleAsync' | 1 | 1.710 ms | 0.0890 ms | 0.0395 ms | 1.16 | 0.10 | 3.9063 | - | 31.53 KB | 1.10 |
| 'Raw client: GetItem / Query pages' | 100 | 4.385 ms | 0.5940 ms | 0.3107 ms | 1.00 | 0.10 | 54.6875 | 15.6250 | 283.04 KB | 1.00 |
| 'DynamoDBContext LoadAsync / QueryAsync' | 100 | 4.086 ms | 0.7836 ms | 0.4098 ms | 0.94 | 0.11 | 78.1250 | 23.4375 | 415.75 KB | 1.47 |
| 'ARX RetrieveAsync / RetrieveMultipleAsync' | 100 | 4.429 ms | 0.7136 ms | 0.3732 ms | 1.01 | 0.11 | 70.3125 | 23.4375 | 379.97 KB | 1.34 |
| 'Raw client: GetItem / Query pages' | 1000 | 22.038 ms | 1.3404 ms | 0.5952 ms | 1.00 | 0.04 | 437.5000 | 343.7500 | 2584.03 KB | 1.00 |
| 'DynamoDBContext LoadAsync / QueryAsync' | 1000 | 25.530 ms | 1.6240 ms | 0.7210 ms | 1.16 | 0.04 | 583.3333 | 500.0000 | 3848.85 KB | 1.49 |
| 'ARX RetrieveAsync / RetrieveMultipleAsync' | 1000 | 25.910 ms | 3.1513 ms | 1.6482 ms | 1.18 | 0.08 | 538.4615 | 307.6923 | 3475.47 KB | 1.34 |
IndexAndScanBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw client: Query GSI1 pages (200 orders by status)' | Index | 7.058 ms | 2.5842 ms | 1.1474 ms | 1.02 | 0.21 | 93.7500 | 46.8750 | 538.91 KB | 1.00 |
| 'ARX RetrieveMultipleAsync through GSI1' | Index | 6.778 ms | 0.9655 ms | 0.4287 ms | 0.98 | 0.14 | 140.6250 | 78.1250 | 835.88 KB | 1.55 |
| 'Raw client: Scan pages with a filter (1,000 products, int_value >= 500)' | Scan | 18.226 ms | 1.6797 ms | 0.8785 ms | 1.00 | 0.06 | 187.5000 | 156.2500 | 1248.34 KB | 1.00 |
| 'ARX RetrieveMultipleAsync with AllowScan' | Scan | 18.660 ms | 2.2010 ms | 0.9772 ms | 1.03 | 0.07 | 312.5000 | 187.5000 | 1880.14 KB | 1.51 |
ShardedReadBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Rows | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw client: Query each shard in parallel, then merge by SK' | 100 | 3.995 ms | 0.5194 ms | 0.1852 ms | 1.00 | 0.06 | 54.6875 | 15.6250 | 272.23 KB | 1.00 |
| 'ARX RetrieveMultipleAsync of the page (shards merged)' | 100 | 4.382 ms | 0.7215 ms | 0.3204 ms | 1.10 | 0.09 | 78.1250 | 23.4375 | 382.37 KB | 1.40 |
| 'Raw client: Query each shard in parallel, then merge by SK' | 1000 | 13.050 ms | 1.0940 ms | 0.5722 ms | 1.00 | 0.06 | 281.2500 | 187.5000 | 1735.18 KB | 1.00 |
| 'ARX RetrieveMultipleAsync of the page (shards merged)' | 1000 | 14.644 ms | 2.2851 ms | 1.1951 ms | 1.12 | 0.10 | 437.5000 | 406.2500 | 2710.37 KB | 1.56 |
DocumentModelBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| 'Raw client: PutItem with attribute_not_exists' | Create | 5.890 ms | 0.7810 ms | 0.4085 ms | 1.00 | 0.09 | - | 28.27 KB | 1.00 |
| 'Document model: Table.PutItemAsync with the same condition' | Create | 6.140 ms | 1.2497 ms | 0.5549 ms | 1.05 | 0.11 | - | 34.81 KB | 1.23 |
| 'ARX CreateAsync' | Create | 5.949 ms | 1.3954 ms | 0.6196 ms | 1.01 | 0.12 | - | 32.54 KB | 1.15 |
| 'Raw client: GetItem (consistent)' | Retrieve | 1.662 ms | 0.5897 ms | 0.3084 ms | 1.03 | 0.24 | 5.8594 | 28.69 KB | 1.00 |
| 'Document model: Table.GetItemAsync (consistent)' | Retrieve | 1.861 ms | 0.1655 ms | 0.0866 ms | 1.15 | 0.19 | 3.9063 | 32.76 KB | 1.14 |
| 'ARX RetrieveAsync' | Retrieve | 1.791 ms | 0.4265 ms | 0.2231 ms | 1.11 | 0.22 | 5.8594 | 31.54 KB | 1.10 |
BatchGetBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Standard : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=Standard IterationCount=8 LaunchCount=1
WarmupCount=3
| Method | Keys | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|---|
| 'Raw client: BatchGetItem (consistent, UnprocessedKeys retried)' | 25 | 8.151 ms | 0.6995 ms | 0.3659 ms | 1.00 | 0.06 | 15.6250 | - | 95.93 KB | 1.00 |
| 'DynamoDBContext batch get (consistent)' | 25 | 8.995 ms | 1.6401 ms | 0.8578 ms | 1.11 | 0.11 | 31.2500 | - | 191.02 KB | 1.99 |
| 'Raw client: one GetItem per key, in parallel' | 25 | 15.284 ms | 8.5942 ms | 4.4950 ms | 1.88 | 0.53 | 156.2500 | 31.2500 | 717.78 KB | 7.48 |
| 'ARX: one RetrieveAsync per key, in parallel' | 25 | 11.557 ms | 2.8564 ms | 1.4939 ms | 1.42 | 0.18 | 156.2500 | 62.5000 | 785.81 KB | 8.19 |
| 'Raw client: BatchGetItem (consistent, UnprocessedKeys retried)' | 100 | 71.995 ms | 13.7967 ms | 7.2160 ms | 1.01 | 0.15 | - | - | 303.47 KB | 1.00 |
| 'DynamoDBContext batch get (consistent)' | 100 | 71.251 ms | 6.2568 ms | 3.2724 ms | 1.00 | 0.12 | 142.8571 | - | 684.99 KB | 2.26 |
| 'Raw client: one GetItem per key, in parallel' | 100 | 39.684 ms | 3.6582 ms | 1.6243 ms | 0.56 | 0.07 | 454.5455 | 363.6364 | 2870.47 KB | 9.46 |
| 'ARX: one RetrieveAsync per key, in parallel' | 100 | 49.407 ms | 11.7926 ms | 5.2360 ms | 0.69 | 0.11 | 454.5455 | 363.6364 | 3146.82 KB | 10.37 |
MoveBenchmarks
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.9711/25H2/2025Update/HudsonValley2)
Intel Core i7-8750H CPU 2.20GHz (Max: 2.21GHz) (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.403
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
SingleOperation : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3
Job=SingleOperation InvocationCount=1 IterationCount=12
LaunchCount=1 RunStrategy=Monitoring UnrollFactor=1
WarmupCount=1
| Method | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|
| 'Raw client: GetItem, then TransactWriteItems (conditional delete + conditional put)' | 5.714 ms | 0.2964 ms | 0.2314 ms | 1.00 | 0.06 | 74.83 KB | 1.00 |
| 'ARX UpdateAsync with AllowKeyChange' | 6.511 ms | 1.4933 ms | 1.1658 ms | 1.14 | 0.20 | 84.39 KB | 1.13 |
Run them yourself
The benchmark code is published, so you can check these numbers on your own machine and database: arx-benchmark-dynamodb.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.