Skip to content
This repository has been archived by the owner on Aug 15, 2021. It is now read-only.
This repository has been archived by the owner on Aug 15, 2021. It is now read-only.

Compilation is very slow, especially for release builds #189

Open
@Timmmm

Description

The example file below contains a load of serde-derive'd structs and code to load them using serde_cbor. I compiled it in release & debug, and then again after changing serde_cbor to serde_json to get the following compile times:

Debug Release
serde_json 5.0s 13.3s
serde_cbor 11.2s 53.9s

As you can see it is a lot slower than serde_json, and the release build is unusably slow. By looking at the Rust and LLVM profiling outputs I found that most of the time is spent in LLVM and mostly in optimising serde_cbor-related functions.

I compared the output of cargo expand and as expected the only line that changes is serde_cbor/json::from_reader().

To get the LLVM timings run this command:

cargo +nightly rustc --release -- -Zself-profile -Zno-parallel-llvm -Zllvm-time-trace

And then open the resulting llvm_timings.json in about:tracing.

image

If you zoom in and click on the OptFunction blocks it tells you which function it is optimising.

image

From clicking around randomly the most common one is serde_cbor::de::Deserializer<R>::parse_value function (with various hashes at the end), but there's also parse_str, parse_map, recursion_checked, etc. Kind of makes sense because parse_value has that big map but honesty I can't see why it should take so long.

Here's my test code:

#![allow(non_snake_case)]
#![allow(non_camel_case_types)]

use serde::Deserialize;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use anyhow::Result;

#[derive(Deserialize, Debug)]
pub struct CA {
  pub a: CB,
  pub b: CC,
  pub c: HashMap<String, f64>,
  pub d: Vec<CD>,

  pub e: CE,
  pub f: CF,

  pub g: Vec<CG>,
  pub h: Vec<u32>,
  pub i: Vec<u32>,

  pub j: CJ,
  pub k: CH,
  pub l: CL,

  pub n: Memory,

  pub o: Option<CO>,
}

#[derive(Deserialize, Debug)]
pub struct CO {
  pub a: String,
  pub b: String,
  pub c: u32,
  pub d: u32,
  pub e: u32,
}

#[derive(Deserialize, Debug)]
pub struct CB {
  pub a: u64,
  pub b: u64,
  pub c: u64,
  pub d: u64,
}

#[derive(Deserialize, Debug)]
pub struct CD {
  pub a: String,
  pub b: u64,
  pub c: String,
  pub d: String,
  pub e: u32,
  pub f: u32,
  pub g: u64,
}

#[derive(Deserialize, Debug)]
pub struct CJ {
  pub a: Vec<Vec<u64>>,
  pub b: Vec<Vec<u64>>,
  pub c: Option<Vec<Vec<u64>>>,
  pub d: Vec<Vec<u64>>,
  pub e: Option<Vec<String>>,
  pub f: Option<Vec<String>>,

}

#[derive(Deserialize, Debug)]
pub struct CL {
  pub a: Vec<Vec<u64>>,
  pub b: Vec<Vec<u64>>,
  pub c: Vec<Vec<u64>>,
  pub d: Option<Vec<HashMap<String, String>>>,
  pub e: Option<Vec<HashMap<String, String>>>,

}

#[derive(Deserialize, Debug)]
pub struct CH {
  pub a: Vec<Vec<u64>>,
  pub b: Vec<Vec<u64>>,
  pub c: Vec<Vec<u64>>,
  pub d: Option<Vec<String>>,
  pub e: Option<Vec<String>>,

}

#[derive(Deserialize, Debug)]
pub struct CE {
  pub a: Vec<String>,
  pub b: Vec<Vec<u32>>,
  pub c: Vec<Vec<u32>>,
  pub d: Option<CycleEstimates>,
}

#[derive(Deserialize, Debug)]
pub struct CycleEstimates {
  pub a: Vec<Vec<u64>>,
  pub b: Vec<Vec<u64>>,
  pub c: Vec<Vec<u64>>,
}

#[derive(Deserialize, Debug)]
pub struct CC {
  pub a: u64,
  pub b: u64,
  pub c: f64,
  pub d: u64,
  pub e: u64,
  pub f: u64,
  pub g: Vec<u64>,
  pub h: u64,
  pub i: u64,
  pub j: TT,
}

#[derive(Deserialize, Debug)]
pub enum TT {
  A,
  B,
  C,
}

#[derive(Deserialize, Debug)]
pub struct CF {
  pub a: Vec<String>,
  pub b: Vec<u64>,
}

#[derive(Deserialize, Debug)]
pub struct Memory {
  pub a: DA,
  pub b: DB,
  pub c: DC,
  pub d: DD,
  pub e: DE,
}

#[derive(Deserialize, Debug)]
pub struct DA {
  pub a1: AA,
  pub a2: AA,
  pub a3: AA,
  pub a4: AA,
  pub a5: AA,
  pub a6: AA,
  pub a7: AA,
  pub a8: AA,
  pub a9: AA,
  pub a10: AA,
  pub a11: AA,
  pub a12: AA,
  pub a13: AA,
  pub a14: AA,
  pub a15: AA,
  pub a16: AA,
  pub a17: AA,
  pub a18: AA,
  pub a19: AA,
  pub a20: AA,
  pub a21: AA,
  pub a22: AA,
}

#[derive(Deserialize, Debug)]
pub struct AA {
  pub a: XS,
  pub b: XS,
  pub c: XS,
  pub d: Vec<u32>,
}

#[derive(Deserialize, Debug)]
pub struct XS {
  pub a: Vec<u32>,
  pub b: Vec<u32>,
}

