title: How do I use filter_map() rather then filter() combined with map() without performance decreasing?
body: <p>I would like to use <code>filter_map()</code> instead of <code>unwrap()</code> in the <code>map()</code> and <code>filter()</code> but I see a performance decrease when doing this. How do I write the code using <code>filter_map()</code> without losing performance? Why is there a loss of performance in the first place?</p>
  
  <p><strong>src/lib.rs</strong></p>
  
  <pre><code>use std::collections::HashMap;
  
  pub enum Kind {
      Square(Square),
      Circle(Circle),
  }
  
  #[derive(Default, Copy, Clone)]
  pub struct Circle {
      a: u32,
      b: u32,
      c: u32,
      d: u32,
  }
  
  #[derive(Default)]
  pub struct Square {
      a: u32,
      b: Option&lt;u32&gt;,
      c: Option&lt;u32&gt;,
      d: Option&lt;u32&gt;,
      e: Option&lt;u32&gt;,
  }
  
  impl Kind {
      pub fn get_circle(&amp;self) -&gt; Option&lt;&amp;Circle&gt; {
          if let Kind::Circle(b) = self {
              return Some(b);
          }
          None
      }
  }
  </code></pre>
  
  <p><strong>benches/test.rs</strong></p>
  
  <pre><code>#![feature(test)]
  extern crate test;
  
  #[cfg(test)]
  mod tests {
      use std::collections::HashMap;
      use std::net::{IpAddr, Ipv4Addr, SocketAddr};
      use test::Bencher;
      use testing::Circle;
      use testing::Kind;
      use testing::Square;
  
      fn get_bencher() -&gt; HashMap&lt;SocketAddr, Kind&gt; {
          let mut question = HashMap::new();
          let square: Square = Default::default();
          question.insert(
              SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0),
              Kind::Square(square),
          );
  
          let circle: Circle = Default::default();
          for n in 1..=10000 {
              let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), n);
              question.insert(socket, Kind::Circle(circle));
          }
          question
      }
  
      #[bench]
      fn bencher01(b: &amp;mut Bencher) {
          let question = get_bencher();
  
          b.iter(|| {
              question
                  .iter()
                  .map(|a| (a.0, a.1.get_circle()))
                  .filter_map(|(&amp;a, b)| Some((a, b?)))
                  .collect::&lt;Vec&lt;_&gt;&gt;()
          })
      }
  
      #[bench]
      fn bencher02(b: &amp;mut Bencher) {
          let question = get_bencher();
  
          b.iter(|| {
              question
                  .iter()
                  .map(|a| (a.0, a.1.get_circle()))
                  .filter(|c| c.1.is_some())
                  .map(|d| (*d.0, d.1.unwrap()))
                  .collect::&lt;Vec&lt;_&gt;&gt;()
          })
      }
  
      #[bench]
      fn bencher03(b: &amp;mut Bencher) {
          let question = get_bencher();
  
          b.iter(|| {
              question
                  .iter()
                  .filter_map(|a| Some((*a.0, a.1.get_circle()?)))
                  .collect::&lt;Vec&lt;_&gt;&gt;()
          })
      }
  }
  </code></pre>
  
  <p>Run these tests using Rust nightly and <code>cargo bench</code> which forces release mode.</p>
  
  <p><strong>output</strong></p>
  
  <pre class="lang-none prettyprint-override"><code>running 3 tests
  test tests::bencher01 ... bench:     201,978 ns/iter (+/- 12,787)
  test tests::bencher02 ... bench:      89,004 ns/iter (+/- 6,204)
  test tests::bencher03 ... bench:     238,569 ns/iter (+/- 6,004)
  </code></pre>
  
  <p>I'm using <code>rustc 1.44.0-nightly (6dee5f112 2020-04-06)</code> on <code>Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz Linux #### 5.6.4-arch1-1 #1 SMP PREEMPT Mon, 13 Apr 2020 12:21:19 +0000 x86_64 GNU/Linux</code></p>