Caching.md - Mirroar/hivemind GitHub Wiki

Caching

Hivemind uses a flexible caching system to optimize performance by storing frequently accessed or expensive-to-calculate data. Caching helps reduce CPU usage and avoid redundant calculations, but it's important to use it correctly to avoid bugs or stale data.

How the Cache Works

  • The cache stores data under a unique cache key (a string identifier) for a specified interval (in ticks).
  • When you request cached data, you provide a key, a maximum age, and a callback to generate the data if it's missing or expired.
  • The cache system supports three main storage locations:
    • Heap cache: Data is stored in the bot's heap memory. It is fast and efficient, but is lost on a global reset (e.g., code upload). Use cache.inHeap and cache.fromHeap.
    • Memory cache: Data is stored in persistent Memory and survives global resets. Use cache.inMemory and cache.fromMemory.
    • Object cache: Data is stored on the _cache property of any object (commonly used for game objects like rooms or creeps to store calculated properties for the current tick only). Use cache.inObject and cache.fromObject.

Example Usage

import cache from 'utils/cache';

// Cache in heap for 10 ticks
const result = cache.inHeap('myKey', 10, () => expensiveCalculation());

// Cache in persistent memory for 100 ticks
const result = cache.inMemory('myPersistentKey', 100, () => fetchData());

// Cache on a room object for the current tick
const sources = cache.inObject(room, 'sources', 1, () => room.find(FIND_SOURCES));

Important Notes

  • Never store game objects (like Creep, Room, or Structure instances) in cache. These objects are only valid for the current tick and will become invalid or cause errors if accessed later. Instead, cache their IDs or calculated properties and retrieve them using Game.getObjectById.
  • Choose the cache location based on how long you want the data to persist and how expensive it is to recalculate.
  • Use unique and descriptive cache keys to avoid collisions.
  • The maxAge parameter controls how often the cached data is refreshed. Shorter intervals mean fresher data but more CPU usage.
  • The cache interval is not fixed - the system will automatically adjust based on CPU usage and the current game state. This means that if the bot is under heavy load, it may skip some cache updates to prioritize critical tasks.

Best Practices

  • Use heap cache for fast, per-tick optimizations that don't need to survive global resets.
  • Use memory cache for data that is expensive to recalculate and should persist across resets.
  • Use object cache for properties that are specific to a single game object (e.g., a room's sources or a creep's calculated path).
  • Always cache serializable data (numbers, strings, arrays, plain objects), not game objects.