Linq to Entities表现/功能之间的性能差异 [英] Linq to Entities performance difference between Expression/Func

查看:91
本文介绍了Linq to Entities表现/功能之间的性能差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是测试一个简单的查询,我以不同的方式访问,但每个的速度可以变化最多2秒。我希望有人能澄清为什么会这样。我的项目是在很早的阶段,所以我以为我会确定我在做的太大了之前。



诚然,我的测试风格并不完美,但我认为这样做够好。



'使用通用的Repository和UnitofWork,并且我在这个语句中打数据库(本地机器上的sqlexpress)10,000次。该表只有64条记录。测试运行在发布模式。

  [TestMethod] 
public void MyTestMethod()
{
using(var u = new UnitOfWork())
{
TestA(u);
TestB(u);
}
}

TestA(Func):

  public void TestA(UnitOfWork u)
{
秒表s = Stopwatch.StartNew();
s.Start();
var x = 0;
var repo = u.Repository< MyEntity>();
var code =ABCD.First()。ToString();
while(x< 10000)
{
var testCase = repo.Single(w => w.Code == code&& w.CodeOrder == 0) ;
x ++;
}
s.Stop();

Console.WriteLine(TESTA:+ s.Elapsed);
}

TestB(Expression):

  public void TestB(UnitOfWork u)
{
秒表s = Stopwatch.StartNew();
s.Start();
var x = 0;
var repo = u.Repository< MyEntity>();
var code =ABCD.First()。ToString();
while(x< 10000)
{
var testCase = repo.First(w => w.Code == code&& w.CodeOrder == 0) ;
x ++;
}
s.Stop();
Console.WriteLine(TESTB:+ s.Elapsed);
}

即使我正在使用电话 First ) Single(),它们不是内置的LINQ调用。他们是我的存储库的一部分。



First() expression(IQueryable)

  public TEntity Single(Func< TEntity,bool>谓词)
{
return dbSet.FirstOrDefault(predicate);
}

Single() func(IEnumerable)

  public TEntity First(Expression< Func< TEntity,bool>> predicate)
{
return dbSet.FirstOrDefault(predicate);
}

输出:

$ b $测试结果:通过

结果StandardOutput:

TESTA: 00:00:02.4798818
TESTB:00:00:03.4212112


解决方案

这不是一个答案,而只是试图确保测试结果更可靠。



尝试写这样的测试:

  public long TestA()
{
using(var u = new UnitOfWork())
{
var s = Stopwatch.StartNew();
var x = 0;
var repo = u.Repository< MyEntity>();
var code =ABCD.First()。ToString();
while(x< 10000)
{
var testCase = repo.Single(w => w.Code == code&& w.CodeOrder == 0) ;
x ++;
}
s.Stop();
return s.ElapsedMilliseconds;
}
}

(显然 TestB 只是一个小的变体。)



然后你的测试方法变成:

  [TestMethod] 
public void MyTestMethod()
{
var dummyA = TestA();
var dummyB = TestB();

var realA = 0L;
var realB = 0L; $ var $ i $ = $;
$
realB + = TestB();
}

Console.WriteLine(TESTA:+ realA.ToString());
Console.WriteLine(TESTB:+ realA.ToString());
}

现在,您的结果可能更准确。让我们知道现在的时间。






现在尝试更改这样的测试:

  public int TestA()
{
var gc0 = GC.CollectionCount(0);
using(var u = new UnitOfWork())
{
var s = Stopwatch.StartNew();
var x = 0;
var repo = u.Repository< MyEntity>();
var code =ABCD.First()。ToString();
while(x< 10000)
{
var testCase = repo.Single(w => w.Code == code&& w.CodeOrder == 0) ;
x ++;
}
s.Stop();
}
return GC.CollectionCount(0) - gc0;
}

这应该确定正在执行多少代0个垃圾回收。这可能表明性能问题是您的测试而不是SQL。


