About C # delegate creation performance

There are a lot of thoughts in my project. So, I fixed the delegates in the dictionaries. The problem is that I decided to use MethodInfo as dict keys, I tried to use a search method that looks something like this:

Func<T,R> LookUp(Func<T,R> m) { return (Func<T,R>)dict[m.Method]; } //LookUp(MyCls.Method) 

But after several tests, I found out that giving the LookUp method using the function address, i.e. creating transition delegates on the fly, pretty slow, really slow:

 class MyCls { public static void Operate(int whatever){ } } class MainClass { delegate void Doer<T>(T arg); static Dictionary<MethodInfo,Delegate> _dict = new Dictionary<MethodInfo,Delegate>(); public static void Main (string[] args) { Action<int> dg = MyCls.Operate; _dict[dg.Method] = Delegate.CreateDelegate(typeof(Action<int>),dg.Method); //performance test var start = Environment.TickCount; for (int i = 0; i < 10000000; i++) { //LookUp(dg);//11 //LookUp<int>(MyCls.Operate);//1503 //new MyCls();//431 } Console.WriteLine (Environment.TickCount-start); } static Action<T> LookUp<T>(Action<T> dg) { //should return (Action<T>)_dict[dg.Method]; return null; } 

So the question is this: to improve performance, should I change my approach and write some unsafe code (Are pointers to objects even supported by C #?) Or are there alternative solutions for such C # situations?

Please help me out of there!

+6
source share
3 answers

I used the class some time ago to aggregate events (Mediator) in a Winform application that had a dictionary cache of type "as key" and "Delegate as value". The class looks something like this ...

 public sealed class EventAggregator { #region Fields private readonly Dictionary<Type, List<Object>> subscribers = new Dictionary<Type, List<Object>>(); #endregion #region Public Methods public void Subscribe<TMessage>(Action<TMessage> handler) { if (subscribers.ContainsKey(typeof(TMessage))) { var handlers = subscribers[typeof(TMessage)]; handlers.Add(handler); } else { var handlers = new List<Object> {handler}; subscribers[typeof(TMessage)] = handlers; } } public void Unsubscribe<TMessage>(Action<TMessage> handler) { if (subscribers.ContainsKey(typeof(TMessage))) { var handlers = subscribers[typeof(TMessage)]; handlers.Remove(handler); if (handlers.Count == 0) { subscribers.Remove(typeof(TMessage)); } } } public void Publish<TMessage>(TMessage message) { if (subscribers.ContainsKey(typeof(TMessage))) { var handlers = subscribers[typeof(TMessage)]; foreach (Action<TMessage> handler in handlers) { handler.Invoke(message); } } } #endregion } 

which, I think, is somewhat similar to what you are trying to do.

Instead of looking for the delegate itself, try finding the type for which this delegate is required.

+1
source

In general, using interfaces will always be better in terms of performance than using delegates / reflection.
Do you have control over objects to use the interface instead of delegates?

+1
source

Delegates are reference types that encapsulate a function, so they are essentially pointers to functions.

It seems to me that you are trying to create some kind of function repository. If all functions match the Func signature, then use this and do not use the generic Delegate class.

Alternatively, if you want to store all different types of delegates with different signatures using the Delegate class, you should probably use the .DynamicInvoke () method instead of MethodInfo, since your key uses something simpler, like a string or a return function value or some combination.

Here is a simple example of what I mean by various methods for LookUp,

 class FunctionRepository : List<Delegate> // could also be a Dictionary<,> { public R Invoke<R>(string name, params object[] args) { var _delegate = this.Single(x => x.Method.ReturnType == typeof(R) && x.Method.Name == name); return (R)_delegate.DynamicInvoke(args); } public Func<R> LookUp<R>(string name, params object[] args) { var _delegate = this.Single(x => x.Method.ReturnType == typeof(R) && x.Method.Name == name); return () => (R)_delegate.DynamicInvoke(args); } public Func<Object[], R> LookUp<R>(string name) { var _delegate = this.Single(x => x.Method.ReturnType == typeof(R) && x.Method.Name == name); return (args) => (R)_delegate.DynamicInvoke(args); } } 
0
source

Source: https://habr.com/ru/post/893741/


All Articles