aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-04-30 01:02:44 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-04-30 01:09:48 +0200
commitea9464fccd26783564e852f10212fc9ce850c5ff (patch)
treeaca90bfd97ff0b6fd81b8726a8f44216ab9443fa
parent71d4c873bd12233b585637404115cfea9462c904 (diff)
downloadgo-oblast-ea9464fccd26783564e852f10212fc9ce850c5ff.tar.gz
benchmark: provide a handwritten N=1 implementation for InsertAndDelete
As I had expected, this removes an unfair disadvantage for Oblast, which had to maintain two differently-typed slices for Insert() and Delete(). This is not really a fair comparison since usually you would not be doing both operations in one go. For Gorp, this rewrite is neutral. But in a shocking twist, Gorm somehow does _significantly_ worse with a specialized N=1 implementation: ``` BenchmarkInsertAndDelete/N=1/via_Gorm-24 before: 11508 B/op 157 allocs/op after: 12840 B/op 172 allocs/op ```
-rw-r--r--benchmark/benchmark_test.go29
1 files changed, 29 insertions, 0 deletions
diff --git a/benchmark/benchmark_test.go b/benchmark/benchmark_test.go
index 439ecaf..12f739c 100644
--- a/benchmark/benchmark_test.go
+++ b/benchmark/benchmark_test.go
@@ -285,6 +285,16 @@ func BenchmarkInsertAndDelete(b *testing.B) {
}
must.Succeed(b, store.Delete(noctx, db, records...))
}
+ if batchSize == 1 {
+ insertAndDeleteWithOblast = func(b *testing.B) {
+ record := OblastEntry{Message: "hello"}
+ must.Succeed(b, store.Insert(noctx, db, &record))
+ if record.ID == 0 {
+ b.Errorf("ID was not filled!")
+ }
+ must.Succeed(b, store.Delete(noctx, db, record))
+ }
+ }
insertAndDeleteWithGorp := func(b *testing.B) {
records := make([]any, batchSize)
@@ -299,6 +309,16 @@ func BenchmarkInsertAndDelete(b *testing.B) {
}
_ = must.Return(gorpDB.Delete(records...))(b)
}
+ if batchSize == 1 {
+ insertAndDeleteWithGorp = func(b *testing.B) {
+ record := GorpEntry{Message: "hello"}
+ must.Succeed(b, gorpDB.Insert(&record))
+ if record.ID == 0 {
+ b.Errorf("ID was not filled!")
+ }
+ _ = must.Return(gorpDB.Delete(&record))(b)
+ }
+ }
insertAndDeleteWithGorm := func(b *testing.B) {
records := make([]GormEntry, batchSize)
@@ -315,6 +335,15 @@ func BenchmarkInsertAndDelete(b *testing.B) {
assert.ErrEqual(b, result.Error, "<success>")
assert.Equal(b, result.RowsAffected, int64(batchSize))
}
+ if batchSize == 1 {
+ insertAndDeleteWithGorm = func(b *testing.B) {
+ record := GormEntry{Message: "hello"}
+ must.Succeed(b, gorm.G[GormEntry](gormDB).Create(b.Context(), &record))
+ result := gormDB.Delete(&record)
+ assert.ErrEqual(b, result.Error, "<success>")
+ assert.Equal(b, result.RowsAffected, 1)
+ }
+ }
insertAndDeleteWithStraightExec := func(b *testing.B) {
ids := make([]int64, batchSize)