flatland-protocol 0.2.3

Flatland3 wire protocol types and codecs
Documentation
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use flatland_protocol::{
    codec::{BincodeCodec, Codec, PostcardCodec},
    types::{EntityState, TickDelta, Transform, Velocity2D, WorldClock, WorldCoord},
    Envelope,
};

fn sample_tick_delta(entity_count: usize) -> TickDelta {
    TickDelta {
        tick: 1_337,
        entities: (0..entity_count)
            .map(|i| EntityState {
                id: (i + 1) as u64,
                label: String::new(),
                transform: Transform {
                    position: WorldCoord::surface(i as f32 * 0.7, i as f32 * 0.3),
                    yaw: (i as f32 * 0.1) % 6.28,
                    velocity: Velocity2D {
                        vx: 1.2,
                        vy: -0.4,
                    },
                },
                vitals: None,
                attributes: None,
                skills: None,
                inside_building: None,
            })
            .collect(),
        resource_nodes: Vec::new(),
        buildings: Vec::new(),
        doors: Vec::new(),
        npcs: Vec::new(),
        inventory: Vec::new(),
        blueprints: Vec::new(),
        world_clock: WorldClock::default(),
        ground_drops: Vec::new(),
        placed_containers: Vec::new(),
        combat: None,
    }
}

fn bench_codec(c: &mut Criterion) {
    let mut group = c.benchmark_group("tick_delta_codec");
    for entity_count in [15, 50, 100] {
        let payload = Envelope::new(sample_tick_delta(entity_count));

        group.bench_with_input(
            BenchmarkId::new("postcard_encode", entity_count),
            &payload,
            |b, payload| {
                let codec = PostcardCodec;
                b.iter(|| codec.encode(black_box(payload)).unwrap());
            },
        );
        group.bench_with_input(
            BenchmarkId::new("postcard_decode", entity_count),
            &payload,
            |b, payload| {
                let codec = PostcardCodec;
                let bytes = codec.encode(payload).unwrap();
                b.iter(|| {
                    let decoded: Envelope<TickDelta> = codec.decode(black_box(&bytes)).unwrap();
                    black_box(decoded);
                });
            },
        );
        group.bench_with_input(
            BenchmarkId::new("bincode_encode", entity_count),
            &payload,
            |b, payload| {
                let codec = BincodeCodec;
                b.iter(|| codec.encode(black_box(payload)).unwrap());
            },
        );
        group.bench_with_input(
            BenchmarkId::new("bincode_decode", entity_count),
            &payload,
            |b, payload| {
                let codec = BincodeCodec;
                let bytes = codec.encode(payload).unwrap();
                b.iter(|| {
                    let decoded: Envelope<TickDelta> = codec.decode(black_box(&bytes)).unwrap();
                    black_box(decoded);
                });
            },
        );

        let postcard_bytes = PostcardCodec.encode(&payload).unwrap();
        let bincode_bytes = BincodeCodec.encode(&payload).unwrap();
        eprintln!(
            "entity_count={entity_count} postcard={} bytes bincode={} bytes",
            postcard_bytes.len(),
            bincode_bytes.len()
        );
    }
    group.finish();
}

criterion_group!(benches, bench_codec);
criterion_main!(benches);