#[derive(Deserialize, Debug)]
pub struct DB {
  pub a1: Vec<Vec<u32>>,
  pub a2: Vec<Vec<u32>>,
  pub a3: Vec<Vec<u32>>,
  pub a4: Vec<Vec<u32>>,
  pub a5: Vec<Vec<u32>>,
  pub a6: Vec<Vec<u32>>,
  pub a7: Vec<Vec<u32>>,
  pub a8: Vec<Vec<u32>>,
}

#[derive(Deserialize, Debug)]
pub struct DC {
  pub a1: Vec<u32>,
  pub a2: Vec<u32>,
  pub a3: Vec<u32>,
  pub a4: Vec<u32>,
  pub a5: Vec<u32>,
  pub a6: Vec<u32>,
  pub a7: Vec<u32>,
  pub a8: Vec<u32>,
}

#[derive(Deserialize, Debug)]
pub struct DD {
  pub a1: Vec<Vec<u32>>,
  pub a2: Vec<Vec<u32>>,
  pub a3: Vec<Vec<u32>>,
  pub a4: Vec<Vec<u32>>,
  pub a5: Vec<Vec<u32>>,
  pub a6: Vec<Vec<u32>>,
  pub a7: Vec<Vec<u32>>,
  pub a8: Vec<Vec<u32>>,
}

#[derive(Deserialize, Debug)]
pub struct DE {
  pub a: AL,
  pub b: Vec<u64>,
  pub e: NAL,
}

#[derive(Deserialize, Debug)]
pub struct AL {
  pub a: Vec<u32>,
  pub b: HashMap<String, VDE>,
}

#[derive(Deserialize, Debug)]
pub struct VDE {
  pub a: u64,
  pub b: Vec<u32>,
}

#[derive(Deserialize, Debug)]
pub struct NAL {
  pub a: Vec<u32>,
  pub b: Vec<CGDE>,
}

#[derive(Deserialize, Debug)]
pub struct CGDE {
  pub a: u64,
  pub b: Vec<u32>,
  pub c: usize,
  pub d: HashMap<String, VDE>,
  pub e: Vec<CGDE>,
}


#[derive(Deserialize, Debug)]
#[serde(tag = "type")]
pub enum CG {
  Se(Se),
  Sh(Sh),
  Sw(Sw),
  Re(Re),
  ReWh(ReWh),
  If(If),
  IfElse(IfElse),
  Call(Call),
  OTE(OTE),
  DX(DX),
  GX(GX),
  SCo(SCo),
  CSS(CSS),
  Sync(Sync),
  SLC(SLC),
  SLCFV(SLCFV),
  GLC(GLC),
  ATF(ATF),
  ATVE(ATVE),
  WU(WU),
  SSSS(SSSS),
  Sans(Sans),
  Sans2(Sans2),
  Tif(Tif),
}

#[derive(Deserialize, Debug)]
pub struct Se {
  pub c: Vec<usize>,
}

#[derive(Deserialize, Debug)]
pub struct Sh {
  pub c: Vec<usize>, // 1 child
}

#[derive(Deserialize, Debug)]
pub struct Sw {
  pub c: Vec<usize>,
}

#[derive(Deserialize, Debug)]
pub struct Re {
  pub c: Vec<usize>, // 1 child
}

#[derive(Deserialize, Debug)]
pub struct ReWh {
  pub c: Vec<usize>, // 1st child is condition, 2nd is body.
}

#[derive(Deserialize, Debug)]
pub struct If {
  pub c: Vec<usize>, // 1st child is true body, 2nd is false body.
}

#[derive(Deserialize, Debug)]
pub struct IfElse {
  pub c: Vec<usize>,
}

#[derive(Deserialize, Debug)]
pub struct Call {
  pub a: usize,
}

#[derive(Deserialize, Debug)]
pub struct OTE {
  pub b: usize,
}

#[derive(Deserialize, Debug)]
pub struct DX {
  pub a: usize,
  pub b: String,
}

#[derive(Deserialize, Debug)]
pub struct GX {
  pub a: usize,
  pub b: String,
}

#[derive(Deserialize, Debug)]
pub struct SCo {
  pub a: usize,
}

#[derive(Deserialize, Debug)]
pub struct CSS {
  pub a: usize,
}

#[derive(Deserialize, Debug)]
pub struct Sync {
  pub a: SyTy,
}

#[derive(Deserialize, Debug)]
pub struct SLC {
}

#[derive(Deserialize, Debug)]
pub struct SLCFV {
}

#[derive(Deserialize, Debug)]
pub struct GLC {
}

#[derive(Deserialize, Debug)]
pub struct ATF {
}

#[derive(Deserialize, Debug)]
pub struct ATVE {
}

#[derive(Deserialize, Debug)]
pub struct WU {
}

#[derive(Deserialize, Debug)]
pub struct SSSS {
}

#[derive(Deserialize, Debug)]
pub struct Sans {
  pub a: Vec<u32>,
}

#[derive(Deserialize, Debug)]
pub struct Sans2 {
  pub a: Vec<u32>,
}

#[derive(Deserialize, Debug)]
pub struct Tif {
  pub c: Vec<usize>,
}

#[derive(Deserialize, Debug)]
pub enum SyTy {
  Internal,
  External,
}

pub fn read_file(
  filename: &Path,
) -> Result<CA> {

  let file = File::open(filename)?;

  let reader = BufReader::new(file);

  Ok(serde_cbor::from_reader(reader)?)
}

fn main() -> Result<()> {
    let gp = read_file(Path::new("foo"))?;
    dbg!(gp);
    Ok(())
}

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions