hollow icon indicating copy to clipboard operation
hollow copied to clipboard

Support object delegate strategies

Open DanielThomas opened this issue 7 years ago • 0 comments

It occurs to me that additional delegate types would offer a great opportunity to move away from special casing caching (or other delegate types), and instead allow a strategy to be configured per type:

  • Annotation on the model POJO
  • A default mode specified for at API generation time
  • Per type at runtime against the API
  • Per-use case, allowing the strategy to be specified either via a helper function on the object itself, or surfaced on the API

HollowObjectCacheProvider and the cachedTypes configuration supports low-cardinality, pre-populated caches, however caching is beneficial for high-cardinality types where fields are accessed repeatedly and/or in tight loops.

Also feels light object access patterns insight will need to be part of this, as they're difficult to detect without deep analysis of profiling data. Optional sampling of field access that surfaces where caching would be beneficial or is inefficient would help consumers choose a good strategy for a type (or crazier still - use that as a heuristic to automatically tune a strategy for a type).

Strategies

Flyweight

The current default lookup strategy.

Interned

The current caching strategy.

Pooled

Like the current caching strategy, but a better fit for high cardinality types. Pools the most frequently accessed objects up to a maximum cardinality or perhaps a memory budget.

Hydrated

Essentially a HollowObjectProvider that calls com.netflix.hollow.api.objects.provider.HollowFactory#newCachedHollowObject for every object instantiation.

Object Caching

Some additional work would be needed on the generator however - the current CachedImpls only stores the ordinal of reference types, and wouldn't work in a case where HollowObjectCacheProvider isn't keeping track of, and returning cached instances. So the fields would need to store references to the objects themselves, rather than just the ordinals for a hydrated case.

Here's a real world example where I swapped in my own HollowObjectFactoryProvider to produce cached objects:

screen shot 2018-11-16 at 3 33 53 pm

Because only the ordinals are cached for references, there's still significant overhead when destructing cached objects. In these caches, we do that manually where it matters.

Lazy

As above, but the generated HollowCachedDelegate cache volatile fields on first access, rather than initializing all fields in the constructor.

POJO

This is a special case in that it's not a strategy per-se, but I think should be a possibility in the generated API. See #342 for details.

DanielThomas avatar Nov 13 '18 17:11 DanielThomas