diff --git a/CHANGELOG.md b/CHANGELOG.md index c11df4f88..8021fac9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ ## Unreleased Changes * Improved the visualization for array properties like Tags ([#829]) +* Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. [#830] [#829]: https://github.com/rojo-rbx/rojo/pull/829 +[#830]: https://github.com/rojo-rbx/rojo/pull/830 ## [7.4.0-rc3] - October 25, 2023 * Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) @@ -141,7 +143,6 @@ * Add buttons for navigation on the Connected page ([#722]) ### Fixes -* Significantly improved performance of `rojo serve` and `rojo build` on macOS. [#783] * Significantly improved performance of `rojo sourcemap` ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) @@ -175,7 +176,6 @@ [#770]: https://github.com/rojo-rbx/rojo/pull/770 [#771]: https://github.com/rojo-rbx/rojo/pull/771 [#774]: https://github.com/rojo-rbx/rojo/pull/774 -[#783]: https://github.com/rojo-rbx/rojo/pull/783 [rbx-dom#299]: https://github.com/rojo-rbx/rbx-dom/pull/299 [rbx-dom#296]: https://github.com/rojo-rbx/rbx-dom/pull/296 diff --git a/Cargo.lock b/Cargo.lock index 87b5111b4..d0565dc16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -424,7 +424,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -549,15 +549,41 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags 1.3.2", + "fsevent-sys", +] + [[package]] name = "fsevent-sys" -version = "4.1.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" dependencies = [ "libc", ] +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.3.28" @@ -857,9 +883,9 @@ dependencies = [ [[package]] name = "inotify" -version = "0.9.6" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" dependencies = [ "bitflags 1.3.2", "inotify-sys", @@ -891,6 +917,15 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "ipnet" version = "2.8.0" @@ -928,23 +963,13 @@ dependencies = [ ] [[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" +name = "kernel32-sys" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "bitflags 1.3.2", - "libc", + "winapi 0.2.8", + "winapi-build", ] [[package]] @@ -953,6 +978,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.148" @@ -1065,6 +1096,25 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.8.8" @@ -1072,11 +1122,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.48.0", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -1095,23 +1168,33 @@ dependencies = [ "tempfile", ] +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "notify" -version = "6.1.1" +version = "4.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" dependencies = [ - "bitflags 2.4.0", - "crossbeam-channel", + "bitflags 1.3.2", "filetime", + "fsevent", "fsevent-sys", "inotify", - "kqueue", "libc", - "log", - "mio", + "mio 0.6.23", + "mio-extras", "walkdir", - "windows-sys 0.48.0", + "winapi 0.3.9", ] [[package]] @@ -1121,7 +1204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1171,7 +1254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" dependencies = [ "bstr", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2028,7 +2111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2191,7 +2274,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio", + "mio 0.8.8", "num_cpus", "pin-project-lite", "socket2 0.5.4", @@ -2550,6 +2633,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -2560,6 +2649,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2572,7 +2667,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2728,7 +2823,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2737,7 +2832,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2750,6 +2845,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "xml-rs" version = "0.8.19" diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index 43516260b..c9961d0ed 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -1,7 +1,9 @@ # memofs Changelog ## Unreleased Changes -* Changed the `StdBackend` file watcher to use `PollWatcher` on macOS. +* Changed `StdBackend` file watching component to use minimal recursive watches. [#830] + +[#830]: https://github.com/rojo-rbx/rojo/pull/830 ## 0.2.0 (2021-08-23) * Updated to `crossbeam-channel` 0.5.1. diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index b60a30381..5cf5a7334 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -13,5 +13,5 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" [dependencies] crossbeam-channel = "0.5.1" fs-err = "2.3.0" -notify = "6.1.1" +notify = "4.0.15" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index 4e95f110b..0a8fb3b79 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -1,68 +1,55 @@ -use std::io; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::sync::mpsc; +use std::thread; +use std::time::Duration; +use std::{collections::HashSet, io}; use crossbeam_channel::Receiver; - -use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; - -#[cfg(target_os = "macos")] -use notify::{Config, PollWatcher}; - -#[cfg(target_os = "macos")] -use std::time::Duration; +use notify::{watcher, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent}; /// `VfsBackend` that uses `std::fs` and the `notify` crate. pub struct StdBackend { - #[cfg(target_os = "macos")] - watcher: PollWatcher, - - #[cfg(not(target_os = "macos"))] watcher: RecommendedWatcher, - watcher_receiver: Receiver, + watches: HashSet, } impl StdBackend { pub fn new() -> StdBackend { + let (notify_tx, notify_rx) = mpsc::channel(); + let watcher = watcher(notify_tx, Duration::from_millis(50)).unwrap(); + let (tx, rx) = crossbeam_channel::unbounded(); - let event_handler = move |res: Result| match res { - Ok(event) => match event.kind { - EventKind::Create(_) => { - for path in event.paths { - let _ = tx.send(VfsEvent::Create(path)); + thread::spawn(move || { + for event in notify_rx { + match event { + DebouncedEvent::Create(path) => { + tx.send(VfsEvent::Create(path))?; } - } - EventKind::Modify(_) => { - for path in event.paths { - let _ = tx.send(VfsEvent::Write(path)); + DebouncedEvent::Write(path) => { + tx.send(VfsEvent::Write(path))?; } - } - EventKind::Remove(_) => { - for path in event.paths { - let _ = tx.send(VfsEvent::Remove(path)); + DebouncedEvent::Remove(path) => { + tx.send(VfsEvent::Remove(path))?; } + DebouncedEvent::Rename(from, to) => { + tx.send(VfsEvent::Remove(from))?; + tx.send(VfsEvent::Create(to))?; + } + _ => {} } - _ => {} - }, - Err(e) => println!("watch error: {:?}", e), - }; - - #[cfg(not(target_os = "macos"))] - let watcher = notify::recommended_watcher(event_handler).unwrap(); + } - #[cfg(target_os = "macos")] - let watcher = PollWatcher::new( - event_handler, - Config::default().with_poll_interval(Duration::from_millis(200)), - ) - .unwrap(); + Result::<(), crossbeam_channel::SendError>::Ok(()) + }); Self { watcher, watcher_receiver: rx, + watches: HashSet::new(), } } } @@ -112,12 +99,22 @@ impl VfsBackend for StdBackend { } fn watch(&mut self, path: &Path) -> io::Result<()> { - self.watcher - .watch(path, RecursiveMode::NonRecursive) - .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) + if self.watches.contains(path) + || path + .ancestors() + .any(|ancestor| self.watches.contains(ancestor)) + { + Ok(()) + } else { + self.watches.insert(path.to_path_buf()); + self.watcher + .watch(path, RecursiveMode::Recursive) + .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) + } } fn unwatch(&mut self, path: &Path) -> io::Result<()> { + self.watches.remove(path); self.watcher .unwatch(path) .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner))