Skip to content

stonstad/Stellar.Benchmarks

Repository files navigation

Stellar.Benchmarks

Benchmarks for .NET Embedded Databases and Persistent Storage

Why do these benchmarks exist?

As a game developer, I needed a high-concurrency storage solution suitable for player-managed game servers. Installing traditional local databases posed too high a demand on players. I found that the available storage solutions were either too slow or struggled with concurrency issues during high volumes of simultaneous reads and writes. Such limitations are impractical for game servers, which must support a large number of players efficiently. I created a survey of available embedded solutions for C#/.NET. Full disclosure: I am the creator of Stellar.FastDB.

Benchmark Configuration

Software

  • Windows 11 (10.0.22631.3447/23H2/2023Update/SunValley3)
  • .NET 8.0.4 (8.0.424.16909)
  • X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI

Hardware

  • AMD Ryzen 9 7950X, 1 CPU, 32 logical and 16 physical cores
  • Western Digital SN850X NVMe Gen4 PCIe SSD 2TB

Each benchmark undergoes a warm-up iteration, followed by three additional iterations to calculate the benchmark's error and standard deviation. The complete source code for each test is available in this repository.

Products

Each product is evaluated using its default settings.

Product License Package Version
Stellar.FastDB MIT License Stellar.FastDB 1.0.3
LiteDB MIT License LiteDB 5.0.19
SQLite MIT License Microsoft.Data.Sqlite 8.0.4
VistaDB Commercial Unavailable 6.3

Results

The tests conducted involve inserting, deleting, upserting, or querying records. For relational embedded databases like VistaDB and SQLite, operations are performed directly through table insertions. In contrast, document-oriented databases such as VistaDB and FastDB utilize serialization methods: VistaDB employs BSON serialization, while FastDB uses either UTF8 JSON or MessagePack binary. Complete test results are available within this repository.

Insert

The benchmarks involve inserting batches of 1K, 5K, and 10K records, with each operation focusing on an insert. After each benchmark, the size of the database file is recorded. Testing larger datasets, such as 500K records, with LiteDB, SQLite, and VistaDB is impractical due to the extended duration of these tests.

FastDB and SQLite provide the smallest storage footprints among the databases tested. Notably, FastDB performs inserts significantly faster than its counterparts.

Method Product Op/s FileSize
Insert1000 FastDB 193,550.9 64 KB
Insert5000 FastDB 197,049.3 326 KB
Insert10000 FastDB 192,855.8 653 KB
Insert1000 LiteDB 1,778.9 136 KB
Insert5000 LiteDB 1,310.2 816 KB
Insert10000 LiteDB 1,251.0 1,656 KB
Insert1000 SQLite 713.3 52 KB
Insert5000 SQLite 747.6 228 KB
Insert10000 SQLite 753.7 444 KB
Insert1000 VistaDB 2,503.1 124 KB
Insert5000 VistaDB 4,078.1 484 KB
Insert10000 VistaDB 2,648.0 940 KB

Delete

Deletes 1K, 5K, and 10K records. Among the databases evaluated, FastDB consistently achieves the fastest deletion times.

Method Product Op/s FileSize
Delete1000 FastDB 181,408.1 64 KB
Delete5000 FastDB 179,938.7 326 KB
Delete10000 FastDB 164,177.6 653 KB
Delete1000 LiteDB 1,337.3 192 KB
Delete5000 LiteDB 1,256.5 848 KB
Delete10000 LiteDB 1,207.7 1,664 KB
Delete1000 SQLite 741.9 52 KB
Delete5000 SQLite 748.4 228 KB
Delete10000 SQLite 757.6 444 KB
Delete1000 VistaDB 5,182.7 124 KB
Delete5000 VistaDB 6,537.4 484 KB
Delete10000 VistaDB 5,503.5 940 KB

Upsert

Upserts 1K, 5K, and 10K records.

Method Product Op/s FileSize
Upsert1000 FastDB 102,105.1 64 KB
Upsert5000 FastDB 98,313.4 326 KB
Upsert10000 FastDB 93,633.9 653 KB
Upsert1000 LiteDB 3,471.8 192 KB
Upsert5000 LiteDB 3,441.2 848 KB
Upsert10000 LiteDB 3,192.2 1,664 KB
Upsert1000 SQLite 729.9 52 KB
Upsert5000 SQLite 743.3 228 KB
Upsert10000 SQLite 741.9 444 KB
Upsert1000 VistaDB 4,935.4 124 KB
Upsert5000 VistaDB 3,442.2 484 KB
Upsert10000 VistaDB 2,372.8 940 KB

