snow icon indicating copy to clipboard operation
snow copied to clipboard

investigate ways to avoid heap allocations

Open mcginty opened this issue 7 years ago • 8 comments

Right now for the sake of cleaner syntax, there's allocation being done using Box structs to avoid forcing users of snow to specify a ton of ugly generics when they store sessions in their own structs, for example.

mcginty avatar Jun 21 '18 08:06 mcginty

It would be an option to use impl Trait. Unfortunately, this does not allow users to store the results in their own structs.

Maybe associated types would help?

vks avatar Jul 18 '18 12:07 vks

@vks I think we'd need impl Trait to extend support for being used in structs, which it currently can't do and I'm not sure what the roadmap is for that.

If you have any suggestions for associated types I'm all ears! Another thought I had was to simply disallow external resolvers and use enums to avoid allocations, but of course that comes as a compromise.

mcginty avatar Jul 19 '18 02:07 mcginty

related to #62

mcginty avatar Sep 01 '19 10:09 mcginty

Why is snow doing Box<dyn SomeTrait> everywhere rather than &'a SomeTrait? Is it because the explicit lifetimes would make it harder for snow users?

isislovecruft avatar Sep 30 '19 22:09 isislovecruft

@isislovecruft yep, it's purely for ergonomic reasons. I'd love to use something like associated traits and maybe a convenience macro to be able to drop the Boxes while keeping roughly the same level of simplicity.

mcginty avatar Oct 03 '19 04:10 mcginty

If you want trait objects without heap allocations, one option is an enum with Deref impl whose Target is the desired trait object. Something like this:

enum CipherBackends {
    #[cfg(feature = "backend1")]
    ....
}
impl core::ops::Deref for CipherBackends {
    type Target = dyn Cipher;

    fn deref(&self) -> &(dyn Cipher + 'static) {
        match self {
            #[cfg(feature = "backend1")]
            ....
        }
    }
}

This should work more or less the same as Box<Cipher>, but avoids keeping data on the heap.

Note that this does have the advantage that the size of CipherBackends will always be as big as the largest of the variants, but hopefully they're roughly the same size.

tarcieri avatar Oct 23 '19 14:10 tarcieri

@tarcieri the reason I didn't choose this method in the original design is because I wanted the option for people to implement their own crypto backends if snow didn't provide any that fit their needs. If it's totally clear that flexibility isn't necessary, we could definitely switch to something like this.

mcginty avatar Nov 10 '19 05:11 mcginty

Unfortunately I think you need either Box or a generic type parameter in that case, the former requiring a heap allocation, and the latter defeating the point of using an enum since it can just monomorphize rather than using a trait object.

tarcieri avatar Nov 10 '19 12:11 tarcieri