Skip to content

Continuous Benchmark for ORM libraries written in golang.

License

Notifications You must be signed in to change notification settings

benchplus/goorm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

goorm

Continuous Benchmark for ORM libraries written in golang.

English | δΈ­ζ–‡

Overview

This repository provides performance benchmarks for popular Go ORM libraries using SQLite as the test database. The benchmarks are designed to compare the performance of different ORM libraries across common database operations.

Tested ORM Libraries

  • ZORM - A simple, ultra-fast ORM library
  • BORM - A better ORM library that is simple, fast and self-mockable for Go
  • GORM - The most popular ORM library for Go
  • SQLX - A library which provides a set of extensions on go's standard database/sql library
  • XORM - A simple and powerful ORM for Go
  • ENT - An entity framework for Go
  • BUN - SQL-first Golang ORM

Benchmark Tests

The following operations are benchmarked:

Test Case Description
InsertSingle Single record insertion performance
InsertBatch Batch insertion performance (100 records per batch)
GetByID Single record retrieval by primary key
GetByIDs Multiple records retrieval by primary keys
Update Record update performance
Delete Record deletion performance
Count Count query performance
GetAll Paginated query performance (limit/offset)

Running Benchmarks

Prerequisites

  • Go 1.21 or higher
  • SQLite3

Run All Benchmarks

go test -bench=. -benchmem

Run Specific ORM Benchmark

# ZORM only
go test -bench=ZORM -benchmem

# BORM only
go test -bench=BORM -benchmem

# GORM only
go test -bench=GORM -benchmem

# XORM only
go test -bench=XORM -benchmem

# SQLX only
go test -bench=SQLX -benchmem

# BUN only
go test -bench=BUN -benchmem

# ENT only
go test -bench=ENT -benchmem

Run Specific Test Case

# Insert single test for all ORMs
go test -bench=InsertSingle -benchmem

# GetByID test for all ORMs
go test -bench=GetByID -benchmem

Benchmark Results

Quick Summary

Test Case ZORM BORM BUN ENT GORM SQLX XORM
InsertSingle🟒 1x🟒 1x🟠 3.13x🟠 3.46xπŸ”΄ 7.09xπŸ”΄ 60.61xπŸ”΄ 61.12x
InsertBatch🟒 1x🟒 1x🟑 1.30x🟠 2.50x🟑 1.89x🟠 3.57x🟠 3.33x
GetByID🟒 1x🟒 1x🟑 1.52x🟑 1.85x🟑 1.90x🟠 2x🟠 3.12x
GetByIDs🟒 1x🟒 1x🟑 1.17x🟑 1.38x🟑 1.39x🟑 1.36x🟑 1.98x
Update🟒 1x🟒 1x🟠 2.67xπŸ”΄ 9.86xπŸ”΄ 7.06xπŸ”΄ 82.52xπŸ”΄ 84x
Delete🟒 1x🟒 1x🟠 2.31x🟠 2.62xπŸ”΄ 6.40xπŸ”΄ 105.84xπŸ”΄ 101.85x
Count🟒 1x🟒 1x🟠 2.15xπŸ”΄ 13.40x🟠 2.99x🟠 4.34xπŸ”΄ 5.95x
GetAll🟒 1x🟒 1x🟑 1.14x🟑 1.21x🟑 1.43x🟑 1.18x🟑 1.91x

Ratio indicates performance multiplier relative to the fastest ORM (lower is better)

⭐ indicates the ORM is both fast and memory-efficient for this test case (Pareto-optimal in ns/op and B/op, lower is better). Stars are placed in the ns/op and B/op columns.

Detailed Results

Test Environment

  • Go Version: 1.21+
  • Database: SQLite (in-memory, DSN uses cache=shared&mode=memory)
  • CPU: M4 Pro
  • OS: darwin (amd64)

The benchmark results show:

  • ns/op: Nanoseconds per operation
  • B/op: Bytes allocated per operation
  • allocs/op: Number of allocations per operation

InsertSingle (Single Record Insertion)

ORM ns/op Ratio B/op allocs/op
ZORM2,913 ⭐🟒 1x464 ⭐16
BORM2,916🟒 1x46416
BUN9,123🟠 3.13x5,40527
ENT10,065🟠 3.46x2,64274
GORM20,652πŸ”΄ 7.09x6,11696
SQLX176,553πŸ”΄ 60.61x63218
XORM178,033πŸ”΄ 61.12x2,69054

InsertBatch (Batch Insertion - 100 records)

