Skip to content
14 changes: 7 additions & 7 deletions internal/cache/metadata/stat_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ type statCacheBucketView struct {
type entry struct {
m *gcs.MinObject
f *gcs.Folder
expiration time.Time
expiration int64
// Set to true only for implicit directory entries. This flag will always remain false for negative entries and explicit objects.
implicitDir bool
}
Expand Down Expand Up @@ -201,7 +201,7 @@ func (sc *statCacheBucketView) Insert(m *gcs.MinObject, expiration time.Time) {
// Insert an entry.
e := entry{
m: m,
expiration: expiration,
expiration: expiration.Unix(),
}
Comment thread
vedantdas-source marked this conversation as resolved.

if _, err := sc.sharedCache.Insert(name, e); err != nil {
Expand Down Expand Up @@ -237,7 +237,7 @@ func (sc *statCacheBucketView) InsertImplicitDir(objectName string, expiration t
// Insert an entry.
e := entry{
implicitDir: true,
expiration: expiration,
expiration: expiration.Unix(),
}
Comment thread
vedantdas-source marked this conversation as resolved.

if _, err := sc.sharedCache.Insert(name, e); err != nil {
Expand All @@ -251,7 +251,7 @@ func (sc *statCacheBucketView) AddNegativeEntry(objectName string, expiration ti
// Insert a negative entry.
e := entry{
m: nil,
expiration: expiration,
expiration: expiration.Unix(),
}
Comment thread
vedantdas-source marked this conversation as resolved.

if _, err := sc.sharedCache.Insert(name, e); err != nil {
Expand All @@ -265,7 +265,7 @@ func (sc *statCacheBucketView) AddNegativeEntryForFolder(folderName string, expi
// Insert a negative entry.
e := entry{
f: nil,
expiration: expiration,
expiration: expiration.Unix(),
}
Comment thread
vedantdas-source marked this conversation as resolved.

if _, err := sc.sharedCache.Insert(name, e); err != nil {
Expand Down Expand Up @@ -315,7 +315,7 @@ func (sc *statCacheBucketView) sharedCacheLookup(key string, now time.Time) (boo
e := value.(entry)

// Has this entry expired?
if e.expiration.Before(now) {
if e.expiration < now.Unix() {
sc.Erase(key)
return false, nil
}
Comment thread
vedantdas-source marked this conversation as resolved.
Expand All @@ -328,7 +328,7 @@ func (sc *statCacheBucketView) InsertFolder(f *gcs.Folder, expiration time.Time)

e := entry{
f: f,
expiration: expiration,
expiration: expiration.Unix(),
}

Comment thread
vedantdas-source marked this conversation as resolved.
if _, err := sc.sharedCache.Insert(name, e); err != nil {
Expand Down
85 changes: 85 additions & 0 deletions internal/cache/metadata/stat_cache_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package metadata_test

import (
"fmt"
"testing"
"time"

"github.com/googlecloudplatform/gcsfuse/v3/internal/cache/lru"
"github.com/googlecloudplatform/gcsfuse/v3/internal/cache/metadata"
"github.com/googlecloudplatform/gcsfuse/v3/internal/storage/gcs"
)

func generateKeys(count int) []string {
keys := make([]string, count)
for i := 0; i < count; i++ {
keys[i] = fmt.Sprintf("object-%d", i)
}
return keys
}

func setupStatCache(capacity uint64) metadata.StatCache {
// 1000 items * approx 120 bytes each = ~120,000 bytes capacity
lruCache := lru.NewCache(capacity)
return metadata.NewStatCacheBucketView(lruCache, "")
}

func BenchmarkStatCache_Insert(b *testing.B) {
keys := generateKeys(10000)
cache := setupStatCache(uint64(len(keys) * 500))
now := time.Now()

i := 0
for b.Loop() {
key := keys[i%len(keys)]
m := &gcs.MinObject{Name: key}
cache.Insert(m, now)
i++
}
}

func BenchmarkStatCache_AddNegativeEntry(b *testing.B) {
keys := generateKeys(10000)
cache := setupStatCache(uint64(len(keys) * 500))
now := time.Now()

i := 0
for b.Loop() {
key := keys[i%len(keys)]
cache.AddNegativeEntry(key, now)
i++
}
}

func BenchmarkStatCache_LookUp(b *testing.B) {
keys := generateKeys(10000)
cache := setupStatCache(uint64(len(keys) * 500))
now := time.Now()

// Pre-fill the cache with unexpired entries.
for _, key := range keys {
m := &gcs.MinObject{Name: key}
cache.Insert(m, now.Add(time.Hour))
}

i := 0
for b.Loop() {
key := keys[i%len(keys)]
_, _ = cache.LookUp(key, now)
i++
}
}
Loading