From edb3badcb31646aac0ee4a51857ca9b3f2caae43 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 24 Apr 2026 23:47:22 +0200 Subject: [PATCH] Optimize content modifications watching events processing in large projects --- .../Editor/Modules/ContentDatabaseModule.cs | 26 ++++++++++++------- .../AssetsImportingManager.cpp | 8 ++++++ .../ShadersCompilation/ShadersCompilation.cpp | 2 ++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Source/Editor/Modules/ContentDatabaseModule.cs b/Source/Editor/Modules/ContentDatabaseModule.cs index 53075fe38..2331deeee 100644 --- a/Source/Editor/Modules/ContentDatabaseModule.cs +++ b/Source/Editor/Modules/ContentDatabaseModule.cs @@ -24,7 +24,7 @@ namespace FlaxEditor.Modules private bool _rebuildInitFlag; private int _itemsCreated; private int _itemsDeleted; - private readonly HashSet _dirtyNodes = new HashSet(); + private readonly HashSet _dirtyNodes = new HashSet(); /// /// The project directory. @@ -1309,26 +1309,31 @@ namespace FlaxEditor.Modules internal void OnDirectoryEvent(MainContentFolderTreeNode node, FileSystemEventArgs e) { - // Ensure to be ready for external events + // Ignore events during fast setup if (_isDuringFastSetup) return; + ContentFolderTreeNode dirtyNode = node; - // TODO: maybe we could make it faster! since we have a path so it would be easy to just create or delete given file. but remember about subdirectories + // Filter the node based on modified path + // (eg. if we have event for 'Content/Folder1/Folder2' and node is 'Content/Folder1' then we should process but skip other 'Content' subfolders) + var path = StringUtils.NormalizePath(Path.GetDirectoryName(e.FullPath)); + var pathItem = node.Folder.Find(path) as ContentFolder; + if (pathItem != null) + { + dirtyNode = pathItem.Node; + } - // Switch type switch (e.ChangeType) { case WatcherChangeTypes.Created: case WatcherChangeTypes.Deleted: case WatcherChangeTypes.Renamed: - { lock (_dirtyNodes) { - _dirtyNodes.Add(node); + _dirtyNodes.Add(dirtyNode); } break; } - } } private void OnScriptsReload() @@ -1383,14 +1388,15 @@ namespace FlaxEditor.Modules // Update all dirty content tree nodes lock (_dirtyNodes) { + Profiler.BeginEvent("ContentDatabase.Refresh"); foreach (var node in _dirtyNodes) { LoadFolder(node, true); - - if (_enableEvents) - WorkspaceModified?.Invoke(); } + if (_enableEvents && _dirtyNodes.Count != 0) + WorkspaceModified?.Invoke(); _dirtyNodes.Clear(); + Profiler.EndEvent(); } // Lazy-rebuilds diff --git a/Source/Engine/ContentImporters/AssetsImportingManager.cpp b/Source/Engine/ContentImporters/AssetsImportingManager.cpp index 696f43a9e..fb8d60771 100644 --- a/Source/Engine/ContentImporters/AssetsImportingManager.cpp +++ b/Source/Engine/ContentImporters/AssetsImportingManager.cpp @@ -113,6 +113,8 @@ CreateAssetContext::CreateAssetContext(const StringView& inputPath, const String CreateAssetResult CreateAssetContext::Run(const CreateAssetFunction& callback) { + PROFILE_CPU(); + PROFILE_MEM(Content); ASSERT(callback.IsBinded()); // Call action @@ -207,6 +209,9 @@ void CreateAssetContext::AddMeta(JsonWriter& writer) const void CreateAssetContext::ApplyChanges() { + PROFILE_CPU(); + PROFILE_MEM(Content); + // Get access auto storage = ContentStorageManager::TryGetStorage(TargetAssetPath); if (storage && storage->IsLoaded()) @@ -274,6 +279,8 @@ bool AssetsImportingManager::Create(const String& tag, const StringView& outputP bool AssetsImportingManager::Import(const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg) { + PROFILE_CPU(); + PROFILE_MEM(Content); LOG(Info, "Importing file '{0}' to '{1}'...", inputPath, outputPath); // Check if input file exists @@ -347,6 +354,7 @@ String AssetsImportingManager::GetImportPath(const String& path) bool AssetsImportingManager::Create(const Function& callback, const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg) { PROFILE_CPU(); + PROFILE_MEM(Content); ZoneText(*outputPath, outputPath.Length()); const auto startTime = Platform::GetTimeSeconds(); diff --git a/Source/Engine/ShadersCompilation/ShadersCompilation.cpp b/Source/Engine/ShadersCompilation/ShadersCompilation.cpp index c8f68f007..f89f38f9f 100644 --- a/Source/Engine/ShadersCompilation/ShadersCompilation.cpp +++ b/Source/Engine/ShadersCompilation/ShadersCompilation.cpp @@ -310,6 +310,7 @@ namespace { if (action == FileSystemAction::Delete) return; + PROFILE_CPU(); // Get list of assets using this shader file Array toReload; @@ -515,6 +516,7 @@ namespace { if (action == FileSystemAction::Delete || !path.EndsWith(TEXT(".shader"))) return; + PROFILE_CPU(); LOG(Info, "Shader \'{0}\' has been modified.", path);