expirable-cache icon indicating copy to clipboard operation
expirable-cache copied to clipboard

perf: optimize TTL expiration with runtime.nanotime() and consolidated type assertions

Open analytically opened this issue 3 months ago • 1 comments

Replace time.Time with int64 nanotime values for expiration tracking, simplifying TTL checks and reducing memory footprint. 19-30% faster.

Performance improvements (benchstat with n=3 on Apple M1):

  • LRU_Rand_NoExpire: 219.6ns → 173.9ns (-20.8%)
  • LRU_Freq_NoExpire: 218.5ns → 176.2ns (-19.4%)
  • LRU_Rand_WithExpire: 251.8ns → 175.4ns (-30.3%)
  • LRU_Freq_WithExpire: 250.1ns → 176.7ns (-29.3%)

Changes:

  • Use runtime.nanotime() via //go:linkname for fastest monotonic time
  • Store expiration as int64 nanoseconds instead of time.Time
  • Consolidate type assertions (2+ calls → 1 per operation)
  • Replace time.After() with direct integer comparison
  • Remove GetExpiration()

Benefits:

  • Performance: 20-30% faster across all operations
  • Memory: 16 bytes saved per entry (67% reduction in time storage)
  • Correctness: Immune to system clock adjustments (NTP, DST, manual changes)
  • Throughput: Increased from ~4.6M to ~5.7M ops/sec per goroutine

Note: runtime.nanotime() is an internal Go API that may change in future versions. Trade-off accepted for significant performance and correctness benefits.

analytically avatar Oct 01 '25 17:10 analytically

@paskal could you review?

analytically avatar Oct 01 '25 17:10 analytically