【问题标题】:Caching compiled lambda expressions缓存已编译的 lambda 表达式
【发布时间】:2009-09-22 18:28:58
【问题描述】:

我需要将一些信息作为 lambda 表达式传递给某些方法。基本上,这是一种向数据库查询添加信息的方法。一个简单的例子是:

companyData.GetAll(
   where => "SomeField = @SOMEFIELD",
   order => "Id",
   SOMEFIELD => new Parameter {DbType = DbType.String, Value = "some value"}
)

它工作得很好,除了我需要调用LambdaExpression.Compile 来获取参数对象,这对性能影响很大。

为了获得更快的结果,我提供了这个简单的缓存测试:

class ExpressionCache<T,U>
{

    private static ExpressionCache<T, U> instance;
    public static ExpressionCache<T, U> Instance
    {
        get
        {
            if (instance == null) {
                instance = new ExpressionCache<T, U>();
            }
            return instance;
        }
    }

    private ExpressionCache() { }

    private Dictionary<string, Func<T, U>> cache = new Dictionary<string, Func<T, U>>();

    public Func<T, U> Get(Expression<Func<T, U>> expression)
    {
        string key = expression.Body.ToString();
        Func<T,U> func;
        if (cache.TryGetValue(key, out func)) {
            return func;
        }
        func = expression.Compile();
        cache.Add(key, func);
        return func;
    }
}

这个类有很大的不同:从 10000 次迭代的大约 35000 毫秒到大约 700 毫秒。

现在问题来了:使用表达式主体作为字典的键我会遇到什么样的问题?

【问题讨论】:

    标签: c# performance lambda


    【解决方案1】:

    如果您将表达式树编译为委托,我不清楚为什么您需要表达式树。为什么不直接使用委托开始并让编译器将 lambda 表达式转换为委托而不是表达式树?

    至于使用字符串的主体 - 您可能会遇到奇怪的情况,即使用不同的类型但使用相同的属性名称。但是,鉴于您已经将类型用作泛型类型参数,这可能不是问题......我认为它会起作用,尽管我想发誓。 p>

    哦,顺便说一下,您的单例缓存不是线程安全的。我建议您在静态初始化程序中初始化 instance 变量。这导致更简单的代码以及更安全...

    private static readonly ExpressionCache<T, U> instance
         = new ExpressionCache<T, U>();
    public static ExpressionCache<T, U> Instance { get { return instance; } }
    

    【讨论】:

    • +1 表示“哦,顺便说一下,你的单例缓存不是线程安全的。”
    • @Jon:我知道不是线程安全的。这只是一个测试。感谢您提出“公正代表”的想法。我想我对这个 lambda 东西太菜鸟了。
    【解决方案2】:

    Lambda 表达式可以创建闭包。发生这种情况时,表达式主体不会包含进入结果代码的所有内容。您可能会遗漏其中包含的潜在重要局部变量。

    【讨论】:

    • 任何解决方案仍然可以实现缓存?
    猜你喜欢
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2017-01-06
    相关资源
    最近更新 更多