I saw this topic mentioned in code quest list. I think, that sequencer cache can be optimized quite a bit. If you are skeptical, I can(will have to anyway) do some quick hack™ to estimate difference of memory usage as I didn’t actually tried to research this in detail.
Also I don’t have very deep understanding of cache implementation, so please, correct me if I am wrong.
I am able to realize points below, up to prefetching as I haven’t clear image of exact implementation, that would be correct(updating animdata + thread safety).
Trivia:
We use cache to ensure smooth playback of timeline.
This may seem obvious, but when implementing cache, we should ask - will caching of this item actually help?
Overview of current cache:
Currently we use 2 types of cache used in sequencer
- preprocess cache - source data, before scaling and applying modifiers
- sequencer cache - sequence output after scaling and applying modifiers
When rendering strip stack we store
- each frame of sequence before preprocessing stage in preprocess cache
- each frame of sequence after preprocessing stage in sequencer cache
- result of stack rendering in sequencer cache
- still frames - not really interesting
Remove preprocess cache:
It does make sense to have preprocess cache, in current implementation, but there are good reasons, why not to use this cache:
- added code
- increased usage of memory (a LOT) even if there is no preprocessing going on
Getting rid of this cache is quite simple:
- remove modifiers, make them effects instead
- use prescaled proxies / scale uncached data
If sequence input is movie/image, chances are that we already do have proxies in desired resolution, therefore building cache is easier.
With patch D3597 if you chose 50% proxy resolution you will allways make proxies with resolution of 50% of project resolution, so no matter what the resolution of input is, if you have proxy, you can load it directly into RAM cache.
If sequence is effect, we render at desired resolution directly - no preprocess cache needed
Prevent unnecessary caching:
If I have timeline, on which I have movie with a bunch of effects with color correction / transformation applied user can build proxy on topmost sequence, that will output final image. On playback, if proxy is found, source is not rendered, therefore there is no need to cache these sources. This mechanism is already in place, only user can not make proxies on effects. With patch D3597 this is possible.
Other case may be static images. Properties of these can be animated, and we don’t really know if they are animated. If we know, that image is static, we can cache only one frame and use it for whole duration of sequence.
Prefetching / selective caching:
It may be good to be smart with prefetching. For example:
- if current strip stack plays at desired framerate, don’t waste time on trying to prefetch frames of this stack
- if rendering of part of timeline is time consuming, focus all possible resources to prevent FPS drop
- proxy is cache, make efficient way to load it to RAM
- filestream as cache for low RAM, but fast file storage scenario
- be aware of playhead position / time to be played vs load speed
Requirement for prefetching is having thread safe rendering process in place. Right now we are evaluating animdata for whole scene for each frame. This process write to scene object - not thread safe.
Prefetch thread would have to operate on disposable copy of scene. I tried this method, it seems to work well, just scene was visible in UI.
Other option is to use mutex, but “re-entrant” approach such as above would more likely prevent bugs like UI glitching and similar.
I would have to consult this or see similar code or consult mechanisms in place, so this is just wild guess.
Cache invalidation:
If user make change, that would change output of sequence, cache of this sequence have to be discarded / marked to be overwritten.
There is no mechanic that would do this process automatically.
Currently a lot of RNA handlers do call to invalidate cache. I was thinking about using checksums of some arrays of memory(effect data, sequence, curves, …). Doing invalidation manually doesn’t seem to be a bad thing. I am open minded here.
invalidation code however should applied to proxies also, as proxy is cache.
Please leave your opinion on proposed change.