Bulk

Bulk inserts 1K, 5K, or 10K records. Almost all tested solutions demonstrate significant performance gains during bulk-insert operations. While VistaDB lacks a standard bulk insert API, it provides alternative methods for efficient data insertion, such as DDA (Direct Data Access) and CLR (Common Language Runtime) procedures.

Method Product Op/s FileSize
Bulk1000 FastDB 217,646.8 64 KB
Bulk5000 FastDB 226,483.1 326 KB
Bulk10000 FastDB 226,075.9 653 KB
Bulk1000 LiteDB 52,103.5 8 KB
Bulk5000 LiteDB 44,871.5 8 KB
Bulk10000 LiteDB 44,219.3 8 KB
Bulk1000 SQLite 196,256.7 52 KB
Bulk5000 SQLite 290,778.0 228 KB
Bulk10000 SQLite 294,455.4 444 KB
Bulk1000 VistaDB 2,582.1 136 KB
Bulk5000 VistaDB 4,657.8 496 KB
Bulk10000 VistaDB 2,706.4 952 KB

Query

Queries against a dataset of 1K, 5K, or 10K records and constructs a Customer instance for each result.

Queries records and returns a corresponding dataset.

  • FastDB and LiteDB: Customers.Where(a => a.Name.StartsWith("John") && a.Telephone > 5555555)
  • SQLite and VistaDB: "SELECT * FROM Customers WHERE Name LIKE 'John%' AND Telephone > 5555555"
Method Product Op/s FileSize
Query1000 FastDB 14,992,503.7 64 KB
Query5000 FastDB 9,416,787.0 326 KB
Query10000 FastDB 12,080,699.1 653 KB
Query1000 LiteDB 249,787.7 136 KB
Query5000 LiteDB 446,071.4 816 KB
Query10000 LiteDB 497,798.9 1,656 KB
Query1000 SQLite 2,200,704.2 52 KB
Query5000 SQLite 1,553,824.5 228 KB
Query10000 SQLite 2,227,601.5 444 KB
Query1000 VistaDB 74,732.6 124 KB
Query5000 VistaDB 418,324.9 484 KB
Query10000 VistaDB 574,299.0 940 KB

Additional FastDB Benchmarks

The benchmarks presented here focus on FastDB's unique capabilities. FastDB effortlessly accomodates up to 1 million records through a combination of a fast insertion and a compact storage footprint.

FastDB Insert Performance

Method Product Mode Op/s FileSize
Insert1000 FastDB Single 188,786.1 36 KB
Insert10000 FastDB Single 192,850.3 370 KB
Insert100000 FastDB Single 238,873.6 4084 KB
Insert1000000 FastDB Single 236,358.7 48479 KB
Insert1000 FastDB Bulk 222,819.7 36 KB
Insert10000 FastDB Bulk 231,856.1 370 KB
Insert100000 FastDB Bulk 307,370.7 4084 KB
Insert1000000 FastDB Bulk 294,974.6 48479 KB

FastDB Serialization and Parallelism

The default out-of-the-box configuration for FastDB does not include serialization contracts or parallel serialization. However, enabling parallelization significantly enhances the performance of serialization, compression, and encryption operations in FastDB. While the impact on small records is minimal, the difference becomes substantial when dealing with larger records, as demonstrated in the subsequent test.

Method Product Op/s FileSize
Default 10000 FastDB 196,703.5 653 KB
Contract 10000 FastDB 194,597.2 370 KB
Parallel 10000 FastDB 216,106.1 370 KB

FastDB Large Record Parallelism

When dealing with large records, which is often the case with serialized object graphs, the computational cost of compression and encryption can be substantial. In this benchmark, a significant amount of Lorem Ipsum text is stored both with and without encryption or compression. Enabling both compression and encryption markedly reduces throughput. However, by distributing this workload across threads, FastDB achieves nearly the same performance as writing unencrypted and uncompressed storage.

Method Product Op/s FileSize
Large FastDB 124,763.3 20096 KB
LargeEncrypted FastDB 95,370.7 20205 KB
LargeEncryptedCompressed FastDB 63,603.0 14892 KB
LargeEncryptedCompressedParallel FastDB 124,720.8 14892 KB

Releases

No releases published

Packages

No packages published

Languages