diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj index c344f47..7e31d43 100644 --- a/NavisworksTransportPlugin.csproj +++ b/NavisworksTransportPlugin.csproj @@ -272,7 +272,6 @@ - diff --git a/doc/design/2026/geometry3Sharp空间数据结构集成方案.md b/doc/design/2026/geometry3Sharp空间数据结构集成方案.md index 723489e..0ea0fc5 100644 --- a/doc/design/2026/geometry3Sharp空间数据结构集成方案.md +++ b/doc/design/2026/geometry3Sharp空间数据结构集成方案.md @@ -141,7 +141,7 @@ double WindingNumber(Point3d point); #### 应用场景 -**场景 1:优化 GetPotentialColliders()** +场景 1:优化 GetPotentialColliders()** 当前实现(线性遍历): @@ -176,7 +176,7 @@ var potentialColliders = sceneTree.FindNearestTriangles( - 优化后:O(log n) ≈ log₂(290) ≈ 8 次树节点遍历 - **加速比**:约 36 倍 -**场景 2:精确碰撞检测** +场景 2:精确碰撞检测** 替代简单包围盒检测,使用三角形级别的精确相交: @@ -205,7 +205,7 @@ tree.Build(BuildStrategy.TopDownMidpoint); #### 技术挑战 -**挑战 1:Navisworks Geometry → DMesh3 转换** +挑战 1:Navisworks Geometry → DMesh3 转换 Navisworks 的 `ModelItem` 不直接暴露三角网格,需要通过几何提取: @@ -266,7 +266,7 @@ List FindPointsInBox(AxisAlignedBox3d box); #### 应用场景 -**场景 1:加速动画碰撞检测** +场景 1:加速动画碰撞检测 当前问题: @@ -312,7 +312,7 @@ foreach (var obstacle in nearbyObstacles) - 优化后:每帧检测 5-15 个对象(仅邻近格子) - **加速比**:约 7-20 倍 -**场景 2:动态场景更新** +场景 2:动态场景更新 支持障碍物动态添加/移动: @@ -377,7 +377,7 @@ DistTriangle3Triangle3 // 三角形到三角形的距离 #### 应用场景 -**场景 1:精确碰撞容差** +场景 1:精确碰撞容差 当前问题: @@ -412,7 +412,7 @@ foreach (var triangle1 in animatedObjectMesh.Triangles) } ``` -**场景 2:碰撞报告增强** +场景 2:碰撞报告增强 在碰撞报告中显示: @@ -454,7 +454,7 @@ IntrRay3AxisAlignedBox3 // 射线-轴对齐盒相交 #### 应用场景 -**场景 1:路径可达性验证** +场景 1:路径可达性验证 检查两点间的直线路径是否被障碍物阻挡: @@ -487,7 +487,7 @@ public bool IsPathClear(Point3D start, Point3D end, IEnumerable obstacle } ``` -**场景 2:视线检测** +场景 2:视线检测 判断两个物体之间是否有遮挡: @@ -567,7 +567,7 @@ for (int i = 0; i < path.Count - 1; i++) ### 5.1 整体架构 -``` +```graph ┌─────────────────────────────────────────────────────────────┐ │ Navisworks API │ │ (ModelItem, BoundingBox3D, Geometry) │ @@ -1057,7 +1057,7 @@ private List GetPotentialColliders() ### 9.3 集成策略 -``` +```graph geometry3Sharp 基础库 ├── 体素网格模块 (用于路径规划) │ ├── MeshSignedDistanceGrid diff --git a/src/UI/WPF/Collections/ThreadSafeObservableCollection.cs b/src/UI/WPF/Collections/ThreadSafeObservableCollection.cs index 9fcb0fd..52e5292 100644 --- a/src/UI/WPF/Collections/ThreadSafeObservableCollection.cs +++ b/src/UI/WPF/Collections/ThreadSafeObservableCollection.cs @@ -30,7 +30,6 @@ namespace NavisworksTransport.UI.WPF.Collections private readonly object _lock = new object(); private readonly SynchronizationContext _synchronizationContext; private volatile bool _suppressNotification = false; - private readonly DataBindingPerformanceMonitor _performanceMonitor; /// /// 获取当前是否正在批量更新中(禁用通知) @@ -62,11 +61,10 @@ namespace NavisworksTransport.UI.WPF.Collections : base() { _synchronizationContext = SynchronizationContext.Current; - _performanceMonitor = DataBindingPerformanceMonitor.Instance; - + // 启用WPF集合同步机制 BindingOperations.EnableCollectionSynchronization(this, _lock); - + LogManager.Debug($"ThreadSafeObservableCollection<{typeof(T).Name}>已初始化"); } @@ -78,11 +76,10 @@ namespace NavisworksTransport.UI.WPF.Collections : base(collection) { _synchronizationContext = SynchronizationContext.Current; - _performanceMonitor = DataBindingPerformanceMonitor.Instance; - + // 启用WPF集合同步机制 BindingOperations.EnableCollectionSynchronization(this, _lock); - + LogManager.Debug($"ThreadSafeObservableCollection<{typeof(T).Name}>已初始化,包含{Count}个元素"); } @@ -206,36 +203,33 @@ namespace NavisworksTransport.UI.WPF.Collections return; } - using (_performanceMonitor.BeginCollectionUpdate(typeof(ThreadSafeObservableCollection), "AddRange", itemList.Count)) + lock (_lock) { - lock (_lock) + try { - try - { - // 禁用通知 - _suppressNotification = true; + // 禁用通知 + _suppressNotification = true; - // 批量添加 - foreach (var item in itemList) + // 批量添加 + foreach (var item in itemList) + { + if (item != null) { - if (item != null) - { - base.Add(item); - } + base.Add(item); } } - finally - { - // 恢复通知 - _suppressNotification = false; - } - - // 触发批量添加事件 - OnCollectionChanged(new NotifyCollectionChangedEventArgs( - NotifyCollectionChangedAction.Add, - itemList, - Count - itemList.Count)); } + finally + { + // 恢复通知 + _suppressNotification = false; + } + + // 触发批量添加事件 + OnCollectionChanged(new NotifyCollectionChangedEventArgs( + NotifyCollectionChangedAction.Add, + itemList, + Count - itemList.Count)); } LogManager.Debug($"ThreadSafeObservableCollection批量添加{itemList.Count}个元素"); diff --git a/src/UI/WPF/Services/BindingExpressionOptimizer.cs b/src/UI/WPF/Services/BindingExpressionOptimizer.cs index 95d2592..659ba59 100644 --- a/src/UI/WPF/Services/BindingExpressionOptimizer.cs +++ b/src/UI/WPF/Services/BindingExpressionOptimizer.cs @@ -25,9 +25,6 @@ namespace NavisworksTransport.UI.WPF.Services private readonly ConcurrentDictionary _bindingCache; private readonly ConcurrentDictionary _bindingMetadata; - // 性能监控 - private readonly DataBindingPerformanceMonitor _performanceMonitor; - // 优化配置 private TimeSpan _cacheExpiration = TimeSpan.FromMinutes(5); private int _maxCacheSize = 1000; @@ -125,7 +122,6 @@ namespace NavisworksTransport.UI.WPF.Services _bindingCache = new ConcurrentDictionary(); _bindingMetadata = new ConcurrentDictionary(); _pendingUpdates = new HashSet(); - _performanceMonitor = DataBindingPerformanceMonitor.Instance; // 初始化批量更新定时器 _batchUpdateTimer = new DispatcherTimer(DispatcherPriority.Background) @@ -292,10 +288,7 @@ namespace NavisworksTransport.UI.WPF.Services try { - using (_performanceMonitor.BeginPropertyUpdate(bindingExpression.Target?.GetType() ?? typeof(object), GetBindingPath(bindingExpression))) - { - bindingExpression.UpdateTarget(); - } + bindingExpression.UpdateTarget(); // 更新元数据 if (_bindingMetadata.TryGetValue(bindingExpression, out var metadata)) @@ -336,16 +329,13 @@ namespace NavisworksTransport.UI.WPF.Services try { - using (_performanceMonitor.BeginCollectionUpdate(typeof(BindingExpressionOptimizer), "BatchUpdate", updatesToProcess.Count)) - { - // 按优先级和类型分组 - var groupedUpdates = GroupUpdatesByPriority(updatesToProcess); + // 按优先级和类型分组 + var groupedUpdates = GroupUpdatesByPriority(updatesToProcess); - // 按优先级顺序处理 - foreach (var group in groupedUpdates.OrderByDescending(g => g.Key)) - { - ProcessUpdateGroup(group.Value); - } + // 按优先级顺序处理 + foreach (var group in groupedUpdates.OrderByDescending(g => g.Key)) + { + ProcessUpdateGroup(group.Value); } LogManager.Debug($"批量更新完成: {updatesToProcess.Count}个绑定"); diff --git a/src/UI/WPF/Services/DataBindingPerformanceMonitor.cs b/src/UI/WPF/Services/DataBindingPerformanceMonitor.cs deleted file mode 100644 index 5364085..0000000 --- a/src/UI/WPF/Services/DataBindingPerformanceMonitor.cs +++ /dev/null @@ -1,695 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Threading; - -namespace NavisworksTransport.UI.WPF.Services -{ - /// - /// 数据绑定性能监控器 - 监控和分析WPF数据绑定的性能表现 - /// 提供详细的性能指标收集和优化建议 - /// - public class DataBindingPerformanceMonitor : IDisposable - { - #region 字段和属性 - - private static DataBindingPerformanceMonitor _instance; - private static readonly object _instanceLock = new object(); - - // 性能数据收集 - private readonly ConcurrentDictionary _propertyMetrics; - private readonly ConcurrentDictionary _collectionMetrics; - private readonly ConcurrentQueue _updateEvents; - private readonly Timer _reportTimer; - private volatile bool _isDisposed = false; - private volatile bool _isMonitoringEnabled = true; - - // 监控配置 - private TimeSpan _reportInterval = TimeSpan.FromMinutes(5); - private int _maxEventHistory = 10000; - private int _performanceThresholdMs = 16; // 60FPS下每帧约16ms - - /// - /// 获取性能监控器的单例实例 - /// - public static DataBindingPerformanceMonitor Instance - { - get - { - if (_instance == null) - { - lock (_instanceLock) - { - if (_instance == null) - { - _instance = new DataBindingPerformanceMonitor(); - } - } - } - return _instance; - } - } - - /// - /// 是否启用性能监控 - /// - public bool IsMonitoringEnabled - { - get => _isMonitoringEnabled; - set => _isMonitoringEnabled = value; - } - - /// - /// 性能阈值(毫秒)- 超过此值的操作将被标记为慢操作 - /// - public int PerformanceThresholdMs - { - get => _performanceThresholdMs; - set => _performanceThresholdMs = Math.Max(1, value); - } - - /// - /// 当前监控的属性数量 - /// - public int MonitoredPropertiesCount => _propertyMetrics.Count; - - /// - /// 当前监控的集合数量 - /// - public int MonitoredCollectionsCount => _collectionMetrics.Count; - - #endregion - - #region 构造函数和初始化 - - private DataBindingPerformanceMonitor() - { - _propertyMetrics = new ConcurrentDictionary(); - _collectionMetrics = new ConcurrentDictionary(); - _updateEvents = new ConcurrentQueue(); - - // 定期生成性能报告 - _reportTimer = new Timer(GeneratePerformanceReport, null, _reportInterval, _reportInterval); - - LogManager.Info("数据绑定性能监控器已初始化"); - } - - #endregion - - #region 核心监控接口 - - /// - /// 记录属性变更事件的开始 - /// - /// ViewModel类型 - /// 属性名称 - /// 性能测量上下文 - public IDisposable BeginPropertyUpdate(Type viewModelType, string propertyName) - { - if (!_isMonitoringEnabled || _isDisposed) - return new EmptyDisposable(); - - var key = $"{viewModelType.Name}.{propertyName}"; - var stopwatch = Stopwatch.StartNew(); - - return new PropertyUpdateContext(this, key, stopwatch, Dispatcher.CurrentDispatcher); - } - - /// - /// 记录集合变更事件的开始 - /// - /// 集合类型 - /// 操作类型(Add, Remove, Clear等) - /// 影响的项目数量 - /// 性能测量上下文 - public IDisposable BeginCollectionUpdate(Type collectionType, string operationType, int itemCount = 1) - { - if (!_isMonitoringEnabled || _isDisposed) - return new EmptyDisposable(); - - var key = $"{collectionType.Name}.{operationType}"; - var stopwatch = Stopwatch.StartNew(); - - return new CollectionUpdateContext(this, key, stopwatch, itemCount, Dispatcher.CurrentDispatcher); - } - - /// - /// 记录绑定更新事件 - /// - /// 绑定路径 - /// 更新类型 - /// 更新耗时(毫秒) - public void RecordBindingUpdate(string bindingPath, string updateType, double durationMs) - { - if (!_isMonitoringEnabled || _isDisposed) - return; - - var updateEvent = new BindingUpdateEvent - { - Timestamp = DateTime.UtcNow, - BindingPath = bindingPath, - UpdateType = updateType, - DurationMs = durationMs, - IsSlowUpdate = durationMs > _performanceThresholdMs, - ThreadId = Thread.CurrentThread.ManagedThreadId - }; - - _updateEvents.Enqueue(updateEvent); - - // 限制事件历史记录数量 - while (_updateEvents.Count > _maxEventHistory) - { - _updateEvents.TryDequeue(out _); - } - - // 记录慢更新警告 - if (updateEvent.IsSlowUpdate) - { - LogManager.Warning($"检测到慢数据绑定更新: {bindingPath} ({updateType}) - {durationMs:F2}ms"); - } - } - - #endregion - - #region 内部方法 - - /// - /// 完成属性更新监控 - /// - internal void EndPropertyUpdate(string key, Stopwatch stopwatch, Dispatcher dispatcher) - { - if (_isDisposed) return; - - stopwatch.Stop(); - var durationMs = stopwatch.Elapsed.TotalMilliseconds; - - var metrics = _propertyMetrics.GetOrAdd(key, _ => new PropertyUpdateMetrics(key)); - metrics.RecordUpdate(durationMs, dispatcher == Dispatcher.CurrentDispatcher); - - RecordBindingUpdate(key, "PropertyChanged", durationMs); - } - - /// - /// 完成集合更新监控 - /// - internal void EndCollectionUpdate(string key, Stopwatch stopwatch, int itemCount, Dispatcher dispatcher) - { - if (_isDisposed) return; - - stopwatch.Stop(); - var durationMs = stopwatch.Elapsed.TotalMilliseconds; - - var metrics = _collectionMetrics.GetOrAdd(key, _ => new CollectionUpdateMetrics(key)); - metrics.RecordUpdate(durationMs, itemCount, dispatcher == Dispatcher.CurrentDispatcher); - - RecordBindingUpdate(key, "CollectionChanged", durationMs); - } - - /// - /// 生成性能报告 - /// - private void GeneratePerformanceReport(object state) - { - if (_isDisposed) return; - - try - { - var report = GenerateDetailedReport(); - LogManager.Info($"数据绑定性能报告:\n{report}"); - - // 清理过期数据 - CleanupExpiredData(); - } - catch (Exception ex) - { - LogManager.Error($"生成数据绑定性能报告失败: {ex.Message}"); - } - } - - /// - /// 清理过期数据 - /// - private void CleanupExpiredData() - { - var cutoffTime = DateTime.UtcNow.Subtract(TimeSpan.FromHours(1)); - - // 清理属性指标中的过期数据 - foreach (var metrics in _propertyMetrics.Values) - { - metrics.CleanupOldData(cutoffTime); - } - - // 清理集合指标中的过期数据 - foreach (var metrics in _collectionMetrics.Values) - { - metrics.CleanupOldData(cutoffTime); - } - } - - #endregion - - #region 报告生成 - - /// - /// 生成详细的性能报告 - /// - /// 性能报告字符串 - public string GenerateDetailedReport() - { - var report = new System.Text.StringBuilder(); - - report.AppendLine("=== 数据绑定性能监控报告 ==="); - report.AppendLine($"报告时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); - report.AppendLine($"监控状态: {(IsMonitoringEnabled ? "启用" : "禁用")}"); - report.AppendLine($"性能阈值: {PerformanceThresholdMs}ms"); - report.AppendLine(); - - // 属性更新统计 - report.AppendLine("属性更新性能统计:"); - var topSlowProperties = _propertyMetrics.Values - .Where(m => m.UpdateCount > 0) - .OrderByDescending(m => m.AverageUpdateTime) - .Take(10) - .ToList(); - - if (topSlowProperties.Any()) - { - foreach (var metrics in topSlowProperties) - { - report.AppendLine($" {metrics.PropertyKey}:"); - report.AppendLine($" 更新次数: {metrics.UpdateCount}"); - report.AppendLine($" 平均耗时: {metrics.AverageUpdateTime:F2}ms"); - report.AppendLine($" 最大耗时: {metrics.MaxUpdateTime:F2}ms"); - report.AppendLine($" 慢更新次数: {metrics.SlowUpdateCount}"); - report.AppendLine($" 跨线程更新次数: {metrics.CrossThreadUpdateCount}"); - } - } - else - { - report.AppendLine(" 暂无属性更新数据"); - } - - report.AppendLine(); - - // 集合更新统计 - report.AppendLine("集合更新性能统计:"); - var topSlowCollections = _collectionMetrics.Values - .Where(m => m.UpdateCount > 0) - .OrderByDescending(m => m.AverageUpdateTime) - .Take(10) - .ToList(); - - if (topSlowCollections.Any()) - { - foreach (var metrics in topSlowCollections) - { - report.AppendLine($" {metrics.CollectionKey}:"); - report.AppendLine($" 更新次数: {metrics.UpdateCount}"); - report.AppendLine($" 平均耗时: {metrics.AverageUpdateTime:F2}ms"); - report.AppendLine($" 最大耗时: {metrics.MaxUpdateTime:F2}ms"); - report.AppendLine($" 处理项目总数: {metrics.TotalItemsProcessed}"); - report.AppendLine($" 慢更新次数: {metrics.SlowUpdateCount}"); - } - } - else - { - report.AppendLine(" 暂无集合更新数据"); - } - - report.AppendLine(); - - // 最近的慢更新事件 - var recentSlowUpdates = _updateEvents - .Where(e => e.IsSlowUpdate && e.Timestamp > DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(10))) - .OrderByDescending(e => e.DurationMs) - .Take(5) - .ToList(); - - if (recentSlowUpdates.Any()) - { - report.AppendLine("最近的慢更新事件 (10分钟内):"); - foreach (var evt in recentSlowUpdates) - { - report.AppendLine($" {evt.BindingPath} ({evt.UpdateType}) - {evt.DurationMs:F2}ms @ {evt.Timestamp:HH:mm:ss}"); - } - } - - // 性能优化建议 - report.AppendLine(); - report.AppendLine("性能优化建议:"); - - var suggestions = GenerateOptimizationSuggestions(); - if (suggestions.Any()) - { - foreach (var suggestion in suggestions) - { - report.AppendLine($" • {suggestion}"); - } - } - else - { - report.AppendLine(" 当前性能表现良好,暂无优化建议"); - } - - return report.ToString(); - } - - /// - /// 生成性能优化建议 - /// - /// 优化建议列表 - public List GenerateOptimizationSuggestions() - { - var suggestions = new List(); - - // 检查频繁更新的属性 - var frequentProperties = _propertyMetrics.Values - .Where(m => m.UpdateCount > 100 && m.AverageUpdateTime > _performanceThresholdMs) - .ToList(); - - if (frequentProperties.Any()) - { - suggestions.Add($"发现{frequentProperties.Count}个高频慢更新属性,建议考虑使用延迟更新或批量更新机制"); - } - - // 检查大集合操作 - var largeCollectionUpdates = _collectionMetrics.Values - .Where(m => m.AverageItemsPerUpdate > 1000 && m.AverageUpdateTime > _performanceThresholdMs * 5) - .ToList(); - - if (largeCollectionUpdates.Any()) - { - suggestions.Add($"发现{largeCollectionUpdates.Count}个大集合更新操作,建议实现虚拟化或分页机制"); - } - - // 检查跨线程更新 - var crossThreadUpdates = _propertyMetrics.Values - .Where(m => m.CrossThreadUpdateCount > m.UpdateCount * 0.1) // 超过10%的跨线程更新 - .ToList(); - - if (crossThreadUpdates.Any()) - { - suggestions.Add($"发现{crossThreadUpdates.Count}个属性存在频繁的跨线程更新,建议优化线程调度"); - } - - // 检查内存使用 - var totalMetrics = _propertyMetrics.Count + _collectionMetrics.Count; - if (totalMetrics > 1000) - { - suggestions.Add("监控的绑定数量较多,建议定期清理不再使用的绑定以释放内存"); - } - - return suggestions; - } - - /// - /// 获取性能概览数据 - /// - /// 性能概览 - public PerformanceOverview GetPerformanceOverview() - { - var totalPropertyUpdates = _propertyMetrics.Values.Sum(m => m.UpdateCount); - var totalCollectionUpdates = _collectionMetrics.Values.Sum(m => m.UpdateCount); - var totalSlowUpdates = _updateEvents.Count(e => e.IsSlowUpdate); - - var avgPropertyUpdateTime = _propertyMetrics.Values - .Where(m => m.UpdateCount > 0) - .DefaultIfEmpty(new PropertyUpdateMetrics("dummy")) - .Average(m => m.AverageUpdateTime); - - var avgCollectionUpdateTime = _collectionMetrics.Values - .Where(m => m.UpdateCount > 0) - .DefaultIfEmpty(new CollectionUpdateMetrics("dummy")) - .Average(m => m.AverageUpdateTime); - - return new PerformanceOverview - { - TotalPropertyUpdates = totalPropertyUpdates, - TotalCollectionUpdates = totalCollectionUpdates, - TotalSlowUpdates = totalSlowUpdates, - AveragePropertyUpdateTime = avgPropertyUpdateTime, - AverageCollectionUpdateTime = avgCollectionUpdateTime, - MonitoredPropertiesCount = MonitoredPropertiesCount, - MonitoredCollectionsCount = MonitoredCollectionsCount, - IsHealthy = totalSlowUpdates < (totalPropertyUpdates + totalCollectionUpdates) * 0.05 // 少于5%的慢更新 - }; - } - - #endregion - - #region 配置管理 - - /// - /// 设置监控配置 - /// - /// 报告生成间隔 - /// 最大事件历史记录数 - /// 性能阈值(毫秒) - public void ConfigureMonitoring(TimeSpan reportInterval, int maxEventHistory, int performanceThreshold) - { - _reportInterval = reportInterval; - _maxEventHistory = Math.Max(100, maxEventHistory); - _performanceThresholdMs = Math.Max(1, performanceThreshold); - - // 重启定时器 - _reportTimer?.Change(_reportInterval, _reportInterval); - - LogManager.Info($"数据绑定监控配置已更新 - 报告间隔: {reportInterval}, 事件历史: {maxEventHistory}, 性能阈值: {performanceThreshold}ms"); - } - - /// - /// 重置所有监控数据 - /// - public void ResetMonitoringData() - { - _propertyMetrics.Clear(); - _collectionMetrics.Clear(); - - while (_updateEvents.TryDequeue(out _)) { } - - LogManager.Info("数据绑定监控数据已重置"); - } - - #endregion - - #region IDisposable实现 - - public void Dispose() - { - if (_isDisposed) return; - - _isDisposed = true; - _isMonitoringEnabled = false; - - _reportTimer?.Dispose(); - - // 生成最终报告 - try - { - var finalReport = GenerateDetailedReport(); - LogManager.Info($"数据绑定性能监控最终报告:\n{finalReport}"); - } - catch (Exception ex) - { - LogManager.Error($"生成最终性能报告失败: {ex.Message}"); - } - - _propertyMetrics.Clear(); - _collectionMetrics.Clear(); - - LogManager.Info("数据绑定性能监控器已释放"); - } - - #endregion - } - - #region 辅助类和数据结构 - - /// - /// 属性更新上下文 - 用于测量属性更新性能 - /// - internal class PropertyUpdateContext : IDisposable - { - private readonly DataBindingPerformanceMonitor _monitor; - private readonly string _key; - private readonly Stopwatch _stopwatch; - private readonly Dispatcher _dispatcher; - - public PropertyUpdateContext(DataBindingPerformanceMonitor monitor, string key, Stopwatch stopwatch, Dispatcher dispatcher) - { - _monitor = monitor; - _key = key; - _stopwatch = stopwatch; - _dispatcher = dispatcher; - } - - public void Dispose() - { - _monitor.EndPropertyUpdate(_key, _stopwatch, _dispatcher); - } - } - - /// - /// 集合更新上下文 - 用于测量集合更新性能 - /// - internal class CollectionUpdateContext : IDisposable - { - private readonly DataBindingPerformanceMonitor _monitor; - private readonly string _key; - private readonly Stopwatch _stopwatch; - private readonly int _itemCount; - private readonly Dispatcher _dispatcher; - - public CollectionUpdateContext(DataBindingPerformanceMonitor monitor, string key, Stopwatch stopwatch, int itemCount, Dispatcher dispatcher) - { - _monitor = monitor; - _key = key; - _stopwatch = stopwatch; - _itemCount = itemCount; - _dispatcher = dispatcher; - } - - public void Dispose() - { - _monitor.EndCollectionUpdate(_key, _stopwatch, _itemCount, _dispatcher); - } - } - - /// - /// 空的IDisposable实现 - 用于禁用监控时的占位符 - /// - internal class EmptyDisposable : IDisposable - { - public void Dispose() { } - } - - /// - /// 属性更新性能指标 - /// - public class PropertyUpdateMetrics - { - public string PropertyKey { get; } - public long UpdateCount { get; private set; } - public double TotalUpdateTime { get; private set; } - public double MaxUpdateTime { get; private set; } - public long SlowUpdateCount { get; private set; } - public long CrossThreadUpdateCount { get; private set; } - public DateTime LastUpdateTime { get; private set; } - - public double AverageUpdateTime => UpdateCount > 0 ? TotalUpdateTime / UpdateCount : 0; - - private readonly List _updateTimes = new List(); - - public PropertyUpdateMetrics(string propertyKey) - { - PropertyKey = propertyKey; - LastUpdateTime = DateTime.UtcNow; - } - - public void RecordUpdate(double durationMs, bool isOnUIThread) - { - UpdateCount++; - TotalUpdateTime += durationMs; - MaxUpdateTime = Math.Max(MaxUpdateTime, durationMs); - LastUpdateTime = DateTime.UtcNow; - - if (durationMs > 16) // 60FPS阈值 - { - SlowUpdateCount++; - } - - if (!isOnUIThread) - { - CrossThreadUpdateCount++; - } - - _updateTimes.Add(DateTime.UtcNow); - } - - public void CleanupOldData(DateTime cutoffTime) - { - _updateTimes.RemoveAll(t => t < cutoffTime); - } - } - - /// - /// 集合更新性能指标 - /// - public class CollectionUpdateMetrics - { - public string CollectionKey { get; } - public long UpdateCount { get; private set; } - public double TotalUpdateTime { get; private set; } - public double MaxUpdateTime { get; private set; } - public long TotalItemsProcessed { get; private set; } - public long SlowUpdateCount { get; private set; } - public DateTime LastUpdateTime { get; private set; } - - public double AverageUpdateTime => UpdateCount > 0 ? TotalUpdateTime / UpdateCount : 0; - public double AverageItemsPerUpdate => UpdateCount > 0 ? (double)TotalItemsProcessed / UpdateCount : 0; - - private readonly List _updateTimes = new List(); - - public CollectionUpdateMetrics(string collectionKey) - { - CollectionKey = collectionKey; - LastUpdateTime = DateTime.UtcNow; - } - - public void RecordUpdate(double durationMs, int itemCount, bool isOnUIThread) - { - UpdateCount++; - TotalUpdateTime += durationMs; - MaxUpdateTime = Math.Max(MaxUpdateTime, durationMs); - TotalItemsProcessed += itemCount; - LastUpdateTime = DateTime.UtcNow; - - if (durationMs > 50) // 集合操作的更宽松阈值 - { - SlowUpdateCount++; - } - - _updateTimes.Add(DateTime.UtcNow); - } - - public void CleanupOldData(DateTime cutoffTime) - { - _updateTimes.RemoveAll(t => t < cutoffTime); - } - } - - /// - /// 绑定更新事件 - /// - public class BindingUpdateEvent - { - public DateTime Timestamp { get; set; } - public string BindingPath { get; set; } - public string UpdateType { get; set; } - public double DurationMs { get; set; } - public bool IsSlowUpdate { get; set; } - public int ThreadId { get; set; } - } - - /// - /// 性能概览数据 - /// - public class PerformanceOverview - { - public long TotalPropertyUpdates { get; set; } - public long TotalCollectionUpdates { get; set; } - public long TotalSlowUpdates { get; set; } - public double AveragePropertyUpdateTime { get; set; } - public double AverageCollectionUpdateTime { get; set; } - public int MonitoredPropertiesCount { get; set; } - public int MonitoredCollectionsCount { get; set; } - public bool IsHealthy { get; set; } - } - - #endregion -} \ No newline at end of file diff --git a/src/UI/WPF/Services/SmartDataBindingOptimizer.cs b/src/UI/WPF/Services/SmartDataBindingOptimizer.cs index b927665..39287fe 100644 --- a/src/UI/WPF/Services/SmartDataBindingOptimizer.cs +++ b/src/UI/WPF/Services/SmartDataBindingOptimizer.cs @@ -35,9 +35,6 @@ namespace NavisworksTransport.UI.WPF.Services private readonly Dictionary _conditionalConfigs; private readonly object _conditionalConfigLock = new object(); - // 性能监控集成 - private readonly DataBindingPerformanceMonitor _performanceMonitor; - // 配置选项 private TimeSpan _defaultDelayInterval = TimeSpan.FromMilliseconds(100); private TimeSpan _batchUpdateInterval = TimeSpan.FromMilliseconds(50); @@ -102,8 +99,6 @@ namespace NavisworksTransport.UI.WPF.Services _batchUpdates = new Dictionary(); _conditionalConfigs = new Dictionary(); - _performanceMonitor = DataBindingPerformanceMonitor.Instance; - // 初始化延迟更新定时器 _delayedUpdateTimer = new Timer(ProcessDelayedUpdates, null, _defaultDelayInterval, _defaultDelayInterval); @@ -241,10 +236,7 @@ namespace NavisworksTransport.UI.WPF.Services if (target == null) return; - using (_performanceMonitor.BeginPropertyUpdate(target.GetType(), context.PropertyName)) - { - context.UpdateAction?.Invoke(); - } + context.UpdateAction?.Invoke(); LogManager.Debug($"执行延迟更新: {context.PropertyName}, 合并次数: {context.UpdateCount}"); } @@ -436,22 +428,19 @@ namespace NavisworksTransport.UI.WPF.Services { var duration = DateTime.UtcNow - context.StartTime; - using (_performanceMonitor.BeginPropertyUpdate(target.GetType(), $"BatchUpdate_{properties.Count}Properties")) + // 如果目标实现了批量更新接口,使用其批量方法 + if (target is ViewModelBase viewModelBase) { - // 如果目标实现了批量更新接口,使用其批量方法 - if (target is ViewModelBase viewModelBase) + viewModelBase.OnPropertiesChanged(properties.ToArray()); + } + else + { + // 否则逐个触发属性变更通知 + foreach (var propertyName in properties) { - viewModelBase.OnPropertiesChanged(properties.ToArray()); - } - else - { - // 否则逐个触发属性变更通知 - foreach (var propertyName in properties) - { - // 使用反射或其他方式触发PropertyChanged事件 - // 这里需要根据具体的INotifyPropertyChanged实现来调用 - TriggerPropertyChanged(target, propertyName); - } + // 使用反射或其他方式触发PropertyChanged事件 + // 这里需要根据具体的INotifyPropertyChanged实现来调用 + TriggerPropertyChanged(target, propertyName); } } @@ -606,10 +595,7 @@ namespace NavisworksTransport.UI.WPF.Services try { // 执行延迟的更新 - using (_performanceMonitor.BeginPropertyUpdate(target.GetType(), propertyName)) - { - TriggerPropertyChanged(target, propertyName); - } + TriggerPropertyChanged(target, propertyName); lock (_conditionalConfigLock) { @@ -680,16 +666,6 @@ namespace NavisworksTransport.UI.WPF.Services report.AppendLine("条件更新机制:"); report.AppendLine($" 配置的条件更新: {stats.ConfiguredConditionalUpdates}"); - report.AppendLine(); - - // 集成性能监控数据 - var performanceOverview = _performanceMonitor.GetPerformanceOverview(); - report.AppendLine("性能概览:"); - report.AppendLine($" 总属性更新: {performanceOverview.TotalPropertyUpdates}"); - report.AppendLine($" 总集合更新: {performanceOverview.TotalCollectionUpdates}"); - report.AppendLine($" 慢更新次数: {performanceOverview.TotalSlowUpdates}"); - report.AppendLine($" 平均属性更新时间: {performanceOverview.AveragePropertyUpdateTime:F2}ms"); - report.AppendLine($" 系统健康状态: {(performanceOverview.IsHealthy ? "良好" : "需要优化")}"); return report.ToString(); } diff --git a/src/UI/WPF/ViewModels/ViewModelBase.cs b/src/UI/WPF/ViewModels/ViewModelBase.cs index 71c5bbf..2cf7ee0 100644 --- a/src/UI/WPF/ViewModels/ViewModelBase.cs +++ b/src/UI/WPF/ViewModels/ViewModelBase.cs @@ -32,11 +32,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// private readonly SmartDataBindingOptimizer _bindingOptimizer; - /// - /// 数据绑定性能监控器,监控绑定性能 - /// - private readonly DataBindingPerformanceMonitor _performanceMonitor; - /// /// 正在更新的属性集合,用于防重入检测 /// @@ -52,11 +47,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// protected bool IsSmartOptimizationEnabled { get; set; } = true; - /// - /// 是否启用性能监控 - /// - protected bool IsPerformanceMonitoringEnabled { get; set; } = true; - /// /// 主ViewModel引用,用于统一状态栏更新 /// @@ -73,7 +63,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels { _uiStateManager = UIStateManager.Instance; _bindingOptimizer = SmartDataBindingOptimizer.Instance; - _performanceMonitor = DataBindingPerformanceMonitor.Instance; } #endregion @@ -81,7 +70,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels #region 属性更新方法 /// - /// 触发属性变更通知(线程安全,防重入,集成性能监控) + /// 触发属性变更通知(线程安全,防重入) /// /// 属性名称,自动获取调用者名称 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) @@ -91,13 +80,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels return; } - // 性能监控 - IDisposable performanceContext = null; - if (IsPerformanceMonitoringEnabled) - { - performanceContext = _performanceMonitor.BeginPropertyUpdate(this.GetType(), propertyName); - } - try { // 防重入检查 @@ -109,7 +91,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Debug($"[ViewModel] 检测到属性重入更新,跳过: {propertyName}"); return; } - + // 标记属性为正在更新状态 _updatingProperties.Add(propertyName); } @@ -140,9 +122,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels { _updatingProperties.Remove(propertyName); } - - // 结束性能监控 - performanceContext?.Dispose(); } } @@ -510,37 +489,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels #endregion - #region 性能监控和诊断 - - /// - /// 获取当前ViewModel的绑定性能统计 - /// - /// 性能统计信息 - protected virtual string GetBindingPerformanceReport() - { - if (!IsPerformanceMonitoringEnabled) - return "性能监控已禁用"; - - try - { - return _performanceMonitor.GenerateDetailedReport(); - } - catch (Exception ex) - { - LogManager.Error($"[ViewModel] 生成性能报告失败: {ex.Message}"); - return $"生成性能报告失败: {ex.Message}"; - } - } - - /// - /// 启用或禁用性能监控 - /// - /// 是否启用 - protected void SetPerformanceMonitoring(bool enabled) - { - IsPerformanceMonitoringEnabled = enabled; - _performanceMonitor.IsMonitoringEnabled = enabled; - } + #region 诊断方法 /// /// 启用或禁用智能优化