diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6d478eb..285bf43 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -71,6 +71,11 @@ jobs: go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 INCLUDE_LONG_RUNNING=true PROFILES=,-jakarta,javax COHERENCE_VERSION=22.06.9 make clean generate-proto build-test-images test-e2e-standalone + - name: Profile Near Cache + shell: bash + run: | + make profile-near-cache + - uses: actions/upload-artifact@v4 if: failure() with: diff --git a/.gitignore b/.gitignore index b901b03..42b03a9 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ shared/ certs/ release/ etc/ +coherence/coherence.test diff --git a/Makefile b/Makefile index ba1403b..04ad169 100644 --- a/Makefile +++ b/Makefile @@ -161,6 +161,7 @@ copyright: getcopyright ## Check copyright headers -X bin/ \ -X ./test/test/utils.go \ -X dependency-reduced-pom.xml \ + -X ./coherence/coherence.test \ -X binaries/ \ -X build/ \ -X proto/ \ @@ -332,6 +333,15 @@ test-cluster-startup: $(BUILD_PROPS) ## Startup any test cluster members using d test-cluster-shutdown: ## Shutdown any test cluster members using docker-compose cd test/utils && $(DOCKER_COMPOSE) -f docker-compose-2-members.yaml down || true +# ---------------------------------------------------------------------------------------------------------------------- +# Run Near Cache Profile Tests +# ---------------------------------------------------------------------------------------------------------------------- +.PHONY: profile-near-cache +profile-near-cache: ## Run Near Cache Profile Tests + cd coherence && go test -run=^TestNearCacheExpiry1 -cpuprofile=$(TEST_LOGS_DIR)/cpu.out -memprofile=$(TEST_LOGS_DIR)/mem.out + echo top | go tool pprof $(TEST_LOGS_DIR)/cpu.out + echo top | go tool pprof $(TEST_LOGS_DIR)/mem.out + # ---------------------------------------------------------------------------------------------------------------------- # Startup standalone coherence via java -jar diff --git a/coherence/localcache.go b/coherence/localcache.go index d48bfbf..14afd95 100644 --- a/coherence/localcache.go +++ b/coherence/localcache.go @@ -160,13 +160,14 @@ func (l *localCacheImpl[K, V]) GetAll(keys []K) map[K]*V { l.expireEntries() results := make(map[K]*V, 0) + now := time.Now() for _, key := range keys { v, ok := l.data[key] if ok { // have entry so add to the results results[key] = &v.value - v.lastAccess = time.Now() + v.lastAccess = now } } @@ -239,7 +240,7 @@ func (l *localCacheImpl[K, V]) expireEntries() { // check for cache expiry for k, v := range l.data { - if v.ttl > 0 && time.Since(v.insertTime) > v.ttl { + if v.ttl > 0 && start.Sub(v.insertTime) > v.ttl { keysToDelete = append(keysToDelete, k) } } diff --git a/coherence/localcache_test.go b/coherence/localcache_test.go index 239bc60..e6eb4d8 100644 --- a/coherence/localcache_test.go +++ b/coherence/localcache_test.go @@ -300,6 +300,37 @@ func TestBasicLocalCacheSizeCalculation(t *testing.T) { g.Expect(cache.cacheMemory).Should(gomega.Equal(int64(0))) } +type expiryResults struct { + ttl time.Duration + expiryTime time.Duration + cacheExpires int64 +} + +func TestNearCacheExpiry1(_ *testing.T) { + var ( + results = make([]expiryResults, 0) + ttl int64 + ) + + for ttl = 10; ttl < 1_000; ttl += 25 { + results = append(results, localCacheExpiryTest(time.Duration(ttl)*time.Millisecond, 10_000)) + } + + // output results + for _, r := range results { + fmt.Printf("ttl=%5v, cache expires=%5v, time spent expiring=%10v\n", r.ttl, r.cacheExpires, r.expiryTime) + } +} + +func localCacheExpiryTest(ttl time.Duration, count int) expiryResults { + cache := newLocalCache[int, string]("my-cache-high-unit3", withLocalCacheExpiry(ttl)) + for i := 1; i <= count; i++ { + cache.Put(i, fmt.Sprintf("value-%v", i)) + } + + return expiryResults{ttl: ttl, expiryTime: cache.GetCacheExpiresDuration(), cacheExpires: cache.GetCacheExpires()} +} + func Sleep(seconds int) { time.Sleep(time.Duration(seconds) * time.Second) }