Skip to content

Retire AtomData range/labels caches in favour of eager computation #68

@bjmorgan

Description

@bjmorgan

Now that #64 has landed and AtomData stored arrays are frozen on assignment, the derived global_range and global_labels values cannot go stale without going through __setitem__. This opens up a small refactor that simplifies the container.

Current state

AtomData computes global_range and global_labels lazily and caches the results in _range_cache / _labels_cache. _invalidate(key) is called from __setitem__ and __delitem__ to drop stale entries on the supported update paths. Lazy-with-invalidation was the only safe design when stored arrays were mutable, because in-place mutation of the buffer could silently desync the caches.

Proposal

Compute global_range and global_labels eagerly in __setitem__, store them in plain dicts, and retire _invalidate:

  • __setitem__ populates self._ranges[key] and self._labels[key] alongside self._data[key].
  • __delitem__ removes the key from all three dicts.
  • global_range and global_labels become O(1) dict lookups with no cache-presence branches.
  • The _invalidate helper is deleted.

Trade-offs

  • For: The stale-cache foot-gun becomes mechanically impossible rather than merely documented-as-impossible. _invalidate and the if key in cache branches disappear. The derivation of range/labels happens at exactly one site (assignment) rather than scattered across first-query code paths.
  • Against: Compute cost is paid eagerly even for keys whose range/labels are never queried. In practice the rendering pipeline does query them for colourmap normalisation, so the lazy path is rarely "saved" work. Tiny extra memory for storing the derived values on every key.

Out of scope

This is a pure refactor with no observable behaviour change, so the existing tests for global_range and global_labels should keep passing untouched. No public API changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions