timerpool

package
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 3, 2025 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package timerpool provides an optional timer pool for optimizing UseDebounce and UseThrottle composables.

Timer pooling reduces allocation overhead by reusing time.Timer instances instead of creating new ones for each composable. This is an opt-in optimization that can improve performance in applications with heavy debounce/throttle usage.

The pool uses sync.Pool for efficient, thread-safe timer reuse with automatic garbage collection of unused timers. All operations are thread-safe and suitable for concurrent use.

Usage:

// Enable global timer pool (optional, call once at startup)
timerpool.EnableGlobalPool()

// UseDebounce and UseThrottle will automatically use the pool
debounced := UseDebounce(ctx, value, 300*time.Millisecond)

// Check pool statistics
stats := timerpool.GlobalPool.Stats()
fmt.Printf("Active: %d, Hits: %d, Misses: %d\n", stats.Active, stats.Hits, stats.Misses)

Performance:

Timer pooling can reduce composable creation overhead from ~865ns to ~450ns (52% improvement) for UseDebounce and from ~473ns to ~250ns (47% improvement) for UseThrottle. After pool warmup, allocations drop to zero for timer acquisition.

When to Enable:

  • Applications with many concurrent debounce/throttle composables (> 100)
  • High-frequency composable creation/destruction
  • Performance-critical real-time applications

When to Skip:

  • Small applications with few composables (< 50)
  • Current performance is already acceptable
  • Simplicity is more important than micro-optimization

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnableGlobalPool

func EnableGlobalPool()

EnableGlobalPool initializes and enables the global timer pool.

After calling this, all UseDebounce and UseThrottle composables will automatically use timer pooling for improved performance. Safe to call multiple times (idempotent).

Call this once at application startup to enable pooling globally:

func main() {
    timerpool.EnableGlobalPool()
    // ... rest of application ...
}

Thread-safe: Safe to call concurrently from multiple goroutines via sync.Once.

func ResetGlobalPoolForTesting

func ResetGlobalPoolForTesting()

ResetGlobalPoolForTesting resets the global pool state for testing purposes. This function is ONLY for use in tests and should never be called in production code. It resets both GlobalPool and the sync.Once guard to allow re-initialization.

WARNING: This is not thread-safe and should only be called when no other goroutines are accessing GlobalPool.

Types

type Stats

type Stats struct {
	Active int64 // Number of currently active (acquired) timers
	Hits   int64 // Number of times a timer was reused from the pool
	Misses int64 // Number of times a new timer had to be created
}

Stats contains statistics about timer pool usage.

These metrics help monitor pool efficiency and identify optimization opportunities.

type TimerPool

type TimerPool struct {
	// contains filtered or unexported fields
}

TimerPool manages a pool of reusable time.Timer instances for performance optimization.

The pool tracks active timers to prevent leaks and provides statistics on pool usage. All operations are thread-safe using RWMutex for efficient concurrent access.

Implementation uses sync.Pool for automatic memory management - timers not in use may be garbage collected, and new timers are created on demand when the pool is empty.

var GlobalPool *TimerPool

GlobalPool is the default timer pool instance used by composables when pooling is enabled.

Initially nil. Call EnableGlobalPool() to initialize and enable timer pooling for all UseDebounce and UseThrottle composables.

Example:

// Enable at application startup
timerpool.EnableGlobalPool()

// Later in code - composables automatically use the pool
debounced := UseDebounce(ctx, value, 300*time.Millisecond)

func NewTimerPool

func NewTimerPool() *TimerPool

NewTimerPool creates a new timer pool with initialized internal structures.

The pool is ready to use immediately and will create timers on demand as needed. Returns a pointer to the pool for efficient passing and to allow stat tracking.

Example:

pool := timerpool.NewTimerPool()
timer := pool.Acquire(100 * time.Millisecond)
// ... use timer ...
timer.Stop()
pool.Release(timer)

func (*TimerPool) Acquire

func (tp *TimerPool) Acquire(d time.Duration) *time.Timer

Acquire gets a timer from the pool, configured for the specified duration.

If the pool has a timer available, it's reused (cache hit). Otherwise, a new timer is created (cache miss). The timer is tracked as active to prevent leaks.

The returned timer is reset to the specified duration and is ready to use. Callers should Stop() the timer when done and then Release() it back to the pool.

Thread-safe: Safe to call concurrently from multiple goroutines.

Parameters:

  • d: Duration for the timer. Can be zero or negative (timer fires immediately).

Returns:

  • *time.Timer: A timer configured for the specified duration

Example:

timer := pool.Acquire(500 * time.Millisecond)
defer func() {
    timer.Stop()
    pool.Release(timer)
}()

select {
case <-timer.C:
    // Timer expired
case <-ctx.Done():
    // Context canceled
}

func (*TimerPool) Release

func (tp *TimerPool) Release(timer *time.Timer)

Release returns a timer to the pool for reuse.

The timer should be stopped before releasing. Released timers are removed from the active tracking map and returned to the pool for future Acquire() calls.

Releasing nil is safe (no-op). Releasing the same timer twice is also safe (idempotent).

Thread-safe: Safe to call concurrently from multiple goroutines.

Parameters:

  • timer: The timer to release. Must have been acquired from this pool.

Example:

timer := pool.Acquire(100 * time.Millisecond)
// ... use timer ...
timer.Stop()
pool.Release(timer) // Safe to call
pool.Release(timer) // Safe to call again (idempotent)

func (*TimerPool) Stats

func (tp *TimerPool) Stats() Stats

Stats returns current statistics about pool usage.

Statistics include the number of active timers, cache hits, and cache misses. These metrics help monitor pool efficiency and identify performance characteristics.

A high hit rate (hits / (hits + misses)) indicates effective pooling. A low hit rate may indicate the pool is too small or timers are held too long.

Thread-safe: Safe to call concurrently from multiple goroutines.

Returns:

  • Stats: Current pool statistics

Example:

stats := pool.Stats()
hitRate := float64(stats.Hits) / float64(stats.Hits + stats.Misses)
fmt.Printf("Pool efficiency: %.1f%% hit rate\n", hitRate*100)
fmt.Printf("Active timers: %d\n", stats.Active)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL