Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Benchmarks & Resource Usage

on:
push:
branches:
- main
- master
- "feat/**"
pull_request:
branches:
- main
- master
workflow_dispatch:

permissions:
contents: read

concurrency:
group: benchmarks-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
benchmark:
name: Throughput, Memory & Arena Footprint
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout PR / head commit
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: true

- name: Install benchstat
run: go install golang.org/x/perf/cmd/benchstat@latest

- name: Run Performance & Memory Allocation Benchmarks (Head)
run: |
go test -run=^$ -bench=. -benchmem -benchtime=10ms -count=6 ./... | tee benchmark-head.txt

- name: Run Base Branch Benchmarks for Regression Comparison (PR only)
if: github.event_name == 'pull_request'
continue-on-error: true
run: |
HEAD_SHA=$(git rev-parse HEAD)
trap 'git checkout "$HEAD_SHA"' EXIT
git checkout "${{ github.event.pull_request.base.sha }}"
go test -run=^$ -bench=. -benchmem -benchtime=10ms -count=6 ./... | tee benchmark-base.txt
git checkout "$HEAD_SHA"
trap - EXIT
sed -i 's|^pkg: .*|pkg: github.com/google/go-lru|' benchmark-base.txt
benchstat benchmark-base.txt benchmark-head.txt | tee benchstat-comparison.txt

- name: Publish Benchmark & Resource Footprint Summary
run: |
{
echo "## 📊 Performance & Resource Usage Summary"
echo ""
echo "| Benchmark | Iterations | Throughput (\`ns/op\`) | Memory (\`B/op\`) | Allocations (\`allocs/op\`) | Additional Resource Metrics |"
echo "|---|---:|---:|---:|---:|---|"
awk '/^Benchmark_/ && !seen[$1]++ {
bench=$1; iters=$2; ns=$3 " " $4;
b_op="-"; allocs="-"; extra="";
for (i=5; i<=NF; i++) {
if ($(i+1) == "B/op") { b_op = $i " B/op"; i++; }
else if ($(i+1) == "allocs/op") { allocs = $i " allocs/op"; i++; }
else if (i < NF) { extra = extra $i " " $(i+1) " "; i++; }
}
printf "| \`%s\` | %s | %s | %s | %s | %s |\n", bench, iters, ns, b_op, allocs, extra
}' benchmark-head.txt
echo ""
if [ -f benchstat-comparison.txt ]; then
echo "### 🔍 PR vs. Base Regression Comparison (\`benchstat\`)"
echo ""
echo '```text'
cat benchstat-comparison.txt
echo '```'
fi
} >> "$GITHUB_STEP_SUMMARY"

- name: Upload Benchmark Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: benchmark-results
path: |
benchmark-head.txt
benchmark-base.txt
benchstat-comparison.txt
if-no-files-found: ignore
retention-days: 30
118 changes: 118 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: CI

on:
push:
branches:
- main
- master
- "feat/**"
tags:
- "v*"
pull_request:
branches:
- main
- master
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
name: Format & Vet
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: true

- name: Check formatting (gofmt -s)
run: |
UNFORMATTED=$(gofmt -s -l .)
if [ -n "$UNFORMATTED" ]; then
echo "The following files are not properly formatted with 'gofmt -s':"
echo "$UNFORMATTED"
exit 1
fi

- name: Check imports (goimports)
run: |
go install golang.org/x/tools/cmd/goimports@latest
UNFORMATTED_IMPORTS=$("$(go env GOPATH)/bin/goimports" -l .)
if [ -n "$UNFORMATTED_IMPORTS" ]; then
echo "The following files have unformatted imports ('goimports -l .'):"
echo "$UNFORMATTED_IMPORTS"
exit 1
fi

- name: Run go vet
run: go vet ./...

- name: Run golangci-lint
uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7
with:
version: v2.13.1

- name: Verify go.mod and go.sum are tidy
run: |
go mod tidy
git diff --exit-code go.mod go.sum

test:
name: Correctness, Concurrency & Coverage
runs-on: ubuntu-latest
timeout-minutes: 15
needs: lint
steps:
- name: Checkout repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: true

- name: Run Unit, Differential, and Concurrency Tests with Race Detector & Coverage
run: go test -v -race -covermode=atomic -coverprofile=coverage.out ./...

- name: Run Documentation Examples
run: go test -v -run=^Example ./...

- name: Generate Code Coverage Report & Summary
run: |
go tool cover -func=coverage.out | tee coverage.txt
TOTAL_COV=$(tail -n 1 coverage.txt | awk '{print $3}')
{
echo "## ✅ Correctness, Concurrency & Coverage Summary"
echo ""
echo "- **Race Detector (\`-race\`)**: Passed"
echo "- **Unit, Differential & Concurrency Suites**: Passed"
echo "- **Total Statement Coverage**: **${TOTAL_COV}**"
echo ""
echo "<details><summary>Per-Function Coverage Breakdown</summary>"
echo ""
echo '```text'
cat coverage.txt
echo '```'
echo "</details>"
} >> "$GITHUB_STEP_SUMMARY"

