Skip to content

der: Huge generic bloat due to NestedReader #1228

@dishmaker

Description

@dishmaker

Hi!

My .exe file using der crate for a huge protocol is too large (12 MB for a simple DER encoder/decoder)
I've just used cargo bloat and cargo llvm-lines on my protocol crate and was surprised that der crate makes a lot of generic functions.

read_nested is actually the main cause!

Lines                  Copies               Function name
-----                  ------               -------------
34633 (2.6%,  2.6%)    187 (1.0%,  1.0%)    der::reader::Reader::read_nested

Because it is nesting itself recursively!

NestedReader<NestedReader<NestedReader<SliceReader>>>

You can easily check by adding field test: FailAsn1 inside your #[derive(Sequence)]

pub struct FailAsn1 {}

impl<'a> DecodeValue<'a> for FailAsn1 {
    fn decode_value<R: Reader<'a>>(
        reader: &mut R,
        header: Header,
    ) -> Result<Self> {
        // prints: reader type name: NestedReader<NestedReader<NestedReader<NestedReader<NestedReader<SliceReader>>>>>
        panic!("reader type name: {}", tynm::type_name::<R>())
    }
}

Not only that Reader gets generic-bloated but also all Decode and DecodeValue traits.

Really! Just look above, DecodeValue is generic over R: Reader so all objects implementing Decode also get bloated.

But the main cause is that:

  • NestedReader takes Self that can be another NestedReader:

formats/der/src/reader.rs

Lines 127 to 131 in 086ecd7

fn read_nested<'n, T, F>(&'n mut self, len: Length, f: F) -> Result<T>
where
F: FnOnce(&mut NestedReader<'n, Self>) -> Result<T>,
{
let mut reader = NestedReader::new(self, len)?;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions