Implement compression of objects before they are saved into the storage
provider. Each container type can specify which algorithm to use
(currently `none` or `zstd`) and the compression level.
Add infrastructure to pypeline that allows containers to be notified
when they are being used last, this allows two things:
* `Pipe`s eagerly clearing those containers once they are done reading
their contents
* `ScheduledTask`s clearing those out at the end of their execution in
case the pipe did not do it
This overall should improve memory usage as container no longer take up
memory if they are no longer used as part of a `Schedule`.
Add another container for LLVM modules. This one stores one
`llvm::Module` per function (all modules share the same
`llvm::LLVMContext` for performance reasons).
Add the needed infrastructures that allow ephemeral classes (`PipeRun`s)
to be wrapped as a regular pypeline `Pipe` class. These automatically
have their dependencies tracked and propagated to the pypeline.