/ src / dyn_trait_obj.rs
dyn_trait_obj.rs
  1  use super::*;
  2  
  3  module_group! {
  4      name = "Dynamic-Trait-Object";
  5      benches = core, snafu_fat_vs_anyhow_thin
  6  }
  7  
  8  
  9  #[inline(never)]
 10  fn more<T>(x: T) -> T
 11  {
 12      bb(x)
 13  }
 14  
 15  
 16  /// Fundamental uses of passing (as return value or as argument value) fat `dyn Trait` type
 17  /// vs. thin static type, without use of the error-helping libraries.
 18  fn core(c: &mut Criterion)
 19  {
 20      bench_group! { (c) name = "Core";
 21          routines = [
 22              "Thin" = || drop(bb(thin())),
 23              "Fat" = || drop(bb(fat())),
 24              "Thin-More" = || drop(bb(thin_more())),
 25              "Fat-More" = || drop(bb(fat_more())),
 26          ];
 27      }
 28  
 29      #[derive(Debug)]
 30      struct MyError;
 31      impl_StdError! { MyError }
 32  
 33      assert!(size_of::<MyError>() == 0); // So Box::new(MyError) won't allocate.
 34      assert!(size_of::<Box<MyError>>() == size_of::<usize>()); // It's still a pointer.
 35      assert!(size_of::<Box<dyn StdError>>() == 2 * size_of::<usize>()); // Still fat.
 36  
 37      macro_rules! e {
 38          () => {
 39              bb(Box::new(bb(MyError)))
 40          };
 41      }
 42  
 43      fn thin() -> Result<(), Box<MyError>>
 44      {
 45          Err(e!())
 46      }
 47  
 48      fn fat() -> Result<(), Box<dyn StdError>>
 49      {
 50          Err(e!())
 51      }
 52  
 53      fn thin_more() -> Result<(), Box<MyError>>
 54      {
 55          bb(more(bb(Err(bb(more::<Box<MyError>>(e!()))))))
 56      }
 57  
 58      fn fat_more() -> Result<(), Box<dyn StdError>>
 59      {
 60          bb(more(bb(Err(bb(more::<Box<dyn StdError>>(e!()))))))
 61      }
 62  }
 63  
 64  
 65  /// Passing (as return value or as argument value) SNAFU's fat `Box<dyn StdError>` type in its
 66  /// fatter `Whatever` type vs. Anyhow's thin-box type.
 67  fn snafu_fat_vs_anyhow_thin(c: &mut Criterion)
 68  {
 69      // These avoid needing creation in the first two bench'ed routines.
 70      let mut ae: Option<anyhow::Error> = Some(anyhow!(""));
 71      #[allow(clippy::useless_format)]
 72      let mut se: Option<MyWhatever> = Some(snafu::FromString::without_source(format!("")));
 73  
 74      bench_group! { (c) name = "Snafu-Fat-Vs-Anyhow-Thin";
 75          routines = [
 76              "Anyhow" = || ae = bb(anyhow(bb(ae.take().unwrap()))).err(),
 77              "Snafu" = || se = bb(snafu(bb(se.take().unwrap()))).err(),
 78              "Anyhow-Create" = || drop(bb(anyhow_create())),
 79              "Snafu-Create" = || drop(bb(snafu_create())),
 80          ];
 81      }
 82  
 83      assert!(size_of::<anyhow::Error>() == size_of::<usize>());
 84  
 85      // Comparable to `Thin-More`.
 86      fn anyhow(e: anyhow::Error) -> Result<(), anyhow::Error>
 87      {
 88          bb(more(bb(Err(bb(more(bb(e)))))))
 89      }
 90  
 91      fn anyhow_create() -> Result<(), anyhow::Error>
 92      {
 93          let e: anyhow::Error = anyhow!("");
 94          anyhow(e)
 95      }
 96  
 97      assert!(size_of::<MyWhatever>() >= 2 * size_of::<usize>());
 98  
 99      // Comparable to `Fat-More`.
100      fn snafu(e: MyWhatever) -> Result<(), MyWhatever>
101      {
102          bb(more(bb(Err(bb(more(bb(e)))))))
103      }
104  
105      fn snafu_create() -> Result<(), MyWhatever>
106      {
107          #[allow(clippy::useless_format)]
108          let e: MyWhatever = snafu::FromString::without_source(format!(""));
109          snafu(e)
110      }
111  }