diff --git a/Cargo.lock b/Cargo.lock
index 60b6da8eb94..55afcda7bf5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -948,6 +948,7 @@ dependencies = [
  "ra_hir_def 0.1.0",
  "ra_hir_expand 0.1.0",
  "ra_hir_ty 0.1.0",
+ "ra_prof 0.1.0",
  "ra_syntax 0.1.0",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 6ca9cc2e7de..7dc31ad3cbd 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -14,6 +14,7 @@ either = "1.5"
 
 ra_syntax = { path = "../ra_syntax" }
 ra_db = { path = "../ra_db" }
+ra_prof = { path = "../ra_prof" }
 hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" }
 hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
 hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 42ca55fe727..ebd9ee2a8e7 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -7,6 +7,7 @@ use hir_def::{
     StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
 };
 use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
+use ra_prof::profile;
 use ra_syntax::{
     ast::{self, AstNode, NameOwner},
     match_ast, SyntaxNode,
@@ -169,6 +170,7 @@ impl TypeParam {
 
 impl Module {
     pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> {
+        let _p = profile("Module::from_declaration");
         let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);
 
         let parent_module = match parent_declaration {
@@ -191,6 +193,7 @@ impl Module {
     }
 
     pub fn from_definition(db: &impl DefDatabase, src: InFile<ModuleSource>) -> Option<Self> {
+        let _p = profile("Module::from_definition");
         match src.value {
             ModuleSource::Module(ref module) => {
                 assert!(!module.has_semi());
@@ -214,6 +217,7 @@ impl Module {
 }
 
 fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap {
+    let _p = profile("analyze_container");
     return child_by_source(db, src).unwrap_or_default();
 
     fn child_by_source(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<DynMap> {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index b60a6b87e46..85b378483c6 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -26,6 +26,7 @@ use hir_ty::{
     method_resolution::{self, implements_trait},
     Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty,
 };
+use ra_prof::profile;
 use ra_syntax::{
     ast::{self, AstNode},
     match_ast, AstPtr,
@@ -83,6 +84,7 @@ fn def_with_body_from_child_node(
     db: &impl HirDatabase,
     child: InFile<&SyntaxNode>,
 ) -> Option<DefWithBody> {
+    let _p = profile("def_with_body_from_child_node");
     child.cloned().ancestors_with_macros(db).find_map(|node| {
         let n = &node.value;
         match_ast! {
@@ -169,6 +171,7 @@ impl SourceAnalyzer {
         node: InFile<&SyntaxNode>,
         offset: Option<TextUnit>,
     ) -> SourceAnalyzer {
+        let _p = profile("SourceAnalyzer::new");
         let def_with_body = def_with_body_from_child_node(db, node);
         if let Some(def) = def_with_body {
             let (_body, source_map) = db.body_with_source_map(def.into());
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 445d215b7b3..148ff007edc 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -11,6 +11,7 @@ use hir_expand::{
     ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
 };
 use ra_arena::{map::ArenaMap, Arena};
+use ra_prof::profile;
 use ra_syntax::{ast, AstNode, AstPtr};
 use rustc_hash::FxHashMap;
 
@@ -168,6 +169,7 @@ impl Body {
         db: &impl DefDatabase,
         def: DefWithBodyId,
     ) -> (Arc<Body>, Arc<BodySourceMap>) {
+        let _p = profile("body_with_source_map_query");
         let mut params = None;
 
         let (file_id, module, body) = match def {
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 3154df45727..c5e40697739 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -1,12 +1,15 @@
 //! FIXME: write short doc here
 
-use crate::{db::RootDatabase, FileId};
 use hir::{HirDisplay, SourceAnalyzer};
+use once_cell::unsync::Lazy;
+use ra_prof::profile;
 use ra_syntax::{
     ast::{self, AstNode, TypeAscriptionOwner},
     match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange,
 };
 
+use crate::{db::RootDatabase, FileId};
+
 #[derive(Debug, PartialEq, Eq)]
 pub enum InlayKind {
     TypeHint,
@@ -27,7 +30,7 @@ pub(crate) fn inlay_hints(
 ) -> Vec<InlayHint> {
     file.syntax()
         .descendants()
-        .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default())
+        .flat_map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length))
         .flatten()
         .collect()
 }
@@ -38,7 +41,9 @@ fn get_inlay_hints(
     node: &SyntaxNode,
     max_inlay_hint_length: Option<usize>,
 ) -> Option<Vec<InlayHint>> {
-    let analyzer = SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None);
+    let _p = profile("get_inlay_hints");
+    let analyzer =
+        Lazy::new(|| SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None));
     match_ast! {
         match node {
             ast::LetStmt(it) => {