mergesort / Boutique

✨ A magical persistence library (and so much more) for state-driven iOS and Mac apps ✨
https://build.ms/boutique/docs
MIT License
920 stars 45 forks source link

Create A Property Wrapper To Lazily Load Data #56

Open mergesort opened 1 year ago

mergesort commented 1 year ago

As suggested by @tal in #55 Boutique's performance when loading large blobs of data like an image or video can be rather underwhelming. I thought through and wrote about this in #20, but I'd like to prioritize this a feature for Boutique to support.

It seems intuitive to see Boutique and think of using it to store images, but unfortunately that can have real performance issues since those images can balloon the size of your app's memory. In fact it’s what @samalone completely reasonably attempted to do https://github.com/mergesort/Boutique/discussions/17#discussioncomment-3025556, and I'd like to offer a good solution that promises performance, avoids code duplication, and is simple.

The shape of what I'd like to build is a new @Deferred property wrapper. A @Deferred value would not immediately load it's value into memory when a Store is created, instead it would point to a DeferredValue that could be loaded upon a property's access.

This matches a feature that other databases and ORMs provide, the ability to lazy load data, or in Core Data terms this would be called faulting. Marking a property as @Deferred would be most useful when the upfront cost of loading data is high, but a user likely wouldn't notice the cost of loading an item on demand.

Building this would require three (or potentially more steps).

  1. Creating a new DeferredValue type that signals to the Store that it's ok to not load data in real time. This type would still have to maintain some reference to the underlying data, that way it can be loaded when accessed.
  2. Creating a @Deferred property wrapper which exposes the semantics of DeferredValue without having to explicitly wrap every value you wish to defer in a DeferredValue.
  3. Adding support to load a DeferredValue on demand when reading from a Store's items, since currently all data is loaded upfront.

There may be more to do or another way of approaching this problem so I'm very open to feedback!