-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Closed as not planned
Labels
Description
While running the code below, there is a chance of running into an error "fatal error: concurrent map writes
"
It happens suddenly and need to use loop running until it fails
while go test -bench=. -benchtime=0.1s; do :; done
go 1.22.6
require (
github.com/google/uuid v1.6.0
gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.12
)
require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
golang.org/x/text v0.20.0 // indirect
)
package main
import (
"github.com/google/uuid"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/schema"
"math/rand/v2"
"sync"
"testing"
)
type Data1 struct {
UUID uuid.UUID `gorm:"primaryKey;type:uuid"`
}
type Data2 struct {
UUID uuid.UUID `gorm:"primaryKey;type:uuid"`
}
type Data3 struct {
UUID uuid.UUID `gorm:"primaryKey;type:uuid"`
}
func BenchmarkParse(b *testing.B) {
cacheStore := &sync.Map{}
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
if err != nil {
b.Fatalf("failed to connect database")
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
switch rand.IntN(2) {
case 0:
_, _ = schema.ParseWithSpecialTableName([]*struct {
Data1
Data2 Data2 `gorm:"foreignKey:UUID;references:UUID"`
}{}, cacheStore, db.NamingStrategy, "")
case 1:
_, _ = schema.ParseWithSpecialTableName([]*struct {
Data1
Data2 Data2 `gorm:"foreignKey:UUID;references:UUID"`
Data3 Data3 `gorm:"foreignKey:UUID;references:UUID"`
}{}, cacheStore, db.NamingStrategy, "")
}
}
})
}
fatal error: concurrent map writes
goroutine 87 [running]:
gorm.io/gorm/schema.(*Schema).parseRelation(0xc00041e1e0, 0xc000420600)
/home/ponywka/go/pkg/mod/gorm.io/gorm@v1.25.12/schema/relationship.go:103 +0x5d8
gorm.io/gorm/schema.ParseWithSpecialTableName({0x71bc80, 0xc000236360}, 0xc00007e000, {0x7cc6b8, 0xc0001e4000}, {0x0, 0x0})
/home/ponywka/go/pkg/mod/gorm.io/gorm@v1.25.12/schema/schema.go:342 +0x22d8
storage.BenchmarkFind.func1(0xc00007f640)
/home/ponywka/Projects/test3/main_test.go:38 +0x125
testing.(*B).RunParallel.func1()
/home/ponywka/sdk/go1.22.6/src/testing/benchmark.go:797 +0xbf
created by testing.(*B).RunParallel in goroutine 11
/home/ponywka/sdk/go1.22.6/src/testing/benchmark.go:790 +0x116
It happens for me in Find
operation:
fatal error: concurrent map writes
goroutine 36 [running]:
gorm.io/gorm/schema.(*Schema).parseRelation(0xc0001f6000, 0xc0001fc800)
/go/pkg/mod/gorm.io/gorm@v1.25.12/schema/relationship.go:103 +0x5d8
gorm.io/gorm/schema.ParseWithSpecialTableName({0x10cc9c0, 0xc0001720c0}, 0xc000893360, {0x2364c78, 0xc000895300}, {0x0, 0x0})
/go/pkg/mod/gorm.io/gorm@v1.25.12/schema/schema.go:342 +0x22d8
gorm.io/gorm.(*Statement).ParseWithSpecialTableName(0xc000702fc0, {0x10cc9c0?, 0xc0001720c0?}, {0x0?, 0xc00055b278?})
/go/pkg/mod/gorm.io/gorm@v1.25.12/statement.go:493 +0x65
gorm.io/gorm.(*Statement).Parse(...)
/go/pkg/mod/gorm.io/gorm@v1.25.12/statement.go:489
gorm.io/gorm/callbacks.BuildQuerySQL(0xc00016f9e0)
/go/pkg/mod/gorm.io/gorm@v1.25.12/callbacks/query.go:89 +0x31d
gorm.io/gorm/callbacks.Query(0xc00016f9e0)
/go/pkg/mod/gorm.io/gorm@v1.25.12/callbacks/query.go:16 +0x36
gorm.io/gorm.(*processor).Execute(0xc00089ad70, 0xc000137e30?)
/go/pkg/mod/gorm.io/gorm@v1.25.12/callbacks.go:130 +0x3cc
gorm.io/gorm.(*DB).Find(0xc00016f9e0?, {0x10cc9c0, 0xc0001720c0}, {0x0, 0x0, 0x0})
/go/pkg/mod/gorm.io/gorm@v1.25.12/finisher_api.go:170 +0x134
XXX/XXX.XXX({0x235e398, 0x2d6f260})
/src/XXX.go:XXX +0x4b4
It happens because this is where the cache is used
Pic 1 Square 1: Initializing "relation" field
Pic 1 Square 2: Initializing "relation.FieldSchema" field using "getOrParse" function
Pic 2 Square 1: Loading parsed value from cache
Pic 1 Square 3: Mutate "relation.FieldSchema" field