diff --git a/.gitignore b/.gitignore index 47c1a2ea..715365c3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /release .DS_Store /.idea/ +flamegraph.svg diff --git a/Cargo.lock b/Cargo.lock index f1fa07ed..8e52222e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,24 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" +[[package]] +name = "ahash" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" +dependencies = [ + "const-random", +] + +[[package]] +name = "aho-corasick" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.31" @@ -33,6 +51,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.5.1" @@ -98,7 +125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.5.1", "constant_time_eq", ] @@ -160,12 +187,42 @@ dependencies = [ "bitflags", ] +[[package]] +name = "const-random" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" +dependencies = [ + "getrandom", + "proc-macro-hack", +] + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "cpp_demangle" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c924384107361ca729c7d46b9134151b9a955ce99a773784f2777498e8552d" +dependencies = [ + "cfg-if", + "glob", +] + [[package]] name = "crossbeam-channel" version = "0.4.2" @@ -249,6 +306,17 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "debugid" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "751dad1347b163aa77262232129c7ac46e2810485c9b095ac9f7caf200e97df4" +dependencies = [ + "lazy_static", + "regex", + "uuid", +] + [[package]] name = "dirs" version = "2.0.2" @@ -276,6 +344,28 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -338,6 +428,7 @@ dependencies = [ "dirs", "itertools", "log", + "pprof", "rayon-core", "ron", "scopeguard", @@ -348,6 +439,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "hermit-abi" version = "0.1.14" @@ -368,6 +465,32 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe" +dependencies = [ + "autocfg", +] + +[[package]] +name = "inferno" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2a71c56e4c218f2a1d36bc5177cbfdedf89697ac68610ac3c8452cde152231" +dependencies = [ + "ahash", + "indexmap", + "itoa", + "lazy_static", + "log", + "num-format", + "quick-xml", + "rgb", + "str_stack", +] + [[package]] name = "invalidstring" version = "0.1.1" @@ -390,6 +513,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" + [[package]] name = "jobserver" version = "0.1.21" @@ -475,6 +604,22 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +dependencies = [ + "libc", + "winapi 0.3.8", +] + [[package]] name = "memoffset" version = "0.5.4" @@ -524,6 +669,15 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "msvc-demangler" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f23411283f2b097d677da1ae95f7af5ddadd7a2317b97ed0e9dfb2cea548f93" +dependencies = [ + "bitflags", +] + [[package]] name = "net2" version = "0.2.34" @@ -535,6 +689,35 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "nix" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0eaf8df8bab402257e0a5c17a254e4cc1f72a93588a1ddfb5d356c801aa7cb" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "void", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-format" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +dependencies = [ + "arrayvec 0.4.12", + "itoa", +] + [[package]] name = "num-integer" version = "0.1.43" @@ -606,12 +789,36 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +[[package]] +name = "pprof" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1181b929c0495374e521f7a642d8e64a0eee09dd66075d29ef7c28246861c9a" +dependencies = [ + "backtrace", + "inferno", + "lazy_static", + "libc", + "log", + "nix", + "spin", + "symbolic-demangle", + "tempfile", + "thiserror", +] + [[package]] name = "ppv-lite86" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +[[package]] +name = "proc-macro-hack" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" + [[package]] name = "proc-macro2" version = "1.0.18" @@ -621,6 +828,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "quick-xml" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cc440ee4802a86e357165021e3e255a9143724da31db1e2ea540214c96a0f82" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.7" @@ -701,6 +917,24 @@ dependencies = [ "rust-argon2", ] +[[package]] +name = "regex" +version = "1.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -710,6 +944,12 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "rgb" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6714061b32e0b0527005d5874c28a57d905559fecfacd361462ad0b01e701996" + [[package]] name = "ron" version = "0.6.0" @@ -815,6 +1055,50 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" + +[[package]] +name = "str_stack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" + +[[package]] +name = "symbolic-common" +version = "6.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6408c8d87fe1aea5f3321c03b6e4114d0fea0900b13358e67c65298c55fc099d" +dependencies = [ + "debugid", + "failure", + "memmap", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "6.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1bf750b22444e2045f2586433629009b3d5f8abfa8d19fe38234068935f06f" +dependencies = [ + "cc", + "cpp_demangle", + "msvc-demangler", + "rustc-demangle", + "symbolic-common", +] + [[package]] name = "syn" version = "1.0.33" @@ -826,6 +1110,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.1.0" @@ -869,6 +1165,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + [[package]] name = "time" version = "0.1.43" @@ -947,12 +1252,24 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" + [[package]] name = "vcpkg" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 4e077469..f785125d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ ron = "0.6" serde = "1.0" anyhow = "1.0.31" unicode-width = "0.1" +pprof = { version = "0.3", features = ["flamegraph"], optional = true } [badges] maintenance = { status = "actively-developed" } diff --git a/Makefile b/Makefile index 1da266d6..86d70164 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ .PHONY: debug build-release release-linux-musl test clippy clippy-pedantic install install-debug +profile: + cargo run --features=timing,pprof -- -l + debug: cargo run --features=timing -- -l diff --git a/src/main.rs b/src/main.rs index a971da89..dce02997 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ mod components; mod input; mod keys; mod notify_mutex; +mod profiler; mod queue; mod spinner; mod strings; @@ -39,6 +40,7 @@ use crossterm::{ ExecutableCommand, }; use input::{Input, InputEvent}; +use profiler::Profiler; use scopeguard::defer; use scopetime::scope_time; use simplelog::{Config, LevelFilter, WriteLogger}; @@ -72,6 +74,8 @@ pub enum QueueEvent { fn main() -> Result<()> { process_cmdline()?; + let _profiler = Profiler::new(); + if !valid_path()? { eprintln!("invalid path\nplease run gitui inside of a non-bare git repository"); return Ok(()); diff --git a/src/profiler.rs b/src/profiler.rs new file mode 100644 index 00000000..60fbb150 --- /dev/null +++ b/src/profiler.rs @@ -0,0 +1,34 @@ +/// helper struct to not pollute main with feature flags shenanigans for the profiler +/// also we make sure to generate a flamegraph on program exit +pub struct Profiler { + #[cfg(feature = "pprof")] + guard: pprof::ProfilerGuard<'static>, +} + +impl Profiler { + pub fn new() -> Self { + Self { + #[cfg(feature = "pprof")] + guard: pprof::ProfilerGuard::new(100) + .expect("profiler launch error"), + } + } + + fn report(&mut self) { + #[cfg(feature = "pprof")] + if let Ok(report) = self.guard.report().build() { + let file = std::fs::File::create("flamegraph.svg") + .expect("flamegraph file err"); + + report.flamegraph(&file).expect("flamegraph write err"); + + log::info!("profiler reported"); + } + } +} + +impl Drop for Profiler { + fn drop(&mut self) { + self.report(); + } +}