c# - 委托(delegate)和方法组的性能

标签 c# asp.net performance delegates

我正在研究创建 Cachedependency 对象的性能影响,所以我编写了一个非常简单的测试程序,如下所示:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web.Caching;

namespace Test
{
    internal class Program
    {
        private static readonly string[] keys = new[] {"Abc"};
        private static readonly int MaxIteration = 10000000;

        private static void Main(string[] args)
        {
            Debug.Print("first set");
            test2();
            test3();
            test4();
            test5();
            test6();
            test7();
            Debug.Print("second set");
            test7();
            test6();
            test5();
            test4();
            test3();
            test2();
        }

        private static void test2()
        {
            DateTime start = DateTime.Now;
            var list = new List<CacheDependency>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(new CacheDependency(null, keys));
            }

            Debug.Print("test2 Time: " + (DateTime.Now - start));
        }

        private static void test3()
        {
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(() => new CacheDependency(null, keys));
            }

            Debug.Print("test3 Time: " + (DateTime.Now - start));
        }

        private static void test4()
        {
            var p = new Program();
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(p.GetDep);
            }

            Debug.Print("test4 Time: " + (DateTime.Now - start));
        }

        private static void test5()
        {
            var p = new Program();
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(() => { return p.GetDep(); });
            }

            Debug.Print("test5 Time: " + (DateTime.Now - start));
        }

        private static void test6()
        {
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(GetDepStatic);
            }

            Debug.Print("test6 Time: " + (DateTime.Now - start));
        }

        private static void test7()
        {
            DateTime start = DateTime.Now;
            var list = new List<Func<CacheDependency>>();
            for (int i = 0; i < MaxIteration; i++)
            {
                list.Add(() => { return GetDepStatic(); });
            }

            Debug.Print("test7 Time: " + (DateTime.Now - start));
        }

        private CacheDependency GetDep()
        {
            return new CacheDependency(null, keys);
        }

        private static CacheDependency GetDepStatic()
        {
            return new CacheDependency(null, keys);
        }
    }
}

但我不明白为什么这些结果看起来像这样:

first set
test2 Time: 00:00:08.5394884
test3 Time: 00:00:00.1820105
test4 Time: 00:00:03.1401796
test5 Time: 00:00:00.1910109
test6 Time: 00:00:02.2041261
test7 Time: 00:00:00.4840277
second set
test7 Time: 00:00:00.1850106
test6 Time: 00:00:03.2941884
test5 Time: 00:00:00.1750100
test4 Time: 00:00:02.3561347
test3 Time: 00:00:00.1830105
test2 Time: 00:00:07.7324423

特别是:

  1. 为什么 test4test6 慢得多 比他们的委托(delegate)版本?我也 特别注意到Resharper 对委托(delegate)有意见 版本建议更改 test5test7 到“转换为方法组”。 与 test4test6 相同 但它们实际上更慢?
  2. 我似乎不是一个始终如一的人 调用时的性能差异 test4test6,不应该是静态的 调用总是更快?

最佳答案

在方法组 (4,6) 的测试中,C# 编译器不缓存委托(delegate) (Func) 对象。它每次都创造新的。在 7 和 5 中,它将 Action 对象缓存到调用您的方法的生成方法中。因此,从方法组创建 Funcs 非常慢(因为堆分配),但调用速度很快,因为操作点直接指向您的方法。由于 Func 被缓存,因此从 lambdas 创建 Action 很快,但它指向生成的方法,因此有一个不必要的方法调用。

注意并不是所有的 lambda 都可以被缓存(闭包会破坏这个逻辑)

关于c# - 委托(delegate)和方法组的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2448023/

相关文章:

c# - 使用 StringTemplate 输出 DataTable

asp.net - 防止 OWASP 十大漏洞的最佳库/实践

java - 重写 Java 类导致性能不佳?

mysql - 为了性能有必要用 'Limit 1'代替 'SQL SELECT'吗?

c# - 使用EF通过id删除一条记录,如果id不存在则抛出异常

c# - 键盘记录器如何显着提高 PostMessage() 的性能

javascript - 如何阻止用户即时输入格式错误的日期?

C# : How to calculate aspect ratio

php - 棘手的 MySQL 批量查询

c# - 类似于 gmail 的 "Report a bug"功能的库