只使用lru

This commit is contained in:
xiezhaodong 2025-04-24 16:00:01 +08:00
parent 618e8c1aa6
commit 3f922a78c8
4 changed files with 130 additions and 98 deletions

View File

@ -35,7 +35,9 @@ type Config struct {
// PrepareStmt executes the given query in cached statement
PrepareStmt bool
// PrepareStmt cache support LRU expired
PrepareStmtLruConfig *PrepareStmtLruConfig
PrepareStmtMaxSize int
PrepareStmtTTL time.Duration
// DisableAutomaticPing
DisableAutomaticPing bool
// DisableForeignKeyConstraintWhenMigrating
@ -204,7 +206,7 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
}
if config.PrepareStmt {
preparedStmt := NewPreparedStmtDB(db.ConnPool, config.PrepareStmtLruConfig)
preparedStmt := NewPreparedStmtDB(db.ConnPool, config.PrepareStmtMaxSize, config.PrepareStmtTTL)
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
db.ConnPool = preparedStmt
}
@ -275,7 +277,7 @@ func (db *DB) Session(config *Session) *DB {
if v, ok := db.cacheStore.Load(preparedStmtDBKey); ok {
preparedStmt = v.(*PreparedStmtDB)
} else {
preparedStmt = NewPreparedStmtDB(db.ConnPool, db.Config.PrepareStmtLruConfig)
preparedStmt = NewPreparedStmtDB(db.ConnPool, db.Config.PrepareStmtMaxSize, db.Config.PrepareStmtTTL)
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
}

View File

@ -1,4 +1,4 @@
package gorm
package lru
// golang -lru
//https://github.com/hashicorp/golang-lru

View File

@ -0,0 +1,84 @@
package store
import (
"fmt"
"gorm.io/gorm"
"gorm.io/gorm/internal/lru"
"time"
)
type StmtStore interface {
Get(key string) (*gorm.Stmt, bool)
Set(key string, value *gorm.Stmt)
Delete(key string)
AllMap() map[string]*gorm.Stmt
}
/*
type DefaultStmtStore struct {
defaultStmt map[string]*gorm.Stmt
}
func (s *DefaultStmtStore) Init() *DefaultStmtStore {
s.defaultStmt = make(map[string]*gorm.Stmt)
return s
}
func (s *DefaultStmtStore) AllMap() map[string]*gorm.Stmt {
return s.defaultStmt
}
func (s *DefaultStmtStore) Get(key string) (*gorm.Stmt, bool) {
stmt, ok := s.defaultStmt[key]
return stmt, ok
}
func (s *DefaultStmtStore) Set(key string, value *gorm.Stmt) {
s.defaultStmt[key] = value
}
func (s *DefaultStmtStore) Delete(key string) {
delete(s.defaultStmt, key)
}
*/
type LruStmtStore struct {
lru *lru.LRU[string, *gorm.Stmt]
}
func (s *LruStmtStore) NewLru(size int, ttl time.Duration) {
onEvicted := func(k string, v *gorm.Stmt) {
if v != nil {
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Print("close stmt err panic ")
}
}()
if v != nil {
err := v.Close()
if err != nil {
//
fmt.Print("close stmt err: ", err.Error())
}
}
}()
}
}
s.lru = lru.NewLRU[string, *gorm.Stmt](size, onEvicted, ttl)
}
func (s *LruStmtStore) AllMap() map[string]*gorm.Stmt {
return s.lru.KeyValues()
}
func (s *LruStmtStore) Get(key string) (*gorm.Stmt, bool) {
stmt, ok := s.lru.Get(key)
return stmt, ok
}
func (s *LruStmtStore) Set(key string, value *gorm.Stmt) {
s.lru.Add(key, value)
}
func (s *LruStmtStore) Delete(key string) {
s.lru.Remove(key)
}

View File

