dotnet C# calls the object assignment of the delegated GetInvocationList

This article is also called learning sex from Stephen Toub sql tutorial Can optimize the series. This is what I learned from Stephen Toub to optimize the performance of WPF framework. Under the hot path, that is, frequent calls java basic course If the GetInvocationList method of the delegate is called, it will not be created each time depending on the size of the delegate python basic tutorial New array objects of the same size, while in frequently called c# tutorial Module, a large number of objects will be created

As a delegate of the following code, of course vb.net tutorial The same is true for events

            Action action = Foo;
            for (int i = 0; i < 10; i++)
            {
                action += Foo;
            }

            static void Foo()
            {

            }

If the GetInvocationList method of action is called, some memory will be applied for each call. For example, use the following code for testing

            for (int i = 0; i < 100; i++)
            {
                var beforeAllocatedBytesForCurrentThread = GC.GetAllocatedBytesForCurrentThread();
                var invocationList = action.GetInvocationList();
                var afterAllocatedBytesForCurrentThread = GC.GetAllocatedBytesForCurrentThread();
                Console.WriteLine(afterAllocatedBytesForCurrentThread - beforeAllocatedBytesForCurrentThread);
            }

Getallocatedbytes forcurrentthread in the above code is a method at the GC level, which can be used to obtain the memory allocated by the current thread. This is a method used to assist debugging. For details, please see dotnet uses GC Getallocatedbytes forcurrentthread gets the memory size allocated by the current thread

You can see the console output at runtime as follows

312
112
112
112
112
112
112
112
112
112
112
112
// No water

This is because in the underlying implementation, the code for calling the GetInvocationList method is as follows

    public override sealed Delegate[] GetInvocationList()
    {
      Delegate[] delegateArray;
      if (!(this._invocationList is object[] invocationList))
      {
        delegateArray = new Delegate[1]{ (Delegate) this };
      }
      else
      {
        delegateArray = new Delegate[(int) this._invocationCount];
        for (int index = 0; index < delegateArray.Length; ++index)
          delegateArray[index] = (Delegate) invocationList[index];
      }
      return delegateArray;
    }

You can see that you need to re apply for the array every time, and then give the elements in the array. If the GetInvocationList method is called repeatedly in modules that call frequently, there will be a certain performance loss. For example, in WPF's mobile mouse and other logic

An optimization method is that if the specified delegate or event is incremented less than the number of calls to GetInvocationList, such as the pre notifyinput of WPF, it can be cached during incrementing, so that subsequent calls do not need to reallocate memory

For details of the above optimization, please see Avoid calling GetInvocationList on hot paths by stephentoub · Pull Request #4736 · dotnet/wpf

All the code in this article github And gitee Welcome to visit

You can obtain the source code of this article in the following ways. First create an empty folder, then use the command line cd command to enter this empty folder, and enter the following code on the command line to obtain the code of this article

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 6ed312e74e286d581e3d609ed555447474259ae4

The above uses the source of gitee. If gitee cannot access it, please replace it with the source of github

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

After getting the code, go to the FairhojafallJeeleefuyi folder

Keywords: C#

Added by redsox8185 on Sun, 16 Jan 2022 18:25:21 +0200