From 3df5edb75f8e579f1f4a97795f116d82d3e3b49c Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 21 Jan 2019 05:55:09 -0800 Subject: Fix inefficient interop in OSX FileSystemWatcher (#34715) * Fix inefficient interop in OSX FileSystemWatcher Avoid unnecessary array allocations in the FileSystemWatcher callback * Add using for FSEventStreamEventFlags --- src/Common/src/Interop/OSX/Interop.EventStream.cs | 6 ++-- .../src/System/IO/FileSystemWatcher.OSX.cs | 36 ++++++++++------------ 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/Common/src/Interop/OSX/Interop.EventStream.cs b/src/Common/src/Interop/OSX/Interop.EventStream.cs index 7c6e93c761..19e9f5cb62 100644 --- a/src/Common/src/Interop/OSX/Interop.EventStream.cs +++ b/src/Common/src/Interop/OSX/Interop.EventStream.cs @@ -88,10 +88,8 @@ internal static partial class Interop size_t numEvents, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte** eventPaths, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - FSEventStreamEventFlags[] eventFlags, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - FSEventStreamEventId[] eventIds); + FSEventStreamEventFlags* eventFlags, + FSEventStreamEventId* eventIds); /// /// Internal wrapper to create a new EventStream to listen to events from the core OS (such as File System events). diff --git a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs index b13f1ba632..1165464901 100644 --- a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs +++ b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs @@ -96,9 +96,9 @@ namespace System.IO // Always re-create the filter flags when start is called since they could have changed if ((flagsToTranslate & (NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Size)) != 0) { - flags = FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | + flags = FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | FSEventStreamEventFlags.kFSEventStreamEventFlagItemFinderInfoMod | - FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | + FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner; } if ((flagsToTranslate & NotifyFilters.Security) != 0) @@ -366,13 +366,9 @@ namespace System.IO IntPtr clientCallBackInfo, size_t numEvents, byte** eventPaths, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - Interop.EventStream.FSEventStreamEventFlags[] eventFlags, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - FSEventStreamEventId[] eventIds) + FSEventStreamEventFlags* eventFlags, + FSEventStreamEventId* eventIds) { - Debug.Assert((eventPaths != null) && (numEvents.ToInt32() == eventFlags.Length) && (numEvents.ToInt32() == eventIds.Length)); - // Try to get the actual watcher from our weak reference. We maintain a weak reference most of the time // so as to avoid a rooted cycle that would prevent our processing loop from ever ending // if the watcher is dropped by the user without being disposed. If we can't get the watcher, @@ -549,13 +545,13 @@ namespace System.IO /// Compares the given event flags to the filter flags and returns which event (if any) corresponds /// to those flags. /// - private WatcherChangeTypes FilterEvents(Interop.EventStream.FSEventStreamEventFlags eventFlags) + private WatcherChangeTypes FilterEvents(FSEventStreamEventFlags eventFlags) { - const Interop.EventStream.FSEventStreamEventFlags changedFlags = Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | - Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemFinderInfoMod | - Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | - Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner | - Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemXattrMod; + const FSEventStreamEventFlags changedFlags = FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | + FSEventStreamEventFlags.kFSEventStreamEventFlagItemFinderInfoMod | + FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | + FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner | + FSEventStreamEventFlags.kFSEventStreamEventFlagItemXattrMod; WatcherChangeTypes eventType = 0; // If any of the Changed flags are set in both Filter and Event then a Changed event has occurred. if (((_filterFlags & changedFlags) & (eventFlags & changedFlags)) > 0) @@ -564,12 +560,12 @@ namespace System.IO } // Notify created/deleted/renamed events if they pass through the filters - bool allowDirs = (_filterFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; - bool allowFiles = (_filterFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; - bool isDir = (eventFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; - bool isFile = (eventFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; + bool allowDirs = (_filterFlags & FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; + bool allowFiles = (_filterFlags & FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; + bool isDir = (eventFlags & FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; + bool isFile = (eventFlags & FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; bool eventIsCorrectType = (isDir && allowDirs) || (isFile && allowFiles); - bool eventIsLink = (eventFlags & (Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsHardlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsSymlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsLastHardlink)) > 0; + bool eventIsLink = (eventFlags & (FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsHardlink | FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsSymlink | FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsLastHardlink)) > 0; if (eventIsCorrectType || ((allowDirs || allowFiles) && (eventIsLink))) { @@ -590,7 +586,7 @@ namespace System.IO return eventType; } - private bool ShouldRescanOccur(Interop.EventStream.FSEventStreamEventFlags flags) + private bool ShouldRescanOccur(FSEventStreamEventFlags flags) { // Check if any bit is set that signals that the caller should rescan return (flags.HasFlag(FSEventStreamEventFlags.kFSEventStreamEventFlagMustScanSubDirs) || -- cgit v1.2.3