### Getting Started Example Source: https://github.com/samber/hot/blob/main/README.md Demonstrates how to create and use a simple LRU cache with a 10-minute TTL. ```APIDOC ## Getting Started Let's start with a simple LRU cache and 10 minutes TTL: ```go import "github.com/samber/hot" cache := hot.NewHotCache[string, int](hot.LRU, 1_000_000). WithTTL(10*time.Minute). Build() cache.Set("hello", 42) values, missing := cache.GetMany([]string{"bar", "baz", "hello"}) // values: {"hello": 42} // missing: ["baz", "bar"] ``` ``` -------------------------------- ### Run Web Server Cache Example Source: https://github.com/samber/hot/blob/main/examples/README.md Navigate to the web server example directory and run the Go program to start the HTTP server. ```bash cd ../web go run web-server.go ``` -------------------------------- ### Install PostgreSQL Driver and Run Example Source: https://github.com/samber/hot/blob/main/examples/database/README.md Commands to download the PostgreSQL driver, set the database connection URL, and run the Go application. ```bash # Install PostgreSQL driver go mod download # Set up database connection export DATABASE_URL="postgres://user:password@localhost/dbname?sslmode=disable" # Run the example go run postgresql-cache.go ``` -------------------------------- ### Install HOT Source: https://github.com/samber/hot/blob/main/docs/quickstart.md Install the HOT library using the go get command. ```bash go get github.com/samber/hot ``` -------------------------------- ### Run HTTP Server Example Source: https://github.com/samber/hot/blob/main/examples/web/README.md Execute the main Go file to start the HTTP server. This command initiates the web application with caching layers and API endpoints. ```bash go run http-server.go ``` -------------------------------- ### Install HOT Cache Library Source: https://github.com/samber/hot/blob/main/README.md Install the HOT cache library using go get. Includes an AI Agent Skill for Golang. ```bash go get github.com/samber/hot # AI Agent Skill: npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-hot ``` -------------------------------- ### Run Prometheus Observability Example Source: https://github.com/samber/hot/blob/main/examples/observability/README.md Execute the main Go program to start the cache and the metrics server. Access the Prometheus metrics endpoint in your browser. ```bash go run prometheus.go ``` -------------------------------- ### Run Concurrency Example Source: https://github.com/samber/hot/blob/main/examples/basic/concurrency/README.md Execute the main concurrency example using the go run command. ```bash go run thread-safety.go ``` -------------------------------- ### Run Simple LRU Cache Example Source: https://github.com/samber/hot/blob/main/examples/basic/simple-lru/README.md Execute the main Go program to run the simple LRU cache example. This command starts the demonstration of cache operations. ```bash go run simple.go ``` -------------------------------- ### Run Simple LRU Cache Example Source: https://github.com/samber/hot/blob/main/examples/README.md Navigate to the simple LRU cache example directory and run the Go program. ```bash cd basic/simple-lru go run simple.go ``` -------------------------------- ### Install Benchmark Dependencies Source: https://github.com/samber/hot/blob/main/bench/README.md Installs necessary Go packages for running benchmarks, including benchstat and prettybench. ```bash # Install benchmark dependencies go get golang.org/x/perf/cmd/benchstat go get github.com/cespare/prettybench ``` -------------------------------- ### Run Batch Operations Example Source: https://github.com/samber/hot/blob/main/examples/basic/batch/README.md Execute the Go program to run the batch operations example and observe performance comparisons. ```bash go run batch-operations.go ``` -------------------------------- ### Run TTL Cache Example Source: https://github.com/samber/hot/blob/main/examples/basic/ttl/README.md Execute the TTL cache example using the Go run command. ```bash go run ttl.go ``` -------------------------------- ### HTTP Server Output Example Source: https://github.com/samber/hot/blob/main/examples/web/README.md This output shows the successful startup of the HTTP server, indicating the creation of caches and listing available API endpoints. ```text 🌐 HTTP Server with Cache Example ================================= ✅ User cache created with 1000 items capacity ✅ Product cache created with 2000 items capacity 🚀 HTTP server started on :8080 Available endpoints: - GET /health - Server health - GET /users - List users - GET /users/{id} - Get user by ID - POST /users - Create user - PUT /users/{id} - Update user - DELETE /users/{id} - Delete user - GET /products - List products - GET /products/{id} - Get product by ID - POST /products - Create product - PUT /products/{id} - Update product - DELETE /products/{id} - Delete product - GET /cache/stats - Cache statistics - POST /cache/clear - Clear all caches - POST /cache/warmup - Warm up caches - GET /metrics - Prometheus metrics ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/samber/hot/blob/main/README.md Installs necessary development tools for the project. Use this before running tests or contributing. ```bash make tools ``` -------------------------------- ### Implementing Cache Persistence Source: https://github.com/samber/hot/blob/main/docs/faq.md Provides examples for saving cache data to a file on shutdown and loading it back on startup. ```go // Save cache on shutdown func saveCache(cache *hot.HotCache[string, *User]) { items := make(map[string]*User) cache.Range(func(key string, value *User) bool { items[key] = value return true }) saveToFile(items) } // Load cache on startup func loadCache(cache *hot.HotCache[string, *User]) { items := loadFromFile() cache.SetMany(items) } ``` -------------------------------- ### Clone HOT Cache Repository Source: https://github.com/samber/hot/blob/main/examples/README.md Clone the HOT cache repository to access the examples. ```bash git clone https://github.com/samber/hot.git cd hot/examples ``` -------------------------------- ### Simple LRU Cache Initialization and Usage Source: https://github.com/samber/hot/blob/main/README.md Demonstrates creating a basic LRU cache with a capacity of 100,000 items and performing set and get operations, including batch retrieval. ```go import "github.com/samber/hot" // Available eviction policies: hot.LRU, hot.LFU, hot.TinyLFU, hot.WTinyLFU, hot.S3FIFO, hot.TwoQueue, hot.ARC, hot.SIEVE, hot.FIFO // Capacity: 100k keys/values cache := hot.NewHotCache[string, int](hot.LRU, 100_000). Build() cache.Set("hello", 42) cache.SetMany(map[string]int{"foo": 1, "bar": 2}) values, missing := cache.GetMany([]string{"bar", "baz", "hello"}) // values: {"bar": 2, "hello": 42} // missing: ["baz"] value, found, _ := cache.Get("foo") // value: 1 // found: true ``` -------------------------------- ### PostgreSQL Database Schema for Users and Products Source: https://github.com/samber/hot/blob/main/examples/database/README.md SQL statements to create the 'users' and 'products' tables in a PostgreSQL database. These tables are used by the example application. ```sql CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, age INTEGER, created_at TIMESTAMP, updated_at TIMESTAMP ); CREATE TABLE products ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, price DECIMAL(10,2), category VARCHAR(100), stock INTEGER, created_at TIMESTAMP, updated_at TIMESTAMP ); ``` -------------------------------- ### Prometheus Queries for HOT Cache Metrics Source: https://github.com/samber/hot/blob/main/README.md Example Prometheus queries to analyze cache performance. These queries demonstrate how to calculate hit ratio, eviction rates, cache size, utilization, and insertion rates. ```promql # Cache hit ratio rate(hot_hit_total[5m]) / (rate(hot_hit_total[5m]) + rate(hot_miss_total[5m])) ``` ```promql # Eviction rate by reason rate(hot_eviction_total[5m]) ``` ```promql # Cache size in MB hot_size_bytes / 1024 / 1024 ``` ```promql # Cache utilization percentage hot_length / hot_settings_capacity * 100 ``` ```promql # Insertion rate rate(hot_insertion_total[5m]) ``` -------------------------------- ### Get User API Request Source: https://github.com/samber/hot/blob/main/examples/web/README.md Example using curl to retrieve a specific user by their ID from the HTTP server. ```bash curl http://localhost:8080/users/1 ``` -------------------------------- ### Size Cache Appropriately Based on Dataset Size Source: https://github.com/samber/hot/blob/main/docs/best-practices.md A common rule of thumb is to size the cache to hold 10-20% of your dataset. This example shows how to initialize a cache for 1 million user records, aiming to hold 150,000. ```go cache := hot.NewHotCache[string, *User](hot.LRU, 150_000). WithTTL(15*time.Minute). Build() ``` -------------------------------- ### Create User API Request Source: https://github.com/samber/hot/blob/main/examples/web/README.md Example using curl to create a new user by sending a JSON payload to the HTTP server. Ensure the Content-Type header is set to application/json. ```bash curl -X POST http://localhost:8080/users \ -H "Content-Type: application/json" \ -d '{"name":"Alice","email":"alice@example.com","age":30}' ``` -------------------------------- ### Retrieve Value by Key Source: https://github.com/samber/hot/blob/main/README.md Use `Get` to retrieve a value by its key, which returns the value, a boolean indicating if it was found, and any error. Use `Peek` to retrieve without updating access time or LRU position. ```go cache.Get(key K) -> (value V, found bool, error error) cache.Peek(key K) -> (value V, found bool) ``` -------------------------------- ### Get Cache Algorithm Information Source: https://github.com/samber/hot/blob/main/README.md Retrieve information about the cache's underlying algorithm and version using the `Algorithm` method. ```go cache.Algorithm() -> (name string, version string) ``` -------------------------------- ### Get Cache Statistics API Request Source: https://github.com/samber/hot/blob/main/examples/web/README.md Example using curl to fetch statistics about the cache from the HTTP server. This is useful for monitoring cache performance. ```bash curl http://localhost:8080/cache/stats ``` -------------------------------- ### Create and Use an LRU Cache with TTL Source: https://github.com/samber/hot/blob/main/README.md Demonstrates creating a string-to-int LRU cache with a 10-minute TTL and setting/getting values. Shows how to retrieve multiple values and identify missing keys. ```go import "github.com/samber/hot" cache := hot.NewHotCache[string, int](hot.LRU, 1_000_000). WithTTL(10*time.Minute). Build() cache.Set("hello", 42) values, missing := cache.GetMany([]string{"bar", "baz", "hello"}) // values: {"hello": 42} // missing: ["baz", "bar"] ``` -------------------------------- ### Migrate from Go map to HOT Cache Source: https://github.com/samber/hot/blob/main/docs/faq.md Demonstrates the transition from using a standard Go map to a HOT cache instance. Shows how to initialize the cache with LRU eviction and TTL, and how to replace map operations with cache methods. ```go // Before var cache = make(map[string]*User) // After cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithTTL(5*time.Minute). Build() // Replace operations cache["key"] = value // -> cache.Set("key", value) value := cache["key"] // -> value, found, _ := cache.Get("key") delete(cache, "key") // -> cache.Delete("key") ``` -------------------------------- ### Create and Use a Simple LRU Cache Source: https://github.com/samber/hot/blob/main/docs/quickstart.md Demonstrates creating an LRU cache with a specified capacity and TTL, then storing and retrieving a value. ```go package main import ( "fmt" "time" "github.com/samber/hot" ) func main() { // Create a simple LRU cache with 1000 items capacity cache := hot.NewHotCache[string, int](hot.LRU, 1000). WithTTL(5*time.Minute). Build() // Store a value cache.Set("user:123", 42) // Retrieve a value value, found, err := cache.Get("user:123") if err != nil { fmt.Printf("Error: %v\n", err) return } if found { fmt.Printf("Found: %d\n", value) } else { fmt.Println("Not found") } } ``` -------------------------------- ### Preload Cache on Startup Source: https://github.com/samber/hot/blob/main/README.md Populates the cache with initial data from a specified loader function when the cache is first created. ```go // Preload cache on startup with data from loader WithWarmUp(loader func() (map[K]V, []K, error)) ``` -------------------------------- ### Create Cache with Database Loader Source: https://github.com/samber/hot/blob/main/docs/quickstart.md Shows how to create a cache that automatically loads data from a database when a key is not found. Configure TTL and a custom loader function. ```go package main import ( "database/sql" "fmt" "time" "github.com/samber/hot" ) type User struct { ID string Name string Email string } func main() { db, _ := sql.Open("postgres", "connection_string") // Create cache with database loader cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithTTL(10*time.Minute). WithLoaders(func(keys []string) (found map[string]*User, err error) { // Query database for missing keys found = make(map[string]*User) for _, key := range keys { user := &User{} err := db.QueryRow("SELECT id, name, email FROM users WHERE id = $1", key). Scan(&user.ID, &user.Name, &user.Email) if err == nil { found[key] = user } } return found, nil }). Build() // Get user - will automatically load from database if not in cache user, found, err := cache.Get("user:123") if err != nil { fmt.Printf("Error: %v\n", err) return } if found { fmt.Printf("User: %s (%s)\n", user.Name, user.Email) } } ``` -------------------------------- ### Create and Use an LRU Cache Source: https://github.com/samber/hot/blob/main/docs/README.md Demonstrates how to create a new LRU cache with a specified capacity and TTL, and then how to set and retrieve values from it. Ensure you import the 'time' package for TTL duration. ```go import "github.com/samber/hot" import "time" // Create a simple LRU cache cache := hot.NewHotCache[string, int](hot.LRU, 1000). WithTTL(5*time.Minute). Build() // Use the cache cache.Set("key", 42) value, found, _ := cache.Get("key") ``` -------------------------------- ### Create High-Performance Sharded Cache Source: https://github.com/samber/hot/blob/main/docs/quickstart.md Demonstrates setting up a sharded cache for high concurrency, including sharding strategy, Prometheus metrics, and batch operations for better performance. ```go package main import ( "hash/fnv" "time" "github.com/samber/hot" ) func main() { // Create sharded cache for high concurrency cache := hot.NewHotCache[string, []byte](hot.LRU, 10000). WithTTL(1*time.Hour). WithSharding(16, func(key string) uint64 { h := fnv.New64a() h.Write([]byte(key)) return h.Sum64() }). WithPrometheusMetrics("api-cache"). Build() // Use batch operations for better performance cache.SetMany(map[string][]byte{ "key1": []byte("value1"), "key2": []byte("value2"), "key3": []byte("value3"), }) values, missing := cache.GetMany([]string{"key1", "key2", "key4"}) fmt.Printf("Found: %d items, Missing: %d items\n", len(values), len(missing)) } ``` -------------------------------- ### Manage Cache Lifecycle Source: https://github.com/samber/hot/blob/main/README.md Use `Purge` to clear all items, `WarmUp` to preload data, and `Janitor`/`StopJanitor` to manage the background cleanup process. ```go cache.Purge() cache.WarmUp(loader hot.Loader[K, V]) -> error cache.Janitor() cache.StopJanitor() ``` -------------------------------- ### Run All Benchmarks Source: https://github.com/samber/hot/blob/main/bench/README.md Executes all defined benchmarks for the HOT cache using the make command. ```bash # Run all benchmarks make bench ``` -------------------------------- ### Available Eviction Algorithms Source: https://github.com/samber/hot/blob/main/README.md Lists the various eviction algorithms supported by the HOT cache library. ```go hot.LRU hot.LFU hot.TinyLFU hot.WTinyLFU hot.S3FIFO hot.TwoQueue hot.ARC hot.SIEVE hot.FIFO ``` -------------------------------- ### Generate and Analyze CPU Profile Source: https://github.com/samber/hot/blob/main/bench/README.md Commands to generate a CPU profile for benchmarks and analyze it using pprof. This helps identify performance bottlenecks. ```bash # Generate CPU profile go test -bench=BenchmarkLRU -cpuprofile=cpu.prof ./pkg/lru/ # Analyze with pprof go tool pprof cpu.prof ``` -------------------------------- ### Pretty Print Benchmark Results Source: https://github.com/samber/hot/blob/main/bench/README.md Formats benchmark results for better readability using the prettybench tool. ```bash # Pretty print benchmark results prettybench -benchmem ./... ``` -------------------------------- ### Run Project Tests Source: https://github.com/samber/hot/blob/main/README.md Executes the project's test suite. Use 'make watch-test' for continuous testing during development. ```bash make test ``` ```bash make watch-test ``` -------------------------------- ### Enable and Expose Prometheus Metrics for HOT Cache Source: https://github.com/samber/hot/blob/main/README.md Enable Prometheus metrics by calling `WithPrometheusMetrics()` with a cache name. Register the cache metrics with Prometheus and set up an HTTP server to expose them. Ensure necessary imports are included. ```go import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/samber/hot" "net/http" ) // Create cache with Prometheus metrics cache := hot.NewHotCache[string, string](hot.LRU, 1000). WithTTL(5*time.Minute). WithJitter(0.5, 10*time.Second). WithRevalidation(10*time.Second). WithRevalidationErrorPolicy(hot.KeepOnError). WithPrometheusMetrics("users-by-id"). WithMissingCache(hot.ARC, 1000). Build() // Register the cache metrics with Prometheus err := prometheus.Register(cache) if err != nil { log.Fatalf("Failed to register metrics: %v", err) } deferr prometheus.Unregister(cache) // Set up HTTP server to expose metrics http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil) ``` -------------------------------- ### Enable Missing Key Caching (Shared) Source: https://github.com/samber/hot/blob/main/README.md Use this when missing keys are infrequent. It shares the missing cache with the main cache to avoid pollution. ```go import "github.com/samber/hot" cache := hot.NewHotCache[string, int](hot.LRU, 100_000). WithMissingSharedCache(). Build() ``` -------------------------------- ### Cache with Time-To-Live (TTL) and Expiration Source: https://github.com/samber/hot/blob/main/README.md Configures a cache with a default TTL of 1 minute, optional jitter for TTL randomization, and a janitor for background purging of expired keys. ```go import "github.com/samber/hot" cache := hot.NewHotCache[string, int](hot.LRU, 100_000). WithTTL(1 * time.Minute). // items will expire after 1 minute WithJitter(2, 30*time.Second). // optional: randomizes the TTL with an exponential distribution in the range [0, +30s) WithJanitor(1 * time.Minute). // optional: background job will purge expired keys every minutes Build() cache.SetWithTTL("foo", 42, 10*time.Second) // shorter TTL for "foo" key ``` -------------------------------- ### Implement Efficient Loaders with Batching Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Use batch database queries with an IN clause to efficiently load multiple records by their IDs. This reduces the number of database round trips. ```go // ✅ Good: Batch database queries func userLoader(keys []string) (found map[string]*User, err error) { if len(keys) == 0 { return make(map[string]*User), nil } // Use IN clause for batch queries placeholders := make([]string, len(keys)) args := make([]interface{}, len(keys)) for i, key := range keys { placeholders[i] = fmt.Sprintf("$%d", i+1) args[i] = key } query := fmt.Sprintf("SELECT id, name, email FROM users WHERE id IN (%s)", strings.Join(placeholders, ",")) rows, err := db.Query(query, args...) if err != nil { return nil, err } defer rows.Close() found = make(map[string]*User) for rows.Next() { user := &User{} err := rows.Scan(&user.ID, &user.Name, &user.Email) if err != nil { return nil, err } found[user.ID] = user } return found, nil } ``` -------------------------------- ### Benchmark Template for New Features Source: https://github.com/samber/hot/blob/main/bench/README.md Use this template to add new benchmark functions for features. Ensure benchmarks are added to the relevant package and cover the new functionality. ```go func BenchmarkNewFeature(b *testing.B) { cache := hot.NewHotCache[string, int](hot.LRU, 1000). WithNewFeature(). Build() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { key := fmt.Sprintf("key:%d", i%1000) cache.Set(key, i) cache.Get(key) i++ } }) } ``` -------------------------------- ### Cache Warmup with Preloaded Data Source: https://github.com/samber/hot/blob/main/docs/quickstart.md Preloads frequently accessed data into the cache during initialization using a warmup function. ```go // Preload frequently accessed data cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithWarmUp(func() (map[string]*User, []string, error) { // Load popular users from database users := map[string]*User{ "user:admin": {ID: "admin", Name: "Administrator"}, "user:guest": {ID: "guest", Name: "Guest User"}, } return users, nil, nil }). Build() ``` -------------------------------- ### Optimize Sharding Strategy Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Use a reasonable number of shards to balance performance and overhead. Avoid excessive sharding, which can increase complexity and resource consumption. ```go // ❌ Bad: Too many shards (overhead) cache.WithSharding(1000, hasher) // ✅ Good: Reasonable number of shards cache.WithSharding(16, hasher) // 2^4 shards ``` -------------------------------- ### Compare Benchmark Results Source: https://github.com/samber/hot/blob/main/bench/README.md Compares two sets of benchmark results using benchstat to analyze performance differences. ```bash # Compare benchmark results benchstat old.txt new.txt ``` -------------------------------- ### Manual and Pattern-Based Cache Invalidation Source: https://github.com/samber/hot/blob/main/docs/faq.md Demonstrates how to manually delete single or multiple keys, or use pattern-based deletion with a range function for cache invalidation. ```go // Manual invalidation cache.Delete("key") cache.DeleteMany([]string{"key1", "key2"}) // Pattern-based invalidation cache.Range(func(key string, value *User) bool { if strings.HasPrefix(key, "user:") { cache.Delete(key) } return true }) ``` -------------------------------- ### Using HOT with Custom Data Types Source: https://github.com/samber/hot/blob/main/docs/faq.md Shows how to use HOT with custom struct types for both keys and values, leveraging Go generics. ```go // Custom structs type User struct { ID string; Name string } cache := hot.NewHotCache[string, *User](hot.LRU, 1000) // Custom key types type UserID struct { ID string } cache := hot.NewHotCache[UserID, *User](hot.LRU, 1000) ``` -------------------------------- ### Enable Prometheus Metrics for Production Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Always enable Prometheus metrics in production environments for monitoring. This provides visibility into cache performance and behavior. ```go // ✅ Good: Always enable metrics in production cache := hot.NewHotCache[string, *Data](hot.LRU, 100_000). WithPrometheusMetrics("user-cache"). Build() // Register with Prometheus prometheus.MustRegister(cache) ``` -------------------------------- ### Cache Error Handling Patterns Source: https://github.com/samber/hot/blob/main/README.md Illustrates how to handle potential errors during cache operations, including single key retrieval and batch operations. ```go // Handle cache operations with proper error checking value, found, err := cache.Get("key") if err != nil { // Handle loader errors (database connection, network issues, etc.) log.Printf("Cache get error: %v", err) return } if !found { // Key doesn't exist in cache and wasn't found by loaders log.Printf("Key not found: %s", "key") return } // Use value safely fmt.Printf("Value: %v", value) // Batch operations with error handling values, missing := cache.GetMany([]string{"key1", "key2", "key3"}) if len(missing) > 0 { log.Printf("Missing keys: %v", missing) } // Process found values for key, value := range values { fmt.Printf("%s: %v", key, value) } ``` -------------------------------- ### LRU Cache Initialization Source: https://github.com/samber/hot/blob/main/README.md Initializes a new Least Recently Used (LRU) cache with a specified capacity. This is a fundamental eviction policy. ```go cache := lru.NewLRUCache[string, *User](100_000) ``` -------------------------------- ### Inspect Cache Contents Source: https://github.com/samber/hot/blob/main/README.md Methods like `Keys`, `Values`, `All`, and `Range` allow inspection of cache contents without modifying the cache state. `Len` and `Capacity` provide size information. ```go cache.Keys() -> []K cache.Values() -> []V cache.All() -> map[K]V cache.Range(fn func(key K, value V) bool) cache.Len() -> int cache.Capacity() -> (current int, max int) ``` -------------------------------- ### Configure Caching for Missing Keys in HOT Cache Source: https://github.com/samber/hot/blob/main/docs/faq.md Set up caching for missing keys to avoid repeated lookups for non-existent entries. This can be done with a separate cache or by sharing it with the main cache. ```go // Separate cache for missing keys cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithMissingCache(hot.LFU, 100). Build() ``` ```go // Share with main cache cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithMissingSharedCache(). Build() ``` -------------------------------- ### Set up Sharding for HOT Cache Source: https://github.com/samber/hot/blob/main/docs/faq.md Configure sharding for the HOT cache to improve concurrency by reducing lock contention. Use a power of 2 for the number of shards for optimal performance. ```go cache := hot.NewHotCache[string, *Data](hot.LRU, 10000). WithSharding(16, func(key string) uint64 { h := fnv.New64a() h.Write([]byte(key)) return h.Sum64() }). Build() ``` -------------------------------- ### Choose Cache Eviction Algorithm Source: https://github.com/samber/hot/blob/main/bench/README.md Select the appropriate cache eviction algorithm based on your data access patterns. LRU is for general use, LFU for frequently accessed data, ARC for mixed patterns, and FIFO for simple eviction. ```go // For general use cache := hot.NewHotCache[string, int](hot.LRU, 1000) // For frequently accessed data cache := hot.NewHotCache[string, int](hot.LFU, 1000) // For mixed access patterns cache := hot.NewHotCache[string, int](hot.ARC, 1000) // For simple, predictable eviction cache := hot.NewHotCache[string, int](hot.FIFO, 1000) ``` -------------------------------- ### Generate and Analyze Memory Profile Source: https://github.com/samber/hot/blob/main/bench/README.md Commands to generate a memory profile for benchmarks and analyze it using pprof. Useful for identifying memory usage issues. ```bash # Generate memory profile go test -bench=BenchmarkLRU -memprofile=mem.prof ./pkg/lru/ # Analyze with pprof go tool pprof mem.prof ``` -------------------------------- ### Environment Variables for Performance Tuning Source: https://github.com/samber/hot/blob/main/bench/README.md Set environment variables to control Go runtime behavior for benchmarking. GOMAXPROCS and GOGC can significantly impact performance. ```bash # Disable CPU frequency scaling export GOMAXPROCS=1 export GOGC=off # Run benchmarks make bench ``` -------------------------------- ### Handle Database Failures with Fallback Loaders Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Implement graceful degradation by providing fallback loaders for a cache. If the primary database fails, the cache will attempt to load data from a secondary database. ```go // ✅ Good: Graceful degradation cache := hot.NewHotCache[string, *User](hot.LRU, 100_000). WithLoaders( func(keys []string) (found map[string]*User, err error) { // Try primary database return primaryDB.LoadUsers(keys) }, func(keys []string) (found map[string]*User, err error) { // Fallback to secondary database log.Printf("Primary DB failed, trying secondary: %v", err) return secondaryDB.LoadUsers(keys) }, ). Build() ``` -------------------------------- ### Implement Sharding for High Concurrency Source: https://github.com/samber/hot/blob/main/bench/README.md Utilize sharding with a custom hasher to improve performance in high-concurrency environments. Specify the number of shards and the hashing function. ```go // For high concurrency cache := hot.NewHotCache[string, int](hot.LRU, 1_000). WithSharding(16, hasher). Build() ``` -------------------------------- ### Enable Missing Key Caching (Dedicated) Source: https://github.com/samber/hot/blob/main/README.md Use this when missing keys are frequent to prevent pollution of the main cache. It uses a dedicated cache for missing keys. ```go import "github.com/samber/hot" cache := hot.NewHotCache[string, int](hot.LRU, 100_000). WithMissingCache(hot.LFU, 50_000). Build() ``` -------------------------------- ### Set Appropriate TTL Values for Cache Entries Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Use `WithTTL` to set a time-to-live for cache entries. Consider shorter TTLs for frequently changing data and longer TTLs for stable data. Use `WithJitter` to prevent cache stampedes by adding random variation to TTL expiration. ```go cache := hot.NewHotCache[string, *User](hot.LRU, 100_000). WithTTL(5*time.Minute). Build() ``` ```go cache := hot.NewHotCache[string, *Config](hot.LRU, 100_000). WithTTL(1*time.Hour). Build() ``` ```go cache := hot.NewHotCache[string, *Data](hot.LRU, 100_000). WithTTL(10*time.Minute). WithJitter(0.1, 30*time.Second). // ±30s jitter Build() ``` -------------------------------- ### Configure Shared Cache for Missing Keys Source: https://github.com/samber/hot/blob/main/README.md Shares the main cache's storage for tracking missing keys, which is efficient when the rate of missing keys is low. ```go // Share missing key cache with main cache (good for low missing rate) WithMissingSharedCache() ``` -------------------------------- ### Generate Flame Graph Source: https://github.com/samber/hot/blob/main/bench/README.md Commands to generate a flame graph from a CPU profile for visual performance analysis. This aids in understanding function call frequencies and durations. ```bash # Generate flame graph go test -bench=BenchmarkLRU -cpuprofile=cpu.prof ./pkg/lru/ go tool pprof -http=:8080 cpu.prof ``` -------------------------------- ### Implement Proper Error Handling with Retries Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Implement graceful error handling for cache loading operations, including retry logic with exponential backoff. This ensures resilience against transient failures when fetching data. ```go // ✅ Good: Handle loader errors gracefully cache := hot.NewHotCache[string, *User](hot.LRU, 100_000). WithLoaders(func(keys []string) (found map[string]*User, err error) { // Implement retry logic for retries := 0; retries < 3; retries++ { found, err = loadFromDatabase(keys) if err == nil { return found, nil } time.Sleep(time.Duration(retries+1) * 100 * time.Millisecond) } return nil, fmt.Errorf("failed after 3 retries: %w", err) }). Build() ``` -------------------------------- ### Prometheus Queries for Cache Monitoring Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Use these PromQL queries to monitor key cache metrics. Analyze hit ratio, eviction rate, and utilization to ensure optimal performance and capacity. ```promql # Cache hit ratio (should be > 80% for good performance) rate(hot_hit_total[5m]) / (rate(hot_hit_total[5m]) + rate(hot_miss_total[5m])) # Eviction rate (high rates indicate undersized cache) rate(hot_eviction_total[5m]) # Cache utilization hot_length / hot_settings_capacity ``` -------------------------------- ### Hasher Interface for Key Hashing Source: https://github.com/samber/hot/blob/main/README.md The `Hasher` interface defines a function for generating a 16-bit hash of a key, crucial for shard partitioning. A fast function with minimal collisions is recommended. ```go type Hasher[K any] func(key K) uint64 func hash(key string) uint64 { hasher := fnv.New64a() hasher.Write([]byte(s)) return hasher.Sum64() } ``` -------------------------------- ### Preload Cache with Timeout Protection Source: https://github.com/samber/hot/blob/main/README.md Preloads the cache with data from a loader, including a timeout to prevent slow data sources from blocking startup. ```go // Preload with timeout protection for slow data sources WithWarmUpWithTimeout(timeout time.Duration, loader func() (map[K]V, []K, error)) ``` -------------------------------- ### Check Key Existence Source: https://github.com/samber/hot/blob/main/README.md Use `Has` to check if a key exists in the cache without any side effects. Use `PeekMany` to check multiple keys without side effects. ```go cache.Has(key K) -> bool cache.PeekMany(keys []K) -> (found map[K]V, missing []K) ``` -------------------------------- ### Set Default Time-to-Live for Cache Entries Source: https://github.com/samber/hot/blob/main/README.md Configures a default time-to-live (TTL) for all entries added to the cache. ```go // Set default time-to-live for all cache entries WithTTL(ttl time.Duration) ``` -------------------------------- ### Cache Management and Lifecycle Source: https://github.com/samber/hot/blob/main/README.md Includes methods for managing the cache's state, such as purging all items, preloading data, and controlling background cleanup processes. ```APIDOC ## Cache Management and Lifecycle ### Remove all items from cache - **Method**: `cache.Purge()` - **Description**: Removes all items from the cache immediately. ### Preload cache with data - **Method**: `cache.WarmUp(loader hot.Loader[K, V]) -> error` - **Description**: Preloads the cache with data using the provided loader function. Returns an error if the preloading fails. ### Start background cleanup - **Method**: `cache.Janitor()` - **Description**: Starts the background process for cleaning up expired items from the cache. ### Stop background janitor - **Method**: `cache.StopJanitor()` - **Description**: Stops the background janitor process that cleans up expired items. ``` -------------------------------- ### Basic Operations Source: https://github.com/samber/hot/blob/main/README.md Provides methods for fundamental cache interactions like storing, retrieving, and deleting individual key-value pairs. ```APIDOC ## Basic Operations ### Store a key-value pair - **Method**: `cache.Set(key K, value V)` - **Description**: Stores a key-value pair in the cache. ### Store with custom TTL - **Method**: `cache.SetWithTTL(key K, value V, ttl time.Duration)` - **Description**: Stores a key-value pair with a custom time-to-live (TTL), overriding the default TTL. ### Retrieve value by key - **Method**: `cache.Get(key K) -> (value V, found bool, error error)` - **Description**: Retrieves the value associated with a given key. Returns the value, a boolean indicating if the key was found, and any error encountered. ### Check if key exists - **Method**: `cache.Has(key K) -> bool` - **Description**: Checks if a key exists in the cache without any side effects. ### Remove key from cache - **Method**: `cache.Delete(key K) -> bool` - **Description**: Removes a key from the cache. Returns `true` if the key existed and was deleted. ``` -------------------------------- ### Cache Configuration Options Source: https://github.com/samber/hot/blob/main/README.md Options for configuring Time-To-Live (TTL), cache revalidation, missing key caching, data source integration, thread safety, sharding, event callbacks, and metrics. ```APIDOC ## Configuration Options ### TTL and Expiration Settings - `WithTTL(ttl time.Duration)`: Set default time-to-live for all cache entries. - `WithJitter(lambda float64, upperBound time.Duration)`: Add random jitter to TTL to prevent cache stampedes. - `WithJanitor()`: Enable background cleanup of expired items. ### Background Cache Revalidation (Stale-While-Revalidate Pattern) - `WithRevalidation(stale time.Duration, loaders ...hot.Loader[K, V])`: Keep serving stale data while refreshing in background. - `WithRevalidationErrorPolicy(policy hot.RevalidationErrorPolicy)`: Control behavior when revalidation fails (KeepOnError/DropOnError). ### Missing Key Caching - `WithMissingCache(algorithm hot.EvictionAlgorithm, capacity int)`: Use separate cache for missing keys (prevents main cache pollution). - `WithMissingSharedCache()`: Share missing key cache with main cache (good for low missing rate). ### Data Source Integration - `WithLoaders(loaders ...hot.Loader[K, V])`: Set chain of loaders for cache misses (primary, fallback, etc.). ### Thread Safety Configuration - `WithoutLocking()`: Disable mutex for single-threaded applications (performance boost). - `WithCopyOnRead(copier func(V) V)`: Copy values when reading (prevents external modification). - `WithCopyOnWrite(copier func(V) V)`: Copy values when writing (ensures cache owns the data). ### Sharding for High Concurrency - `WithSharding(shards uint64, hasher sharded.Hasher[K])`: Split cache into multiple shards to reduce lock contention. ### Event Callbacks and Hooks - `WithEvictionCallback(callback func(key K, value V))`: Called when items are evicted (LRU/LFU/TinyLFU/W-TinyLFU/S3FIFO/expiration). - `WithWarmUp(loader func() (map[K]V, []K, error))`: Preload cache on startup with data from loader. - `WithWarmUpWithTimeout(timeout time.Duration, loader func() (map[K]V, []K, error))`: Preload with timeout protection for slow data sources. ### Monitoring and Metrics - `WithPrometheusMetrics(cacheName string)`: Enable Prometheus metrics collection with the specified cache name. ### Eviction Algorithms - `hot.LRU` - `hot.LFU` - `hot.TinyLFU` - `hot.WTinyLFU` - `hot.S3FIFO` - `hot.TwoQueue` - `hot.ARC` - `hot.SIEVE` - `hot.FIFO` ### Revalidation Policies - `hot.KeepOnError` - `hot.DropOnError` ``` -------------------------------- ### Set up TTL with Jitter in HOT Cache Source: https://github.com/samber/hot/blob/main/docs/faq.md Configure Time-To-Live (TTL) with jitter to randomize expiration times and prevent cache stampedes. Jitter helps distribute the load when many items expire simultaneously. ```go cache := hot.NewHotCache[string, int](hot.LRU, 1000). WithTTL(5*time.Minute). WithJitter(0.1, 30*time.Second). // ±30s random jitter Build() ``` -------------------------------- ### Missing Key Caching Configuration Source: https://github.com/samber/hot/blob/main/docs/quickstart.md Configures a separate cache specifically for storing information about keys that do not exist, preventing repeated lookups for non-existent keys. Uses LFU eviction policy. ```go // Prevent repeated lookups for non-existent keys cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithMissingCache(hot.LFU, 500). // Separate cache for missing keys WithLoaders(userLoader). Build() ``` -------------------------------- ### Use Batch Operations for Efficiency Source: https://github.com/samber/hot/blob/main/bench/README.md Prefer batch operations like SetMany over individual Set calls for improved performance, especially when dealing with multiple items. ```go // ❌ Slow: Individual operations for _, key := range keys { cache.Set(key, value) } // ✅ Fast: Batch operations cache.SetMany(items) ``` -------------------------------- ### Batch Operations for Cache Source: https://github.com/samber/hot/blob/main/README.md Utilize batch operations like `SetMany`, `GetMany`, and `HasMany` for more efficient handling of multiple cache items. ```go cache.SetMany(items map[K]V) cache.GetMany(keys []K) -> (found map[K]V, missing []K) cache.HasMany(keys []K) -> map[K]bool ``` -------------------------------- ### Integrate Hot Cache with a Database Loader Source: https://github.com/samber/hot/blob/main/docs/faq.md Integrates a Hot Cache with a database by defining a loader function. This function is called to fetch data for keys not present in the cache. ```go cache := hot.NewHotCache[string, *User](hot.LRU, 1000). WithLoaders(func(keys []string) (found map[string]*User, err error) { // Query database for missing keys found = make(map[string]*User) for _, key := range keys { user, err := db.GetUser(key) if err == nil { found[key] = user } } return found, nil }). Build() ``` -------------------------------- ### Enable Prometheus Metrics Collection Source: https://github.com/samber/hot/blob/main/README.md Activates the collection of Prometheus metrics for the cache, identified by a given cache name. ```go // Enable Prometheus metrics collection with the specified cache name WithPrometheusMetrics(cacheName string) ``` -------------------------------- ### Store Key-Value Pair in Cache Source: https://github.com/samber/hot/blob/main/README.md Use `Set` to store a key-value pair with the default TTL. Use `SetWithTTL` to specify a custom time-to-live. ```go cache.Set(key K, value V) cache.SetWithTTL(key K, value V, ttl time.Duration) ``` -------------------------------- ### Cache with Remote Data Source Integration Source: https://github.com/samber/hot/blob/main/README.md Configures a cache to fetch data from a remote source (e.g., database) when keys are not found. Concurrent loader calls for the same key are deduplicated. ```go import "github.com/samber/hot" cache := hot.NewHotCache[string, *User](hot.LRU, 100_000). WithLoaders(func(keys []string) (found map[string]*User, err error) { rows, err := db.Query("SELECT * FROM users WHERE id IN (?)", keys) // ... return users, err }). Build() user, found, err := cache.Get("user-123") // might fail if "user-123" is not in cache and loader returns error // get or create user, found, err := cache.GetWithLoaders( "user-123", func(keys []string) (found map[string]*User, err error) { rows, err := db.Query("SELECT * FROM users WHERE id IN (?)", keys) // ... return users, err }, func(keys []string) (found map[string]*User, err error) { rows, err := db.Query("INSERT INTO users (id, email) VALUES (?, ?)", id, email) // ... return users, err }, ) // either `err` is not nil, or `found` is true // missing value vs nil value user, found, err := cache.GetWithLoaders( "user-123", func(keys []string) (found map[string]*User, err error) { // value could not be found return map[string]*User{}, nil // or // value exists but is nil return map[string]*User{"user-123": nil}, nil }, ) ``` -------------------------------- ### Load Test Cache Performance Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Conduct load tests to evaluate the cache's performance under concurrent access. Use `b.RunParallel` to simulate multiple goroutines accessing and modifying the cache. ```go func BenchmarkCachePerformance(b *testing.B) { cache := hot.NewHotCache[string, *Data](hot.LRU, 10000). WithTTL(10*time.Minute). Build() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { i := 0 for pb.Next() { key := fmt.Sprintf("key:%d", i%1000) cache.Set(key, &Data{Value: i}) cache.Get(key) i++ } }) } ``` -------------------------------- ### Unit Test Cache Behavior Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Write unit tests to verify cache functionality, including cache misses, hits, and the correct application of TTLs and loaders. Ensure data consistency and expected retrieval behavior. ```go func TestUserCache(t *testing.T) { cache := hot.NewHotCache[string, *User](hot.LRU, 100_000). WithTTL(1*time.Minute). WithLoaders(mockUserLoader). Build() // Test cache miss user, found, err := cache.Get("user:123") assert.NoError(t, err) assert.True(t, found) assert.Equal(t, "user:123", user.ID) // Test cache hit user2, found, err := cache.Get("user:123") assert.NoError(t, err) assert.True(t, found) assert.Equal(t, user, user2) // Should be same instance } ``` -------------------------------- ### Enable Sharding for High Concurrency Source: https://github.com/samber/hot/blob/main/README.md Splits the cache into multiple independent shards to reduce lock contention and improve concurrency in high-load scenarios. ```go // Split cache into multiple shards to reduce lock contention WithSharding(shards uint64, hasher sharded.Hasher[K]) ``` -------------------------------- ### Delete Key from Cache Source: https://github.com/samber/hot/blob/main/README.md Use `Delete` to remove a key from the cache, returning true if the key was present. Use `DeleteMany` for efficient removal of multiple keys. ```go cache.Delete(key K) -> bool cache.DeleteMany(keys []K) -> map[K]bool ``` -------------------------------- ### Set Eviction Callback Source: https://github.com/samber/hot/blob/main/README.md Registers a callback function that is executed whenever an item is evicted from the cache due to various eviction policies. ```go // Called when items are evicted (LRU/LFU/TinyLFU/W-TinyLFU/S3FIFO/expiration) WithEvictionCallback(callback func(key K, value V)) ``` -------------------------------- ### Handle Cache Misses Properly Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Always handle potential errors when retrieving data from the cache. Implement fallback mechanisms or return errors to prevent unexpected behavior. ```go // ❌ Bad: No error handling value, found, _ := cache.Get("key") // ✅ Good: Handle errors properly value, found, err := cache.Get("key") if err != nil { log.Printf("Cache error: %v", err) // Fallback to database or return error return nil, err } ``` -------------------------------- ### Use Copy-on-Write for Mutable Data Source: https://github.com/samber/hot/blob/main/docs/best-practices.md Implement copy-on-read to prevent external modifications to cached mutable data like configuration objects. This ensures data integrity within the cache. ```go // ✅ Good: Prevent external modifications cache := hot.NewHotCache[string, *Config](hot.LRU, 100_000). WithCopyOnRead(func(cfg *Config) *Config { // Deep copy the config return &Config{ Settings: cfg.Settings.Clone(), Metadata: cfg.Metadata.Clone(), } }). Build() ```