ORM ns/op Ratio B/op allocs/op
BORM104,405🟒 1x59,503912
ZORM104,862🟒 1x59,502 ⭐912
BUN136,110🟑 1.30x24,455723
GORM197,739🟑 1.89x74,9291,494
ENT261,124🟠 2.50x213,8053,360
XORM347,846🟠 3.33x98,8302,449
SQLX373,004🟠 3.57x47,3491,622

GetByID (Single Record Retrieval)

ORM ns/op Ratio B/op allocs/op
ZORM4,729 ⭐🟒 1x939 ⭐33
BORM4,776🟒 1x93933
BUN7,191🟑 1.52x5,70036
ENT8,766🟑 1.85x3,812103
GORM8,975🟑 1.90x4,07673
SQLX9,471🟠 2x1,15537
XORM14,750🟠 3.12x4,809139

GetByIDs (Multiple Records Retrieval - 10 records)

ORM ns/op Ratio B/op allocs/op
BORM18,082 ⭐🟒 1x3,511 ⭐95
ZORM18,257🟒 1x3,51195
BUN21,171🟒 1.17x7,467107
SQLX24,623🟑 1.36x4,051116
ENT24,997🟑 1.38x9,679230
GORM25,137🟑 1.39x7,369186
XORM35,883🟑 1.98x12,918400

Update (Record Update)

ORM ns/op Ratio B/op allocs/op
ZORM2,103 ⭐🟒 1x454 ⭐13
BORM2,107🟒 1x45413
BUN5,607🟠 2.67x5,04415
GORM14,845πŸ”΄ 7.06x7,44299
ENT20,745πŸ”΄ 9.86x5,608156
SQLX173,533πŸ”΄ 82.52x65416
XORM176,658πŸ”΄ 84x4,082103

Delete (Record Deletion)

ORM ns/op Ratio B/op allocs/op
BORM1,646🟒 1x1607
ZORM1,667🟒 1x159 ⭐7
BUN3,798🟠 2.31x4,88014
ENT4,318🟠 2.62x1,83244
GORM10,536πŸ”΄ 6.40x5,57175
XORM167,642πŸ”΄ 101.85x3,04380
SQLX174,217πŸ”΄ 105.84x25510

Count (Count Query)

ORM ns/op Ratio B/op allocs/op
ZORM1,546 ⭐🟒 1x440 ⭐14
BORM1,555🟒 1x44014
BUN3,327🟠 2.15x1,28823
GORM4,617🟠 2.99x2,72033
SQLX6,716🟠 4.34x50416
XORM9,193πŸ”΄ 5.95x2,39461
ENT20,720πŸ”΄ 13.40x2,38454

GetAll (Paginated Query - limit 100, offset)

ORM ns/op Ratio B/op allocs/op
ZORM95,365 ⭐🟒 1x14,829 ⭐607
BORM95,795🟒 1x14,829607
BUN109,081🟒 1.14x21,955709
SQLX112,556🟒 1.18x17,526712
ENT115,475🟑 1.21x43,3011,256
GORM136,701🟑 1.43x25,3111,128
XORM182,305🟑 1.91x74,8692,771

Test Database

All benchmarks use SQLite as the test database:

  • In-memory database for fast performance
  • Temporary files are automatically cleaned up after tests
  • Each ORM uses its own isolated database instance

Project Structure

goorm/
β”œβ”€β”€ gorm/          # GORM implementation
β”œβ”€β”€ xorm/          # XORM implementation
β”œβ”€β”€ zorm/          # ZORM implementation
β”œβ”€β”€ sqlx/           # SQLX implementation
β”œβ”€β”€ borm/           # BORM implementation
β”œβ”€β”€ bun/            # BUN implementation
β”œβ”€β”€ ent/             # ENT implementation
β”‚   └── schema/      # ENT schema definitions
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ models/     # Test models (User, Post)
β”‚   └── orm/        # Unified ORM interface
β”œβ”€β”€ goorm_test.go   # Benchmark tests
β”œβ”€β”€ go.mod          # Go module file
└── README.md       # This file

Adding New ORM Libraries

To add a new ORM library:

  1. Create a new directory (e.g., ent/)
  2. Implement the ORMInterface in a new file
  3. Add the ORM to the orms map in goorm_test.go
  4. Add benchmark functions following the naming pattern

Note for ENT: ENT requires code generation. After adding the schema files, run:

go generate ./ent

This will generate the ENT client code needed for the implementation.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

References

About

Continuous Benchmark for ORM libraries written in golang.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Languages