I was just testing a simple query that i'm accessing in different ways, but the speed of each can vary by up to 2 seconds. I was hoping someone can clarify why this is the case. My project is in it's very early stages, so I thought I'd make sure I'm doing it right before it gets too big.

Admittedly, my testing style isn't perfect, but i think it's good enough for this.

I'm using a generic Repository and UnitofWork, and I hit the DB (sqlexpress on my local machine) 10,000 times in this while statement. The table only has 64 records. Tests are run in Release mode.

[TestMethod]
public void MyTestMethod()
{
    using (var u = new UnitOfWork())
    {
        TestA(u);
        TestB(u);
    }
}

TestA (Func):

public void TestA(UnitOfWork u)
{
    Stopwatch s = Stopwatch.StartNew();
    s.Start();
    var x = 0;
    var repo = u.Repository<MyEntity>();
    var code = "ABCD".First().ToString();
    while (x < 10000)
    {
        var testCase = repo.Single(w => w.Code == code && w.CodeOrder == 0).Name;
        x++;
    }
    s.Stop();

    Console.WriteLine("TESTA: " + s.Elapsed);
}

TestB (Expression):

public void TestB(UnitOfWork u)
{
    Stopwatch s = Stopwatch.StartNew();
    s.Start();
    var x = 0;
    var repo = u.Repository<MyEntity>();
    var code = "ABCD".First().ToString();
    while (x < 10000)
    {
        var testCase = repo.First(w => w.Code == code && w.CodeOrder == 0).Name;
        x++;
    }
    s.Stop();
    Console.WriteLine("TESTB: " + s.Elapsed);
}

Even though i'm using the calls First() and Single(), they're not the built-in LINQ calls. They're part of my repository.

First() expression (IQueryable)

public TEntity Single(Func<TEntity, bool> predicate)
{
    return dbSet.FirstOrDefault(predicate);
}

Single() func (IEnumerable)

public TEntity First(Expression<Func<TEntity, bool>> predicate)
{
    return dbSet.FirstOrDefault(predicate);
}

Output:

Test Name: MyTestMethod
Test Outcome: Passed

Result StandardOutput:  

TESTA: 00:00:02.4798818
TESTB: 00:00:03.4212112

解决方案

This is not an answer, but just trying to make sure that the test results are more reliable.

Try writing your tests like this:

public long TestA()
{
    using (var u = new UnitOfWork())
    {
        var s = Stopwatch.StartNew();
        var x = 0;
        var repo = u.Repository<MyEntity>();
        var code = "ABCD".First().ToString();
        while (x < 10000)
        {
            var testCase = repo.Single(w => w.Code == code && w.CodeOrder == 0).Name;
            x++;
        }
        s.Stop();
        return s.ElapsedMilliseconds;
    }
}

(Obviously TestB is just a minor variant.)

And then your test method becomes:

[TestMethod]
public void MyTestMethod()
{
    var dummyA = TestA();
    var dummyB = TestB();

    var realA = 0L;
    var realB = 0L;
    for (var i = 0; i < 10; i++)
    {
        realA += TestA();
        realB += TestB();
    }

    Console.WriteLine("TESTA: " + realA.ToString());
    Console.WriteLine("TESTB: " + realA.ToString());
}

Now your results are likely to be more accurate. Let us know the timings now.


Now try changing your tests like this:

public int TestA()
{
    var gc0 = GC.CollectionCount(0);
    using (var u = new UnitOfWork())
    {
        var s = Stopwatch.StartNew();
        var x = 0;
        var repo = u.Repository<MyEntity>();
        var code = "ABCD".First().ToString();
        while (x < 10000)
        {
            var testCase = repo.Single(w => w.Code == code && w.CodeOrder == 0).Name;
            x++;
        }
        s.Stop();
    }
    return GC.CollectionCount(0) - gc0;
}

This should determine how many generation 0 garbage collections are being performed. That might indicate that the performance issues are with your tests and not with the SQL.

这篇关于Linq to Entities表现/功能之间的性能差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