deku icon indicating copy to clipboard operation
deku copied to clipboard

Benchmarks and performance

Open sharksforarms opened this issue 5 years ago • 5 comments

Using criterion

+bonus if compared to other crates like nom for reading

sharksforarms avatar May 28 '20 20:05 sharksforarms

Added some simple benchmarks to catch regressions and measure optimisations on reading

sharksforarms avatar Jun 01 '20 02:06 sharksforarms

I was playing with the magic attribute and benchmarks and I realized it is very slow so I thought I would share:

#![feature(test)]

use deku::prelude::*;

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(endian = "big", magic = b"\x00\x00\x00\x05")]
struct WithMagicV5 {
    value: u32
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(endian = "big")]
struct WithoutMagicV5 {
    #[deku(assert = "*version == 5")]
    version: u32,  // users ideally should not be able to set this as it is always 5
    value: u32
}

#[cfg_attr(test, macro_use)]
extern crate hex_literal;

#[cfg(test)]
mod magic_benches {
    use super::*;

    extern crate test;
    use test::Bencher;
    
    #[bench]
    fn bench_with_magic(b: &mut Bencher) {
        let data = hex!("00 00 00 05 00 00 00 01");
        b.iter(|| {
            let (_, _) = WithMagicV5::from_bytes((&data, 0)).unwrap();
        });
    }
    
    #[bench]
    fn bench_without_magic(b: &mut Bencher) {
        let data = hex!("00 00 00 05 00 00 00 01");
        b.iter(|| {
            let (_, _) = WithoutMagicV5::from_bytes((&data, 0)).unwrap();
        });
    }
}

And the results:

running 2 tests
test magic_benches::bench_with_magic        ... bench:          48 ns/iter (+/- 4)
test magic_benches::bench_without_magic     ... bench:          21 ns/iter (+/- 6)

OliverGavin avatar Apr 17 '21 16:04 OliverGavin

I was playing with the magic attribute and benchmarks and I realized it is very slow so I thought I would share:

Nice one!

There are some optimizations which could be done. This is a great example.

For example, magic attribute handling could convert the byte string to 0x00000005u32 (at compile time?) and do a single u32 read and equality check. Currently, it would do 4 u8 reads and 4 equality checks (iterating the byte string).

To add flexibility, magic could also accept a number or a bytestring!

sharksforarms avatar Apr 17 '21 17:04 sharksforarms

Oh yeah, actually the first problem I faced with magic was that I couldn't pass a number (and it wasn't clear from the docs as it was a string example).

I'd be happy to give this a shot if you could give me a rough idea where to look? Seems relatively easy.

OliverGavin avatar Apr 17 '21 19:04 OliverGavin

@OliverGavin Yes! That would be awesome. Happy to show you where to start.

I'd take a look at how the id attribute works, this attribute accepts both b"bytes" and tokens: https://github.com/sharksforarms/deku/blob/master/deku-derive/src/lib.rs#L17

The magic attribute is declared here: https://github.com/sharksforarms/deku/blob/master/deku-derive/src/lib.rs#L121 and as you can see only accepts a LitByteStr. This would involve changing the type to an enum to accept either b"" and other desired variants (such as LitInt)

I'll create an issue for this!

Edit: https://github.com/sharksforarms/deku/issues/204

sharksforarms avatar Apr 20 '21 16:04 sharksforarms