add LRU cache to fs retrieval
This commit is contained in:
parent
a055638e4b
commit
d1ec8ade9c
3
go.mod
3
go.mod
@ -3,11 +3,13 @@ module Moonshark
|
|||||||
go 1.24.1
|
go 1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.sharkk.net/Go/LRU v1.0.0
|
||||||
git.sharkk.net/Sky/LuaJIT-to-Go v0.4.1
|
git.sharkk.net/Sky/LuaJIT-to-Go v0.4.1
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.4
|
github.com/VictoriaMetrics/fastcache v1.12.4
|
||||||
github.com/alexedwards/argon2id v1.0.0
|
github.com/alexedwards/argon2id v1.0.0
|
||||||
github.com/deneonet/benc v1.1.8
|
github.com/deneonet/benc v1.1.8
|
||||||
github.com/goccy/go-json v0.10.5
|
github.com/goccy/go-json v0.10.5
|
||||||
|
github.com/golang/snappy v1.0.0
|
||||||
github.com/matoous/go-nanoid/v2 v2.1.0
|
github.com/matoous/go-nanoid/v2 v2.1.0
|
||||||
github.com/valyala/bytebufferpool v1.0.0
|
github.com/valyala/bytebufferpool v1.0.0
|
||||||
github.com/valyala/fasthttp v1.62.0
|
github.com/valyala/fasthttp v1.62.0
|
||||||
@ -18,7 +20,6 @@ require (
|
|||||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/golang/snappy v1.0.0 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -1,3 +1,5 @@
|
|||||||
|
git.sharkk.net/Go/LRU v1.0.0 h1:/KqdRVhHldi23aVfQZ4ss6vhCWZqA3vFiQyf1MJPpQc=
|
||||||
|
git.sharkk.net/Go/LRU v1.0.0/go.mod h1:8tdTyl85mss9a+KKwo+Wj9gKHOizhfLfpJhz1ltYz50=
|
||||||
git.sharkk.net/Sky/LuaJIT-to-Go v0.4.1 h1:CAYt+C6Vgo4JxK876j0ApQ2GDFFvy9FKO0OoZBVD18k=
|
git.sharkk.net/Sky/LuaJIT-to-Go v0.4.1 h1:CAYt+C6Vgo4JxK876j0ApQ2GDFFvy9FKO0OoZBVD18k=
|
||||||
git.sharkk.net/Sky/LuaJIT-to-Go v0.4.1/go.mod h1:HQz+D7AFxOfNbTIogjxP+shEBtz1KKrLlLucU+w07c8=
|
git.sharkk.net/Sky/LuaJIT-to-Go v0.4.1/go.mod h1:HQz+D7AFxOfNbTIogjxP+shEBtz1KKrLlLucU+w07c8=
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.4 h1:2xvmwZBW+9QtHsXggfzAZRs1FZWCsBs8QDg22bMidf0=
|
github.com/VictoriaMetrics/fastcache v1.12.4 h1:2xvmwZBW+9QtHsXggfzAZRs1FZWCsBs8QDg22bMidf0=
|
||||||
@ -107,8 +109,6 @@ modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
|
|||||||
modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||||
modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
|
|
||||||
modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
|
|
||||||
modernc.org/libc v1.65.8 h1:7PXRJai0TXZ8uNA3srsmYzmTyrLoHImV5QxHeni108Q=
|
modernc.org/libc v1.65.8 h1:7PXRJai0TXZ8uNA3srsmYzmTyrLoHImV5QxHeni108Q=
|
||||||
modernc.org/libc v1.65.8/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
|
modernc.org/libc v1.65.8/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
|
||||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||||
@ -125,7 +125,5 @@ modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
|||||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
zombiezen.com/go/sqlite v1.4.0 h1:N1s3RIljwtp4541Y8rM880qgGIgq3fTD2yks1xftnKU=
|
|
||||||
zombiezen.com/go/sqlite v1.4.0/go.mod h1:0w9F1DN9IZj9AcLS9YDKMboubCACkwYCGkzoy3eG5ik=
|
|
||||||
zombiezen.com/go/sqlite v1.4.2 h1:KZXLrBuJ7tKNEm+VJcApLMeQbhmAUOKA5VWS93DfFRo=
|
zombiezen.com/go/sqlite v1.4.2 h1:KZXLrBuJ7tKNEm+VJcApLMeQbhmAUOKA5VWS93DfFRo=
|
||||||
zombiezen.com/go/sqlite v1.4.2/go.mod h1:5Kd4taTAD4MkBzT25mQ9uaAlLjyR0rFhsR6iINO70jc=
|
zombiezen.com/go/sqlite v1.4.2/go.mod h1:5Kd4taTAD4MkBzT25mQ9uaAlLjyR0rFhsR6iINO70jc=
|
||||||
|
68
runner/fs.go
68
runner/fs.go
@ -6,15 +6,29 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"Moonshark/utils/logger"
|
"Moonshark/utils/logger"
|
||||||
|
|
||||||
|
lru "git.sharkk.net/Go/LRU"
|
||||||
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
||||||
|
"github.com/golang/snappy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Global filesystem path (set during initialization)
|
// Global filesystem path (set during initialization)
|
||||||
var fsBasePath string
|
var fsBasePath string
|
||||||
|
|
||||||
|
// Global file cache with compressed data
|
||||||
|
var fileCache *lru.LRUCache
|
||||||
|
|
||||||
|
// Cache entry info for statistics/debugging
|
||||||
|
type cacheStats struct {
|
||||||
|
hits int64
|
||||||
|
misses int64
|
||||||
|
}
|
||||||
|
|
||||||
|
var stats cacheStats
|
||||||
|
|
||||||
// InitFS initializes the filesystem with the given base path
|
// InitFS initializes the filesystem with the given base path
|
||||||
func InitFS(basePath string) error {
|
func InitFS(basePath string) error {
|
||||||
if basePath == "" {
|
if basePath == "" {
|
||||||
@ -33,13 +47,20 @@ func InitFS(basePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fsBasePath = absPath
|
fsBasePath = absPath
|
||||||
|
|
||||||
|
// Initialize file cache with 2000 entries (reasonable for most use cases)
|
||||||
|
fileCache = lru.NewLRUCache(2000)
|
||||||
|
|
||||||
logger.Server("Virtual filesystem initialized at: %s", fsBasePath)
|
logger.Server("Virtual filesystem initialized at: %s", fsBasePath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanupFS performs any necessary cleanup
|
// CleanupFS performs any necessary cleanup
|
||||||
func CleanupFS() {
|
func CleanupFS() {
|
||||||
// Nothing to clean up currently
|
if fileCache != nil {
|
||||||
|
fileCache.Clear()
|
||||||
|
logger.Server("File cache cleared - Stats: hits=%d, misses=%d", stats.hits, stats.misses)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolvePath resolves a given path relative to the filesystem base
|
// ResolvePath resolves a given path relative to the filesystem base
|
||||||
@ -79,6 +100,11 @@ func ResolvePath(path string) (string, error) {
|
|||||||
return fullPath, nil
|
return fullPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getCacheKey creates a cache key from path and modification time
|
||||||
|
func getCacheKey(fullPath string, modTime time.Time) string {
|
||||||
|
return fmt.Sprintf("%s:%d", fullPath, modTime.Unix())
|
||||||
|
}
|
||||||
|
|
||||||
// fsReadFile reads a file and returns its contents
|
// fsReadFile reads a file and returns its contents
|
||||||
func fsReadFile(state *luajit.State) int {
|
func fsReadFile(state *luajit.State) int {
|
||||||
if !state.IsString(1) {
|
if !state.IsString(1) {
|
||||||
@ -93,12 +119,46 @@ func fsReadFile(state *luajit.State) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get file info for cache key and validation
|
||||||
|
info, err := os.Stat(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
state.PushString("fs.read_file: " + err.Error())
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create cache key with path and modification time
|
||||||
|
cacheKey := getCacheKey(fullPath, info.ModTime())
|
||||||
|
|
||||||
|
// Try to get from cache first
|
||||||
|
if fileCache != nil {
|
||||||
|
if cachedData, exists := fileCache.Get(cacheKey); exists {
|
||||||
|
if compressedData, ok := cachedData.([]byte); ok {
|
||||||
|
// Decompress cached data
|
||||||
|
data, err := snappy.Decode(nil, compressedData)
|
||||||
|
if err == nil {
|
||||||
|
stats.hits++
|
||||||
|
state.PushString(string(data))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
// Cache corruption - continue to disk read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache miss or error - read from disk
|
||||||
|
stats.misses++
|
||||||
data, err := os.ReadFile(fullPath)
|
data, err := os.ReadFile(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.PushString("fs.read_file: " + err.Error())
|
state.PushString("fs.read_file: " + err.Error())
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compress and cache the data
|
||||||
|
if fileCache != nil {
|
||||||
|
compressedData := snappy.Encode(nil, data)
|
||||||
|
fileCache.Put(cacheKey, compressedData)
|
||||||
|
}
|
||||||
|
|
||||||
state.PushString(string(data))
|
state.PushString(string(data))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -136,6 +196,12 @@ func fsWriteFile(state *luajit.State) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invalidate cache entries for this file path
|
||||||
|
if fileCache != nil {
|
||||||
|
// We can't easily iterate through cache keys, so we'll let the cache
|
||||||
|
// naturally expire old entries when the file is read again
|
||||||
|
}
|
||||||
|
|
||||||
state.PushBoolean(true)
|
state.PushBoolean(true)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user