PERF: Build shape table in parallel

We have lots of file I/O to scan directories for templates,
so it was a good candidate to run in parallel.

--HG--
branch : 1.x
This commit is contained in:
Renaud Paquay
2011-06-02 10:31:46 -07:00
parent 6755e88686
commit 2a43983151
6 changed files with 36 additions and 45 deletions

View File

@@ -59,10 +59,9 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
}
static IEnumerable<ShapeAlteration> GetAlterationBuilders(IShapeTableProvider strategy) {
IList<ShapeAlterationBuilder> alterationBuilders = new List<ShapeAlterationBuilder>();
var builder = new ShapeTableBuilder(alterationBuilders, null);
var builder = new ShapeTableBuilder(null);
strategy.Discover(builder);
return alterationBuilders.Select(alterationBuilder => alterationBuilder.Build());
return builder.BuildAlterations();
}
[Test]

View File

@@ -147,13 +147,11 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
_testViewEngine.Add("~/Modules/Alpha/Views/AlphaShape.blah", null);
var strategy = _container.Resolve<IShapeTableProvider>();
IList<ShapeAlterationBuilder> alterationBuilders = new List<ShapeAlterationBuilder>();
var builder = new ShapeTableBuilder(alterationBuilders,null);
var builder = new ShapeTableBuilder(null);
strategy.Discover(builder);
var alterations = alterationBuilders.Select(alterationBuilder=>alterationBuilder.Build());
var alterations = builder.BuildAlterations();
Assert.That(alterations.Any(alteration => alteration.ShapeType.Equals("AlphaShape", StringComparison.OrdinalIgnoreCase)));
}
}
}

View File

@@ -146,10 +146,9 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
_testViewEngine.Add("~/Modules/Alpha/Styles/alpha-shape.css", null);
var strategy = _container.Resolve<IShapeTableProvider>();
IList<ShapeAlterationBuilder> alterationBuilders = new List<ShapeAlterationBuilder>();
var builder = new ShapeTableBuilder(alterationBuilders,null);
var builder = new ShapeTableBuilder(null);
strategy.Discover(builder);
var alterations = alterationBuilders.Select(alterationBuilder=>alterationBuilder.Build());
var alterations = builder.BuildAlterations();
Assert.That(alterations.Any(alteration => alteration.ShapeType == "Style"));

View File

