Skip to content

Commit

Permalink
add gc scan tests
Browse files Browse the repository at this point in the history
  • Loading branch information
phuslu committed Mar 26, 2024
1 parent 1467d24 commit 2094bcf
Show file tree
Hide file tree
Showing 2 changed files with 243 additions and 0 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/gcscan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: gcscan

on:
schedule:
- cron: '0 0 * * *'
push:
branches:
- master

jobs:
gcscan:
runs-on: ubuntu-latest
steps:
- name: Install packages
run: sudo apt update -y && sudo apt-get install -y csvkit datamash
- uses: actions/setup-go@v4
with:
go-version: '1.22'
check-latest: true
- uses: actions/checkout@v4
- name: go mod tidy
run: |
mkdir bench
cd bench
awk '{if($0 ~ "// env GODEBUG=gctrace=1"){a=1;b=1};if($0 ~ "```" && b=1){b=0};if (a&&b) {print}}' ../README.md > gcscan.go
go mod init bench
go mod tidy
go mod edit -replace github.com/phuslu/lru=../
cat go.mod
- name: GC Tests
working-directory: ./bench
run: |
echo -e 'GCScan\tCacheSize\tScanTime' > memusage.txt
for name in nottl phuslu lxzan ristretto freelru ecache otter theine cloudflare ccache hashicorp; do
for cachesize in 100000 200000 400000 1000000 2000000 4000000; do
env GODEBUG=gctrace=1 go run gcscan.go $name $cachesize 2>&1 | tee gcscan-$name-$cachesize.txt
echo -e "$name\t$cachesize\t$(tail -20 gcscan-$name-$cachesize.txt | awk -F+ '{a+=$2}END{print int(a/20)}') ms" | tee -a gcscan.txt
done
done
cat gcscan.txt
- name: GC Results
working-directory: ./bench
run: |
cat gcscan.txt | datamash --header-in crosstab 1,2 unique 3 | tee >(head -1) | tail -n +2 | sort -k12 -n | datamash transpose | tee >(head -1) | tail -n +2 | sort -n | datamash transpose | csvlook
199 changes: 199 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,204 @@ PASS
ok command-line-arguments 96.989s
```

### GC scan

The GC scan result as below. Check github [gcscan][gcscan] action for more results and details.
<details>
<summary>GC scan on keysize=16(string), valuesize=8(int), cachesize in (100000,200000,400000,1000000,2000000,4000000)</summary>

```go
// env GODEBUG=gctrace=1 go run gcscan.go phuslu 1000000
package main

import (
"fmt"
"os"
"runtime"
"runtime/debug"
"strconv"
"time"

theine "github.com/Yiling-J/theine-go"
"github.com/cespare/xxhash/v2"
cloudflare "github.com/cloudflare/golibs/lrucache"
ristretto "github.com/dgraph-io/ristretto"
freelru "github.com/elastic/go-freelru"
hashicorp "github.com/hashicorp/golang-lru/v2/expirable"
ccache "github.com/karlseguin/ccache/v3"
lxzan "github.com/lxzan/memorycache"
otter "github.com/maypok86/otter"
ecache "github.com/orca-zhang/ecache"
phuslu "github.com/phuslu/lru"
)

const keysize = 16
const repeat = 20

var keys []string

func main() {
name := os.Args[1]
cachesize, _ := strconv.Atoi(os.Args[2])

keys = make([]string, cachesize)
for i := range cachesize {
keys[i] = fmt.Sprintf(fmt.Sprintf("%%0%dd", keysize), i)
}

map[string]func(int){
"nottl": SetupNottl,
"phuslu": SetupPhuslu,
"freelru": SetupFreelru,
"ristretto": SetupRistretto,
"otter": SetupOtter,
"lxzan": SetupLxzan,
"ecache": SetupEcache,
"cloudflare": SetupCloudflare,
"ccache": SetupCcache,
"hashicorp": SetupHashicorp,
"theine": SetupTheine,
}[name](cachesize)
}

func SetupNottl(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := phuslu.NewLRUCache[string, int](cachesize)
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Set(keys[i], i)
}
runtime.GC()
}
}

func SetupPhuslu(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := phuslu.NewTTLCache[string, int](cachesize)
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Set(keys[i], i, time.Hour)
}
runtime.GC()
}
}

func SetupFreelru(cachesize int) {
cache, _ := freelru.NewSharded[string, int](uint32(cachesize), func(s string) uint32 { return uint32(xxhash.Sum64String(s)) })
runtime.GC()
for range repeat {
for i := range cachesize {
cache.AddWithLifetime(keys[i], i, time.Hour)
}
runtime.GC()
}
}

func SetupOtter(cachesize int) {
cache, _ := otter.MustBuilder[string, int](cachesize).WithVariableTTL().Build()
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Set(keys[i], i, time.Hour)
}
runtime.GC()
}
}

func SetupEcache(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := ecache.NewLRUCache(1024, uint16(cachesize/1024), time.Hour)
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Put(keys[i], i)
}
runtime.GC()
}
}

func SetupRistretto(cachesize int) {
cache, _ := ristretto.NewCache(&ristretto.Config{
NumCounters: int64(10 * cachesize), // number of keys to track frequency of (10M).
MaxCost: int64(cachesize), // maximum cost of cache (1M).
BufferItems: 64, // number of keys per Get buffer.
})
runtime.GC()
for range repeat {
for i := range cachesize {
cache.SetWithTTL(keys[i], i, 1, time.Hour)
}
runtime.GC()
}
}

func SetupLxzan(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := lxzan.New[string, int](
lxzan.WithBucketNum(128),
lxzan.WithBucketSize(cachesize/128, cachesize/128),
lxzan.WithInterval(time.Hour, time.Hour),
)
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Set(keys[i], i, time.Hour)
}
runtime.GC()
}
}

func SetupTheine(cachesize int) {
cache, _ := theine.NewBuilder[string, int](int64(cachesize)).Build()
runtime.GC()
for range repeat {
for i := range cachesize {
cache.SetWithTTL(keys[i], i, 1, time.Hour)
}
runtime.GC()
}
}

func SetupCloudflare(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := cloudflare.NewMultiLRUCache(1024, uint(cachesize/1024))
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Set(keys[i], i, time.Now().Add(time.Hour))
}
runtime.GC()
}
}

func SetupCcache(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := ccache.New(ccache.Configure[int]().MaxSize(int64(cachesize)).ItemsToPrune(100))
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Set(keys[i], i, time.Hour)
}
runtime.GC()
}
}

func SetupHashicorp(cachesize int) {
defer debug.SetGCPercent(debug.SetGCPercent(-1))
cache := hashicorp.NewLRU[string, int](cachesize, nil, time.Hour)
runtime.GC()
for range repeat {
for i := range cachesize {
cache.Add(keys[i], i)
}
runtime.GC()
}
}
```
</details>

### Memory usage

The Memory usage result as below. Check github [memory][memory] action for more results and details.
Expand Down Expand Up @@ -684,5 +882,6 @@ For inquiries or support, contact [email protected] or raise github issues.
[goreport]: https://goreportcard.com/report/github.com/phuslu/lru
[benchmark]: https://github.com/phuslu/lru/actions/workflows/benchmark.yml
[memory]: https://github.com/phuslu/lru/actions/workflows/memory.yml
[gcscan]: https://github.com/phuslu/lru/actions/workflows/gcscan.yml
[codecov-img]: https://codecov.io/gh/phuslu/lru/graph/badge.svg?token=Q21AMQNM1K
[codecov]: https://codecov.io/gh/phuslu/lru

0 comments on commit 2094bcf

Please sign in to comment.