diff options
author | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
---|---|---|
committer | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
commit | 178c3e135a2a249692f7784712492e7884ae0c00 (patch) | |
tree | ac6b769dbf7162150caa0c1624786a4dd79ff3be /crates/profile/src/lib.rs | |
parent | 06ff8e6c760ff05f10e868b5d1f9d79e42fbb49c (diff) | |
parent | c2594daf2974dbd4ce3d9b7ec72481764abaceb5 (diff) |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'crates/profile/src/lib.rs')
-rw-r--r-- | crates/profile/src/lib.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs new file mode 100644 index 000000000..ab19271c7 --- /dev/null +++ b/crates/profile/src/lib.rs | |||
@@ -0,0 +1,109 @@ | |||
1 | //! A collection of tools for profiling rust-analyzer. | ||
2 | |||
3 | mod stop_watch; | ||
4 | mod memory_usage; | ||
5 | #[cfg(feature = "cpu_profiler")] | ||
6 | mod google_cpu_profiler; | ||
7 | mod hprof; | ||
8 | mod tree; | ||
9 | |||
10 | use std::cell::RefCell; | ||
11 | |||
12 | pub use crate::{ | ||
13 | hprof::{init, init_from, span}, | ||
14 | memory_usage::{Bytes, MemoryUsage}, | ||
15 | stop_watch::{StopWatch, StopWatchSpan}, | ||
16 | }; | ||
17 | |||
18 | /// Prints backtrace to stderr, useful for debugging. | ||
19 | #[cfg(feature = "backtrace")] | ||
20 | pub fn print_backtrace() { | ||
21 | let bt = backtrace::Backtrace::new(); | ||
22 | eprintln!("{:?}", bt); | ||
23 | } | ||
24 | #[cfg(not(feature = "backtrace"))] | ||
25 | pub fn print_backtrace() { | ||
26 | eprintln!( | ||
27 | r#"enable the backtrace feature: | ||
28 | profile = {{ path = "../profile", features = [ "backtrace"] }} | ||
29 | "# | ||
30 | ); | ||
31 | } | ||
32 | |||
33 | thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false)); | ||
34 | |||
35 | /// Allows to check if the current code is withing some dynamic scope, can be | ||
36 | /// useful during debugging to figure out why a function is called. | ||
37 | pub struct Scope { | ||
38 | prev: bool, | ||
39 | } | ||
40 | |||
41 | impl Scope { | ||
42 | #[must_use] | ||
43 | pub fn enter() -> Scope { | ||
44 | let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true)); | ||
45 | Scope { prev } | ||
46 | } | ||
47 | pub fn is_active() -> bool { | ||
48 | IN_SCOPE.with(|slot| *slot.borrow()) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl Drop for Scope { | ||
53 | fn drop(&mut self) { | ||
54 | IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | /// A wrapper around google_cpu_profiler. | ||
59 | /// | ||
60 | /// Usage: | ||
61 | /// 1. Install gpref_tools (https://github.com/gperftools/gperftools), probably packaged with your Linux distro. | ||
62 | /// 2. Build with `cpu_profiler` feature. | ||
63 | /// 3. Tun the code, the *raw* output would be in the `./out.profile` file. | ||
64 | /// 4. Install pprof for visualization (https://github.com/google/pprof). | ||
65 | /// 5. Bump sampling frequency to once per ms: `export CPUPROFILE_FREQUENCY=1000` | ||
66 | /// 6. Use something like `pprof -svg target/release/rust-analyzer ./out.profile` to see the results. | ||
67 | /// | ||
68 | /// For example, here's how I run profiling on NixOS: | ||
69 | /// | ||
70 | /// ```bash | ||
71 | /// $ nix-shell -p gperftools --run \ | ||
72 | /// 'cargo run --release -p rust-analyzer -- parse < ~/projects/rustbench/parser.rs > /dev/null' | ||
73 | /// ``` | ||
74 | /// | ||
75 | /// See this diff for how to profile completions: | ||
76 | /// | ||
77 | /// https://github.com/rust-analyzer/rust-analyzer/pull/5306 | ||
78 | #[derive(Debug)] | ||
79 | pub struct CpuSpan { | ||
80 | _private: (), | ||
81 | } | ||
82 | |||
83 | #[must_use] | ||
84 | pub fn cpu_span() -> CpuSpan { | ||
85 | #[cfg(feature = "cpu_profiler")] | ||
86 | { | ||
87 | google_cpu_profiler::start("./out.profile".as_ref()) | ||
88 | } | ||
89 | |||
90 | #[cfg(not(feature = "cpu_profiler"))] | ||
91 | { | ||
92 | eprintln!("cpu_profiler feature is disabled") | ||
93 | } | ||
94 | |||
95 | CpuSpan { _private: () } | ||
96 | } | ||
97 | |||
98 | impl Drop for CpuSpan { | ||
99 | fn drop(&mut self) { | ||
100 | #[cfg(feature = "cpu_profiler")] | ||
101 | { | ||
102 | google_cpu_profiler::stop() | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | pub fn memory_usage() -> MemoryUsage { | ||
108 | MemoryUsage::current() | ||
109 | } | ||