From 6505dc0d2067b1da1918739fbf2d28bcf9689d26 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 16 Apr 2026 09:43:10 +0800 Subject: [PATCH] =?UTF-8?q?Optimize=20batch=20state=20checker=20model=20lo?= =?UTF-8?q?okup=20from=20O(N=C2=B2)=20to=20O(N)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace linear scans with Dictionary/HashSet lookups in both RequirePermissionsSimpleBatchStateChecker and RequireFeaturesSimpleBatchStateChecker for consistency. --- ...quirePermissionsSimpleBatchStateChecker.cs | 28 ++++++++++++++--- .../RequireFeaturesSimpleBatchStateChecker.cs | 30 ++++++++++++++----- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs index 70e74a6bca..ad6c9b989e 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs @@ -47,13 +47,33 @@ public class RequirePermissionsSimpleBatchStateChecker : SimpleBatchStat var result = new SimpleStateCheckerResult(context.States); - var permissions = _models.Where(x => context.States.Any(s => s.Equals(x.State))).SelectMany(x => x.Permissions).Distinct().ToArray(); - var grantResult = await permissionChecker.IsGrantedAsync(permissions); + var stateSet = new HashSet(context.States); + var modelLookup = new Dictionary>(); + var allPermissions = new HashSet(); + + foreach (var model in _models) + { + if (!stateSet.Contains(model.State)) + { + continue; + } + + if (!modelLookup.ContainsKey(model.State)) + { + modelLookup[model.State] = model; + } + + foreach (var permission in model.Permissions) + { + allPermissions.Add(permission); + } + } + + var grantResult = await permissionChecker.IsGrantedAsync(allPermissions.ToArray()); foreach (var state in context.States) { - var model = _models.FirstOrDefault(x => x.State.Equals(state)); - if (model != null) + if (modelLookup.TryGetValue(state, out var model)) { if (model.RequiresAll) { diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleBatchStateChecker.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleBatchStateChecker.cs index 2cff28cc08..24089e2364 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleBatchStateChecker.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleBatchStateChecker.cs @@ -49,17 +49,33 @@ public class RequireFeaturesSimpleBatchStateChecker : SimpleBatchStateCh var result = new SimpleStateCheckerResult(context.States); - var relevantModels = _models - .Where(x => context.States.Any(s => s.Equals(x.State))) - .ToList(); + var stateSet = new HashSet(context.States); + var modelLookup = new Dictionary>(); + var allFeatures = new HashSet(); - var features = relevantModels.SelectMany(x => x.FeatureNames).Distinct().ToArray(); - var featureValues = await featureChecker.IsEnabledAsync(features); + foreach (var model in _models) + { + if (!stateSet.Contains(model.State)) + { + continue; + } + + if (!modelLookup.ContainsKey(model.State)) + { + modelLookup[model.State] = model; + } + + foreach (var featureName in model.FeatureNames) + { + allFeatures.Add(featureName); + } + } + + var featureValues = await featureChecker.IsEnabledAsync(allFeatures.ToArray()); foreach (var state in context.States) { - var model = relevantModels.FirstOrDefault(x => x.State.Equals(state)); - if (model != null) + if (modelLookup.TryGetValue(state, out var model)) { if (model.RequiresAll) {