More work on Event Bus optimization

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2013-02-23 11:05:41 -08:00
parent 7bd5c2851b
commit 0c711d4f4b
3 changed files with 33 additions and 26 deletions

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Autofac;
using NUnit.Framework;
@@ -24,11 +25,11 @@ namespace Orchard.Tests.Events {
builder.RegisterType<StubEventHandler2>()
.Named(typeof(ITestEventHandler).Name, typeof(IEventHandler))
.Named(typeof(IEventHandler).Name, typeof(IEventHandler))
.WithMetadata("Interfaces", typeof(StubEventHandler2).GetInterfaces().ToLookup(i => i.Name));
.WithMetadata("Interfaces", typeof(StubEventHandler2).GetInterfaces().ToDictionary(i => i.Name));
builder.RegisterInstance(_eventHandler)
.Named(typeof(ITestEventHandler).Name, typeof(IEventHandler))
.Named(typeof(IEventHandler).Name, typeof(IEventHandler))
.WithMetadata("Interfaces", typeof(StubEventHandler).GetInterfaces().ToLookup(i => i.Name));
.WithMetadata("Interfaces", typeof(StubEventHandler).GetInterfaces().ToDictionary(i => i.Name));
_container = builder.Build();
_eventBus = _container.Resolve<IEventBus>();
@@ -169,8 +170,7 @@ namespace Orchard.Tests.Events {
Assert.That(results, Has.Some.EqualTo("alpha"));
Assert.That(results, Has.Some.EqualTo("[42,alpha]"));
}
public interface ITestEventHandler : IEventHandler {
void Increment();
void Sum(int a);

View File

@@ -66,12 +66,12 @@ namespace Orchard.Environment.ShellBuilders {
.InstancePerLifetimeScope();
foreach (var interfaceType in item.Type.GetInterfaces()
.Where(itf => typeof(IDependency).IsAssignableFrom(itf)
.Where(itf => typeof(IDependency).IsAssignableFrom(itf)
&& !typeof(IEventHandler).IsAssignableFrom(itf))) {
registration = registration.As(interfaceType);
if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType)) {
registration = registration.InstancePerMatchingLifetimeScope("shell");
}
}
else if (typeof(IUnitOfWorkDependency).IsAssignableFrom(interfaceType)) {
registration = registration.InstancePerMatchingLifetimeScope("work");
}
@@ -83,11 +83,16 @@ namespace Orchard.Environment.ShellBuilders {
if (typeof(IEventHandler).IsAssignableFrom(item.Type)) {
var interfaces = item.Type.GetInterfaces();
foreach (var interfaceType in interfaces) {
// Register named instance for each interface, for efficient filtering inside event bus
registration = registration.Named(interfaceType.Name, typeof (IEventHandler));
// register named instance for each interface, for efficient filtering inside event bus
// IEventHandler subclasses onnly
if (interfaceType.IsSubclassOf(typeof(IEventHandler)) && interfaceType != typeof(IEventHandler)) {
registration = registration.Named(interfaceType.Name, typeof(IEventHandler));
}
}
// Keep interfaces in metadata for performance
registration = registration.WithMetadata("Interfaces", interfaces.ToLookup(i => i.Name));
// keep mapping between interface name and actual type
registration = registration.WithMetadata("Interfaces", interfaces.ToDictionary(i => i.Name));
}
foreach (var parameter in item.Parameters) {

View File

@@ -15,8 +15,7 @@ namespace Orchard.Events {
private readonly IExceptionPolicy _exceptionPolicy;
private static readonly ConcurrentDictionary<string, Tuple<ParameterInfo[], Func<IEventHandler, object[], object>>> _delegateCache = new ConcurrentDictionary<string, Tuple<ParameterInfo[], Func<IEventHandler, object[], object>>>();
public DefaultOrchardEventBus(IIndex<string, IEnumerable<Meta<IEventHandler>>> eventHandlers, IExceptionPolicy exceptionPolicy)
{
public DefaultOrchardEventBus(IIndex<string, IEnumerable<Meta<IEventHandler>>> eventHandlers, IExceptionPolicy exceptionPolicy) {
_eventHandlers = eventHandlers;
_exceptionPolicy = exceptionPolicy;
T = NullLocalizer.Instance;
@@ -52,7 +51,7 @@ namespace Orchard.Events {
private bool TryNotifyHandler(Meta<IEventHandler> eventHandler, string messageName, string interfaceName, string methodName, IDictionary<string, object> eventData, out IEnumerable returnValue) {
try {
return TryInvoke(eventHandler, interfaceName, methodName, eventData, out returnValue);
return TryInvoke(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue);
}
catch (Exception exception) {
if (!_exceptionPolicy.HandleException(this, exception)) {
@@ -64,21 +63,19 @@ namespace Orchard.Events {
}
}
private static bool TryInvoke(Meta<IEventHandler> eventHandler, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
var matchingInterfaces = ((ILookup<string, Type>)eventHandler.Metadata["Interfaces"])[interfaceName];
foreach (var interfaceType in matchingInterfaces) {
return TryInvokeMethod(eventHandler.Value, interfaceType, methodName, arguments, out returnValue);
}
returnValue = null;
return false;
private static bool TryInvoke(Meta<IEventHandler> eventHandler, string messageName, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
var interfaces = (IDictionary<string, Type>)eventHandler.Metadata["Interfaces"];
var matchingInterface = interfaces.Count == 1 ? interfaces.First().Value : interfaces[interfaceName];
return TryInvokeMethod(eventHandler.Value, matchingInterface, messageName, interfaceName, methodName, arguments, out returnValue);
}
private static bool TryInvokeMethod(IEventHandler eventHandler, Type interfaceType, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
var key = eventHandler.GetType().FullName + "_" + interfaceType.Name + "_" + methodName + "_" + String.Join("_", arguments.Keys);
private static bool TryInvokeMethod(IEventHandler eventHandler, Type interfaceType, string messageName, string interfaceName, string methodName, IDictionary<string, object> arguments, out IEnumerable returnValue) {
var key = eventHandler.GetType().FullName + "_" + messageName + "_" + String.Join("_", arguments.Keys);
var cachedDelegate = _delegateCache.GetOrAdd(key, k => {
var method = GetMatchingMethod(eventHandler, interfaceType, methodName, arguments);
return method != null
? Tuple.Create(method.GetParameters(), DelegateHelper.CreateDelegate<IEventHandler>(interfaceType, method))
return method != null
? Tuple.Create(method.GetParameters(), DelegateHelper.CreateDelegate<IEventHandler>(eventHandler.GetType(), method))
: null;
});
@@ -89,9 +86,9 @@ namespace Orchard.Events {
returnValue = result as IEnumerable;
if (returnValue == null && result != null)
returnValue = new[] { result };
return true;
return true;
}
returnValue = null;
return false;
}
@@ -115,6 +112,11 @@ namespace Orchard.Events {
}
}
// treating common case separately
if (candidates.Count == 1) {
return candidates[0];
}
if (candidates.Count != 0) {
return candidates.OrderBy(x => x.GetParameters().Length).Last();
}