@ -5,7 +5,7 @@ import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"gorm.io/gorm/internal/store"
"reflect"
"sync"
"time"
@ -19,31 +19,52 @@ type Stmt struct {
}
type PreparedStmtDB struct {
Stmts StmtStore
Stmts store.StmtStore
Mux *sync.RWMutex
ConnPool
}
func newPrepareStmtCache(prepareStmtLruConfig *PrepareStmtLruConfig) *StmtStore {
var stmts StmtStore
if prepareStmtLruConfig != nil && prepareStmtLruConfig.Open {
if prepareStmtLruConfig.Size <= 0 {
panic("LRU prepareStmtLruConfig.Size must > 0")
}
lru := &LruStmtStore{}
lru.NewLru(prepareStmtLruConfig.Size, prepareStmtLruConfig.TTL)
stmts = lru
} else {
defaultStmtStore := &DefaultStmtStore{}
stmts = defaultStmtStore.init()
const DEFAULT_MAX_SIZE = (1 << 63) - 1
const DEFAULT_TTL = time.Hour * 24
// newPrepareStmtCache creates a new statement cache with the specified maximum size and time-to-live (TTL).
// Parameters:
// - PrepareStmtMaxSize: An integer specifying the maximum number of prepared statements to cache.
// If this value is less than or equal to 0, the function will panic.
// - PrepareStmtTTL: A time.Duration specifying the TTL for cached statements.
// If this value differs from the default TTL, it will be used instead.
//
// Returns:
// - A pointer to a store.StmtStore instance configured with the provided parameters.
//
// The function initializes an LRU (Least Recently Used) cache for prepared statements,
// using either the provided size and TTL or default values
func newPrepareStmtCache(PrepareStmtMaxSize int,
PrepareStmtTTL time.Duration) *store.StmtStore {
var lru_size = DEFAULT_MAX_SIZE
var lru_ttl = DEFAULT_TTL
var stmts store.StmtStore
if PrepareStmtMaxSize <= 0 {
panic("PrepareStmtMaxSize must > 0")
}
if PrepareStmtMaxSize != 0 {
lru_size = PrepareStmtMaxSize
}
if PrepareStmtTTL != DEFAULT_TTL {
lru_ttl = PrepareStmtTTL
}
lru := &store.LruStmtStore{}
lru.NewLru(lru_size, lru_ttl)
stmts = lru
return &stmts
}
func NewPreparedStmtDB(connPool ConnPool, prepareStmtLruConfig *PrepareStmtLruConfig) *PreparedStmtDB {
func NewPreparedStmtDB(connPool ConnPool, PrepareStmtMaxSize int,
PrepareStmtTTL time.Duration) *PreparedStmtDB {
return &PreparedStmtDB{
ConnPool: connPool,
Stmts: *newPrepareStmtCache(prepareStmtLruConfig),
Mux: &sync.RWMutex{},
Stmts: *newPrepareStmtCache(PrepareStmtMaxSize,
PrepareStmtTTL),
Mux: &sync.RWMutex{},
}
}
@ -94,9 +115,8 @@ func (sdb *PreparedStmtDB) Reset() {
}
}(stmt)
}
defaultStmt := &DefaultStmtStore{}
defaultStmt.init()
sdb.Stmts = defaultStmt
defaultStmt := newPrepareStmtCache(0, 0)
sdb.Stmts = *defaultStmt
}
func (db *PreparedStmtDB) prepare(ctx context.Context, conn ConnPool, isTransaction bool, query string) (Stmt, error) {
@ -303,77 +323,3 @@ func (tx *PreparedStmtTX) Ping() error {
}
return conn.Ping()
}
type StmtStore interface {
Get(key string) (*Stmt, bool)
Set(key string, value *Stmt)
Delete(key string)
AllMap() map[string]*Stmt
}
type DefaultStmtStore struct {
defaultStmt map[string]*Stmt
}
func (s *DefaultStmtStore) init() *DefaultStmtStore {
s.defaultStmt = make(map[string]*Stmt)
return s
}
func (s *DefaultStmtStore) AllMap() map[string]*Stmt {
return s.defaultStmt
}
func (s *DefaultStmtStore) Get(key string) (*Stmt, bool) {
stmt, ok := s.defaultStmt[key]
return stmt, ok
}
func (s *DefaultStmtStore) Set(key string, value *Stmt) {
s.defaultStmt[key] = value
}
func (s *DefaultStmtStore) Delete(key string) {
delete(s.defaultStmt, key)
}
type LruStmtStore struct {
lru *LRU[string, *Stmt]
}
func (s *LruStmtStore) NewLru(size int, ttl time.Duration) {
onEvicted := func(k string, v *Stmt) {
if v != nil {
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Print("close stmt err panic ")
}
}()
if v != nil {
err := v.Close()
if err != nil {
//
fmt.Print("close stmt err: ", err.Error())
}
}
}()
}
}
s.lru = NewLRU[string, *Stmt](size, onEvicted, ttl)
}
func (s *LruStmtStore) AllMap() map[string]*Stmt {
return s.lru.KeyValues()
}
func (s *LruStmtStore) Get(key string) (*Stmt, bool) {
stmt, ok := s.lru.Get(key)
return stmt, ok
}
func (s *LruStmtStore) Set(key string, value *Stmt) {
s.lru.Add(key, value)
}
func (s *LruStmtStore) Delete(key string) {
s.lru.Remove(key)
}