diff --git a/Cargo.lock b/Cargo.lock index a24c27144fee39f15b6ca4f46d79cef6ac46656b..cc72d569f421cd1a97051538e75deded357e8ea2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20315,6 +20315,7 @@ dependencies = [ "url", "urlencoding", "util", + "util_macros", "uuid", "vim", "vim_mode_setting", diff --git a/crates/util/src/paths.rs b/crates/util/src/paths.rs index 18b8a9ccb0628834b664dfaf2aec622e476cb4ff..085b8b74cb67baf6082fd648a80cb12da9c561ee 100644 --- a/crates/util/src/paths.rs +++ b/crates/util/src/paths.rs @@ -858,8 +858,9 @@ pub fn compare_paths( #[cfg(test)] mod tests { use super::*; + use util_macros::perf; - #[test] + #[perf] fn compare_paths_with_dots() { let mut paths = vec![ (Path::new("test_dirs"), false), @@ -897,7 +898,7 @@ mod tests { ); } - #[test] + #[perf] fn compare_paths_with_same_name_different_extensions() { let mut paths = vec![ (Path::new("test_dirs/file.rs"), true), @@ -919,7 +920,7 @@ mod tests { ); } - #[test] + #[perf] fn compare_paths_case_semi_sensitive() { let mut paths = vec![ (Path::new("test_DIRS"), false), @@ -951,7 +952,7 @@ mod tests { ); } - #[test] + #[perf] fn path_with_position_parse_posix_path() { // Test POSIX filename edge cases // Read more at https://en.wikipedia.org/wiki/Filename @@ -1038,7 +1039,7 @@ mod tests { ); } - #[test] + #[perf] #[cfg(not(target_os = "windows"))] fn path_with_position_parse_posix_path_with_suffix() { assert_eq!( @@ -1094,7 +1095,7 @@ mod tests { ); } - #[test] + #[perf] #[cfg(target_os = "windows")] fn path_with_position_parse_windows_path() { assert_eq!( @@ -1116,7 +1117,7 @@ mod tests { ); } - #[test] + #[perf] #[cfg(target_os = "windows")] fn path_with_position_parse_windows_path_with_suffix() { assert_eq!( @@ -1229,7 +1230,7 @@ mod tests { ); } - #[test] + #[perf] fn test_path_compact() { let path: PathBuf = [ home_dir().to_string_lossy().to_string(), @@ -1244,7 +1245,7 @@ mod tests { } } - #[test] + #[perf] fn test_extension_or_hidden_file_name() { // No dots in name let path = Path::new("/a/b/c/file_name.rs"); @@ -1267,7 +1268,7 @@ mod tests { assert_eq!(path.extension_or_hidden_file_name(), Some("eslintrc.js")); } - #[test] + #[perf] fn edge_of_glob() { let path = Path::new("/work/node_modules"); let path_matcher = @@ -1278,7 +1279,7 @@ mod tests { ); } - #[test] + #[perf] fn project_search() { let path = Path::new("/Users/someonetoignore/work/zed/zed.dev/node_modules"); let path_matcher = @@ -1289,7 +1290,7 @@ mod tests { ); } - #[test] + #[perf] #[cfg(target_os = "windows")] fn test_sanitized_path() { let path = Path::new("C:\\Users\\someone\\test_file.rs"); @@ -1307,7 +1308,7 @@ mod tests { ); } - #[test] + #[perf] fn test_compare_numeric_segments() { // Helper function to create peekable iterators and test fn compare(a: &str, b: &str) -> Ordering { @@ -1375,7 +1376,7 @@ mod tests { assert_eq!(b_iter.collect::(), "def"); } - #[test] + #[perf] fn test_natural_sort() { // Basic alphanumeric assert_eq!(natural_sort("a", "b"), Ordering::Less); @@ -1429,7 +1430,7 @@ mod tests { assert_eq!(natural_sort("File_a1", "File_A1"), Ordering::Less); } - #[test] + #[perf] fn test_compare_paths() { // Helper function for cleaner tests fn compare(a: &str, is_a_file: bool, b: &str, is_b_file: bool) -> Ordering { @@ -1515,8 +1516,9 @@ mod tests { ); } - #[test] + #[perf] fn test_natural_sort_case_sensitivity() { + std::thread::sleep(std::time::Duration::from_millis(100)); // Same letter different case - lowercase should come first assert_eq!(natural_sort("a", "A"), Ordering::Less); assert_eq!(natural_sort("A", "a"), Ordering::Greater); @@ -1534,7 +1536,7 @@ mod tests { assert_eq!(natural_sort("a", "B"), Ordering::Less); } - #[test] + #[perf] fn test_natural_sort_with_numbers() { // Basic number ordering assert_eq!(natural_sort("file1", "file2"), Ordering::Less); @@ -1612,7 +1614,7 @@ mod tests { assert_eq!(natural_sort("file1", "File2"), Ordering::Less); } - #[test] + #[perf] fn test_natural_sort_edge_cases() { // Empty strings assert_eq!(natural_sort("", ""), Ordering::Equal); diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index c550669479e204e15e6647bb211743e17acfc89d..df1445c24cb8354847b2dc72e7bc201065be8a51 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -189,6 +189,7 @@ project = { workspace = true, features = ["test-support"] } terminal_view = { workspace = true, features = ["test-support"] } tree-sitter-md.workspace = true tree-sitter-rust.workspace = true +util_macros.workspace = true workspace = { workspace = true, features = ["test-support"] } [package.metadata.bundle-dev] diff --git a/docs/src/development.md b/docs/src/development.md index 046d515fede061160eff9c4a4bcb7cd1cd63b09e..6cb5f0b8271ab0347d33ee0cf634b60e790f3ba0 100644 --- a/docs/src/development.md +++ b/docs/src/development.md @@ -79,6 +79,12 @@ Here's a typical workflow for comparing frame rendering performance between diff The `script/histogram` tool can accept as many measurement files as you like and will generate a histogram visualization comparing the frame rendering performance data between the provided versions. +### Using `util_macros::perf` + +For benchmarking unit tests, annotate them with the `#[perf]` attribute from the `util_macros` crate. Then run `cargo +perf-test -p $CRATE` to benchmark them. See the rustdoc documentation on `crates/util_macros` and `tooling/perf` for +in-depth examples and explanations. + ## Contributor links - [CONTRIBUTING.md](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md) diff --git a/tooling/perf/src/lib.rs b/tooling/perf/src/lib.rs index c6d620aaeb45064231fea0baaae02b7b0185e3d5..639e1afde34a69b9d4f4bbca0713e973d80edec2 100644 --- a/tooling/perf/src/lib.rs +++ b/tooling/perf/src/lib.rs @@ -1,5 +1,7 @@ //! Some constants and datatypes used in the Zed perf profiler. Should only be //! consumed by the crate providing the matching macros. +//! +//! For usage documentation, see the docs on this crate's binary. use collections::HashMap; use serde::{Deserialize, Serialize}; @@ -274,7 +276,7 @@ impl Output { continue; }; let shift = - (s_timings.iters_per_sec(s_iters) / o_timings.iters_per_sec(o_iters)) - 1.; + (o_timings.iters_per_sec(o_iters) / s_timings.iters_per_sec(s_iters)) - 1.; if shift > max { max = shift; } diff --git a/tooling/perf/src/main.rs b/tooling/perf/src/main.rs index d5be1a9d8a32980cf42cd08f8810ca9aa4ff2631..a9f932d4fa18b712c9f277a80c2370ecceb4b1a3 100644 --- a/tooling/perf/src/main.rs +++ b/tooling/perf/src/main.rs @@ -218,7 +218,10 @@ fn compare_profiles(args: &[String]) { let ident_new = args.first().expect("FATAL: missing identifier for new run"); let ident_old = args.get(1).expect("FATAL: missing identifier for old run"); let wspace_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let runs_dir = PathBuf::from(&wspace_dir).join(consts::RUNS_DIR); + let runs_dir = PathBuf::from(&wspace_dir) + .join("..") + .join("..") + .join(consts::RUNS_DIR); // Use the blank outputs initially, so we can merge into these with prefixes. let mut outputs_new = Output::blank();