mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +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>
|
</Properties>
|
||||||
</Component>
|
</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">
|
<Component Type="Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy.PlacementFileParser">
|
||||||
<Properties>
|
<Properties>
|
||||||
<!-- Set Value="true" to disable Placement files monitoring (Placement.info) -->
|
<!-- Set Value="true" to disable Placement files monitoring (Placement.info) -->
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Autofac.Features.Metadata;
|
using Autofac.Features.Metadata;
|
||||||
using Orchard.Caching;
|
using Orchard.Caching;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
using Orchard.Environment;
|
using Orchard.Environment;
|
||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
@@ -19,6 +20,16 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
private readonly IParallelCacheContext _parallelCacheContext;
|
private readonly IParallelCacheContext _parallelCacheContext;
|
||||||
private readonly Work<IEnumerable<IShapeTableEventHandler>> _shapeTableEventHandlersWork;
|
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(
|
public DefaultShapeTableManager(
|
||||||
IEnumerable<Meta<IShapeTableProvider>> bindingStrategies,
|
IEnumerable<Meta<IShapeTableProvider>> bindingStrategies,
|
||||||
IExtensionManager extensionManager,
|
IExtensionManager extensionManager,
|
||||||
@@ -50,11 +61,36 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
return builder.BuildAlterations().ToReadOnlyCollection();
|
return builder.BuildAlterations().ToReadOnlyCollection();
|
||||||
});
|
});
|
||||||
|
|
||||||
var alterations = alterationSets
|
List<ShapeAlteration> alterations;
|
||||||
.SelectMany(shapeAlterations => shapeAlterations)
|
if (GroupByFeatures) {
|
||||||
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName))
|
var unsortedAlterations = alterationSets
|
||||||
.OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority)
|
.SelectMany(shapeAlterations => shapeAlterations)
|
||||||
.ToList();
|
.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)
|
var descriptors = alterations.GroupBy(alteration => alteration.ShapeType, StringComparer.OrdinalIgnoreCase)
|
||||||
.Select(group => group.Aggregate(
|
.Select(group => group.Aggregate(
|
||||||
@@ -64,8 +100,8 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
return descriptor;
|
return descriptor;
|
||||||
})).ToList();
|
})).ToList();
|
||||||
|
|
||||||
foreach(var descriptor in descriptors) {
|
foreach (var descriptor in descriptors) {
|
||||||
foreach(var alteration in alterations.Where(a => a.ShapeType == descriptor.ShapeType).ToList()) {
|
foreach (var alteration in alterations.Where(a => a.ShapeType == descriptor.ShapeType).ToList()) {
|
||||||
var local = new ShapeDescriptor { ShapeType = descriptor.ShapeType };
|
var local = new ShapeDescriptor { ShapeType = descriptor.ShapeType };
|
||||||
alteration.Alter(local);
|
alteration.Alter(local);
|
||||||
descriptor.BindingSources.Add(local.BindingSource);
|
descriptor.BindingSources.Add(local.BindingSource);
|
||||||
@@ -131,5 +167,18 @@ namespace Orchard.DisplayManagement.Descriptors {
|
|||||||
}
|
}
|
||||||
return false;
|
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