- name: Upload Coverage Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: coverage-report
path: |
coverage.out
coverage.txt
retention-days: 14
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
# Compiled test binaries and build outputs
*.test
*.out
*.exe
*.dll
*.so
*.dylib

# Coverage and profiling artifacts
coverage.txt
coverage.html
*.prof
*.pprof
benchmark-*.txt
benchstat-*.txt
bench*.txt

# Agent workspaces and review/sentinel artifacts
.agents/
BRIEFING.md
BRIEFING_ARCHIVE.md
ORIGINAL_REQUEST.md
REVIEW_REPORT.md
handoff.md

# Editor and OS scratch files
.DS_Store
.idea/
.vscode/
*.swp
*.swo
*~
19 changes: 19 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: "2"

linters:
default: standard
enable:
- errcheck
- gocritic
- govet
- ineffassign
- revive
- staticcheck
- testifylint
- thelper
- unused

formatters:
enable:
- gofmt
- goimports
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Changelog

All notable changes to `github.com/google/go-lru` (`package lru`) are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [0.0.1] - 2026-04-20

### Added
- **Standalone Module & Package Identity**: Published under `module github.com/google/go-lru` with idiomatic `package lru` import surface.
- **Unified Constructor & Configurable Backends**:
- `lru.New(maxSize uint64, opts ...Option) Cache` entry point supporting `lru.WithBackend(backend)` across `BackendMap` (default), `BackendRadix`, and `BackendArenaRadix`.
- Direct engine constructors `lru.NewMapCache`, `lru.NewRadixCache`, and `lru.NewArenaRadixCache`, adapted from Google Cloud Storage FUSE (`gcsfuse`) with differential state-machine tests, multi-goroutine race stress tests, and `WithInvariantChecking` runtime structural verification.
- **Ergonomic `ValueType` Wrappers (`values.go`)**:
- `StringValue` (`NewStringValue`), `BytesValue` (`NewBytesValue`), and generic `SizedValue[T]` (`NewSizedValue[T]`, `NewValue[T]`) so callers can cache `string`, `[]byte`, and arbitrary types without boilerplate struct definitions.
- **Two-Tier Memory-Pressure Reclamation (`PressureAwareCache`)**:
- All three backends (`MapCache`, `RadixCache`, and `ArenaRadixCache`) implement `PressureAwareCache` (`Compact()` and `EvaluateMemoryPressure()`).
- Configurable via `WithPressureFunc`, `WithMemoryBudget`, `WithCompactionThreshold` (Tier 1 lossless compaction), `WithEvictionThreshold` (Tier 2 proactive LRU tail shedding + compaction), `WithEvictionRetentionRatio`, and `DefaultRuntimePressureFunc`.
- **Documentation & Runnable Examples**:
- `example_test.go` with `pkg.go.dev` runnable examples (`ExampleNew`, `ExampleNew_eviction`, `ExampleNew_backendsAndPrefixErase`, `ExampleNew_memoryPressure`).
- Concise user guide in `README.md` backed by `docs/architecture.md` and `docs/performance.md`.
- **Automated GitHub Actions CI**:
- `.github/workflows/ci.yml`: formatting (`gofmt -s`, `goimports`), static analysis (`go vet`, `golangci-lint`), `go mod tidy` verification, `-race` unit/differential/concurrency tests, runnable examples, and statement coverage reporting.
- `.github/workflows/benchmarks.yml`: automated performance and resource footprint benchmarking (`ns/op`, `B/op`, `allocs/op`, `heap-B/entry`, `reclaimed-B/op`) with `benchstat` PR regression comparison.

---

## Release & Versioning Workflow

To cut a new semantic version release (e.g. `v0.0.1`):

```bash
# 1. Verify formatting, static analysis, race-enabled test suite, and examples
test -z "$(gofmt -s -l .)"
test -z "$(goimports -l .)"
go vet ./...
golangci-lint run
go test -race ./...
go test -v -run=^Example ./...

# 2. Verify benchmark & resource usage suite
go test -run=^$ -bench=. -benchmem -benchtime=10ms ./...

# 3. Create and push annotated semantic version tag
git tag -a v0.0.1 -m "Release v0.0.1"
git push origin --tags
```
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ information on using pull requests.
## Community Guidelines

This project follows [Google's Open Source Community
Guidelines](https://opensource.google/conduct/).
Guidelines](https://opensource.google/conduct/).
Loading
Loading