mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-08 00:14:31 +08:00
Perf: shapetable sorting (#8676)
* Grouped ShapeAlteration by feature before sorting them * removed stopwatches * Sorting approach can be selected by setting the GroupByFeatures option in HostComponents.config
This commit is contained in:

committed by
GitHub

parent
bf8cc13922
commit
12e9f06689
@@ -9,6 +9,14 @@
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
<Component Type="Orchard.DisplayManagement.Descriptors.DefaultShapeTableManager">
|
||||
<Properties>
|
||||
<!-- Set Value="true" to enable an optimization in the sorting step of the ShapeAlterations.
|
||||
Warning: Rendered results should not be affected, but intermediate steps might. -->
|
||||
<Property Name="GroupByFeatures" Value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
<Component Type="Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy.PlacementFileParser">
|
||||
<Properties>
|
||||
<!-- Set Value="true" to disable Placement files monitoring (Placement.info) -->
|
||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autofac.Features.Metadata;
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
@@ -19,6 +20,16 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
private readonly IParallelCacheContext _parallelCacheContext;
|
||||
private readonly Work<IEnumerable<IShapeTableEventHandler>> _shapeTableEventHandlersWork;
|
||||
|
||||
/// <summary>
|
||||
/// Group all ShapeAlterations by Feature, so we may more easily sort those by their
|
||||
/// priorities and dependencies. The reason for this is that we may often end up with
|
||||
/// orders of magnitude more ShapeAlterations than Features, so sorting directly the
|
||||
/// former may end up being too expensive.
|
||||
/// We can enable this through HostComponents.config as a safety measure in case this
|
||||
/// breaks some frontend.
|
||||
/// </summary>
|
||||
public bool GroupByFeatures { get; set; }
|
||||
|
||||
public DefaultShapeTableManager(
|
||||
IEnumerable<Meta<IShapeTableProvider>> bindingStrategies,
|
||||
IExtensionManager extensionManager,
|
||||
@@ -50,11 +61,36 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
return builder.BuildAlterations().ToReadOnlyCollection();
|
||||
});
|
||||
|
||||
var alterations = alterationSets
|
||||
.SelectMany(shapeAlterations => shapeAlterations)
|
||||
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName))
|
||||
.OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority)
|
||||
.ToList();
|
||||
List<ShapeAlteration> alterations;
|
||||
if (GroupByFeatures) {
|
||||
var unsortedAlterations = alterationSets
|
||||
.SelectMany(shapeAlterations => shapeAlterations)
|
||||
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName));
|
||||
|
||||
// Group all ShapeAlterations by Feature, so we may more easily sort those by their
|
||||
// priorities and dependencies. The reason for this is that we may often end up with
|
||||
// orders of magnitude more ShapeAlterations than Features, so sorting directly the
|
||||
// former may end up being too expensive.
|
||||
var alterationsByFeature = unsortedAlterations
|
||||
.GroupBy(sa => sa.Feature.Descriptor.Id)
|
||||
.Select(g => new AlterationGroup {
|
||||
Feature = g.First().Feature,
|
||||
Alterations = g
|
||||
});
|
||||
var orderedGroups = alterationsByFeature
|
||||
.OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority);
|
||||
alterations = orderedGroups
|
||||
.SelectMany(g => g.Alterations)
|
||||
.ToList();
|
||||
}
|
||||
else {
|
||||
alterations = alterationSets
|
||||
.SelectMany(shapeAlterations => shapeAlterations)
|
||||
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName))
|
||||
.OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
var descriptors = alterations.GroupBy(alteration => alteration.ShapeType, StringComparer.OrdinalIgnoreCase)
|
||||
.Select(group => group.Aggregate(
|
||||
@@ -64,8 +100,8 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
return descriptor;
|
||||
})).ToList();
|
||||
|
||||
foreach(var descriptor in descriptors) {
|
||||
foreach(var alteration in alterations.Where(a => a.ShapeType == descriptor.ShapeType).ToList()) {
|
||||
foreach (var descriptor in descriptors) {
|
||||
foreach (var alteration in alterations.Where(a => a.ShapeType == descriptor.ShapeType).ToList()) {
|
||||
var local = new ShapeDescriptor { ShapeType = descriptor.ShapeType };
|
||||
alteration.Alter(local);
|
||||
descriptor.BindingSources.Add(local.BindingSource);
|
||||
@@ -131,5 +167,18 @@ namespace Orchard.DisplayManagement.Descriptors {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class AlterationGroup {
|
||||
public Feature Feature { get; set; }
|
||||
public IEnumerable<ShapeAlteration> Alterations { get; set; }
|
||||
}
|
||||
private static int GetPriority(AlterationGroup shapeAlteration) {
|
||||
return shapeAlteration.Feature.Descriptor.Priority;
|
||||
}
|
||||
|
||||
private static bool AlterationHasDependency(AlterationGroup item, AlterationGroup subject) {
|
||||
return ExtensionManager.HasDependency(item.Feature.Descriptor, subject.Feature.Descriptor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user