@@ -14,13 +14,16 @@ namespace Orchard.DisplayManagement.Descriptors {
private readonly IEnumerable<Meta<IShapeTableProvider>> _bindingStrategies;
private readonly IExtensionManager _extensionManager;
private readonly ICacheManager _cacheManager;
private readonly IParallelCacheContext _parallelCacheContext;
public DefaultShapeTableManager(
IEnumerable<Meta<IShapeTableProvider>> bindingStrategies,
IExtensionManager extensionManager,
ICacheManager cacheManager) {
ICacheManager cacheManager,
IParallelCacheContext parallelCacheContext) {
_extensionManager = extensionManager;
_cacheManager = cacheManager;
_parallelCacheContext = parallelCacheContext;
_bindingStrategies = bindingStrategies;
Logger = NullLogger.Instance;
}
@@ -31,19 +34,20 @@ namespace Orchard.DisplayManagement.Descriptors {
return _cacheManager.Get(themeName ?? "", x => {
Logger.Information("Start building shape table");
var builderFactory = new ShapeTableBuilderFactory();
foreach (var bindingStrategy in _bindingStrategies) {
var alterationSets = _parallelCacheContext.RunInParallel(_bindingStrategies, bindingStrategy => {
Feature strategyDefaultFeature = bindingStrategy.Metadata.ContainsKey("Feature") ?
(Feature) bindingStrategy.Metadata["Feature"] :
null;
(Feature)bindingStrategy.Metadata["Feature"] :
null;
var builder = builderFactory.CreateTableBuilder(strategyDefaultFeature);
var builder = new ShapeTableBuilder(strategyDefaultFeature);
bindingStrategy.Value.Discover(builder);
}
return builder.BuildAlterations().ToList();
});
var alterations = builderFactory.BuildAlterations()
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName))
.OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority);
var alterations = alterationSets
.SelectMany(shapeAlterations => shapeAlterations)
.Where(alteration => IsModuleOrRequestedTheme(alteration, themeName))
.OrderByDependenciesAndPriorities(AlterationHasDependency, GetPriority);
var descriptors = alterations.GroupBy(alteration => alteration.ShapeType, StringComparer.OrdinalIgnoreCase)
.Select(group => group.Aggregate(
@@ -98,7 +102,7 @@ namespace Orchard.DisplayManagement.Descriptors {
var availableFeatures = _extensionManager.AvailableFeatures();
var themeFeature = availableFeatures.SingleOrDefault(fd => fd.Id == themeName);
while(themeFeature != null) {
while (themeFeature != null) {
var baseTheme = themeFeature.Extension.BaseTheme;
if (String.IsNullOrEmpty(baseTheme)) {
return false;
@@ -110,21 +114,5 @@ namespace Orchard.DisplayManagement.Descriptors {
}
return false;
}
class ShapeTableBuilderFactory {
readonly IList<ShapeAlterationBuilder> _alterationBuilders = new List<ShapeAlterationBuilder>();
public ShapeTableBuilder CreateTableBuilder(Feature feature) {
return new ShapeTableBuilder(_alterationBuilders, feature);
}
public IEnumerable<ShapeAlteration> BuildAlterations() {
return _alterationBuilders.Select(b => b.Build());
}
}
}
}

View File

@@ -1,13 +1,13 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.Environment.Extensions.Models;
namespace Orchard.DisplayManagement.Descriptors {
public class ShapeTableBuilder {
readonly IList<ShapeAlterationBuilder> _alterationBuilders;
readonly Feature _feature;
private readonly IList<ShapeAlterationBuilder> _alterationBuilders = new List<ShapeAlterationBuilder>();
private readonly Feature _feature;
public ShapeTableBuilder(IList<ShapeAlterationBuilder> alterationBuilders, Feature feature) {
_alterationBuilders = alterationBuilders;
public ShapeTableBuilder(Feature feature) {
_feature = feature;
}
@@ -17,5 +17,8 @@ namespace Orchard.DisplayManagement.Descriptors {
return alterationBuilder;
}
public IEnumerable<ShapeAlteration> BuildAlterations() {
return _alterationBuilders.Select(b => b.Build());
}
}
}

View File

@@ -23,6 +23,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
private readonly IVirtualPathProvider _virtualPathProvider;
private readonly IEnumerable<IShapeTemplateHarvester> _harvesters;
private readonly IEnumerable<IShapeTemplateViewEngine> _shapeTemplateViewEngines;
private readonly IParallelCacheContext _parallelCacheContext;
public ShapeTemplateBindingStrategy(
@@ -32,7 +33,9 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
ICacheManager cacheManager,
IVirtualPathMonitor virtualPathMonitor,
IVirtualPathProvider virtualPathProvider,
IEnumerable<IShapeTemplateViewEngine> shapeTemplateViewEngines) {
IEnumerable<IShapeTemplateViewEngine> shapeTemplateViewEngines,
IParallelCacheContext parallelCacheContext) {
_harvesters = harvesters;
_shellDescriptor = shellDescriptor;
_extensionManager = extensionManager;
@@ -40,6 +43,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
_virtualPathMonitor = virtualPathMonitor;
_virtualPathProvider = virtualPathProvider;
_shapeTemplateViewEngines = shapeTemplateViewEngines;
_parallelCacheContext = parallelCacheContext;
Logger = NullLogger.Instance;
}
@@ -59,7 +63,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
var activeFeatures = availableFeatures.Where(FeatureIsEnabled);
var activeExtensions = Once(activeFeatures);
var hits = activeExtensions.SelectMany(extensionDescriptor => {
var hits = _parallelCacheContext.RunInParallel(activeExtensions, extensionDescriptor => {
Logger.Information("Start discovering candidate views filenames");
var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => {
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
@@ -92,8 +96,8 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
return harvestShapeHits.Select(harvestShapeHit => new { harvestShapeInfo, harvestShapeHit, fileContext });
});
return shapeContexts.Select(shapeContext => new { extensionDescriptor, shapeContext });
});
return shapeContexts.Select(shapeContext => new { extensionDescriptor, shapeContext }).ToList();
}).SelectMany(hits2 => hits2);
foreach (var iter in hits) {