基准测试 Linq2SQL、Subsonic2、Subsonic3 - 有什么其他的想法使它们更快吗?

7

我已经使用Subsonic 2超过3年了...

在Linq出现之后,然后是Subsonic 3,我开始考虑转移到与SQL相关的新Linq futures。

我必须说,我开始移动和移植我的Subsonic 2到SubSonic 3,很快我发现速度非常慢,我不敢相信,并开始所有的测试。

然后我测试了Linq2Sql,也看到了延迟 - 与Subsonic 2进行比较。

我的问题在于,特别是对于linq2sql和即将推出的dotnet版本4,我还能做什么来加快速度?除了我用于测量的代码以外,还有哪些linq2sql设置或类可以使用?

我在这里放置了我进行测试的项目,以及结果的屏幕截图。

我如何进行测试 - 我的测量的准确性。

我只使用Google Chrome来回答我的问题,因为对我来说,在这里展示我使用更复杂程序进行的其他测量是困难的。这是最简单的一个,我只是测量数据读取。我如何证明呢?我做了一个简单的Thread.Sleep(10秒),看看我是否在Google Chrome测量中看到了那10秒钟,是的,我看到了。


(来源: planethost.gr)

这里有更多使用此Sleep线程进行测试的内容,以查看实际上Chrome给出了什么。

10秒延迟
100毫秒延迟
零延迟

只有一个小15ms的测量值,与我做的其他测试相比,它非常小,所以我不在意。

那么我测量了什么

我只测量通过每种方法读取的数据 - 没有计算任何数据或数据库延迟,也没有磁盘读取或任何其他类似的东西。稍后在结果图像中,我将展示测量中不存在任何磁盘活动。


查看此图像,了解我实际上测量了什么以及是否正确

为什么我选择这种测试方式

很简单,它是真实的,并且与我在真实程序中发现的Subsonic 3的延迟问题非常接近。

现在让我们测试DALs

从查看此图像开始。我在每个方法上都有4-5个调用,一个接一个。

结果是这样的。 循环100次,请求5行,其中一行不存在,大约如此。

简单adonet:81毫秒
SubSonic 2:210毫秒
linq2sql:1.70秒
使用CompiledQuery.Compile的linq2sql:239毫秒
Subsonic 3:15.00秒(哇 - 极慢)

项目 http://www.planethost.gr/DalSpeedTests.rar


任何人可以确认此基准测试,或进行任何优化以帮助我吗?

其他测试

有人在这里发布了这个链接 http://ormbattle.net/(然后删除它 - 不知道为什么)。在这个页面中,您可以找到真正有用的高级测试,适用于除了我这里的subsonic 2和subsonic 3之外的所有测试!

优化

我真正想问的是,是否有人可以知道如何通过更改每个dal上的代码和设置来优化DALs的任何技巧,而不是通过更改测试代码。 例如...

优化Linq2SQL

我开始搜索如何优化Linq2sql,并找到 这篇文章,可能还有更多。

最后我使用那页的技巧运行并优化了代码。速度接近1.50秒,从1.70秒提高了很多...大幅改善,但仍然很慢。

然后我发现了一篇不同方式 - 相同思路的文章,哇!速度飞起。 使用CompiledQuery.Compile这个技巧,从1.5秒的时间现在只需要239毫秒。 以下是预编译的代码...

Func<DataClassesDataContext, int, IQueryable<Product>> compiledQuery =
    CompiledQuery.Compile((DataClassesDataContext meta, int IdToFind) =>
                          (from myData in meta.Products
                           where myData.ProductID.Equals(IdToFind)
                           select myData));

StringBuilder Test = new StringBuilder();
int[] MiaSeira = { 5, 6, 10, 100, 7 };

using (DataClassesDataContext context = new DataClassesDataContext())
{
    context.ObjectTrackingEnabled = false;

    for (int i = 0; i < 100; i++)
    {
        foreach (int EnaID in MiaSeira)
        {
            var oFindThat2P = compiledQuery(context, EnaID);

            foreach (Product One in oFindThat2P)
            {
                Test.Append("<br />");
                Test.Append(One.ProductName);
            }
        }
    }
}

优化SubSonic 3和问题

我进行了许多性能分析,并逐一更改,速度有所提高,但仍然太慢。我在subsonic组中发布了它们,但他们忽略了这个问题,他们说一切都很快...

这里是我的性能分析和subsonic源代码中的延迟点的一些截图

我发现subsonic3对数据库结构的调用比对数据本身的调用更多。需要重新考虑请求数据的方式,并遵循subsonic2的思路(如果可能的话)。

尝试像我在linq2Sql中做的那样对subsonic 3进行预编译,但目前失败了...

优化SubSonic 2

在我发现subsonic 3极其缓慢之后,我开始检查subsonic 2 - 我以前从未这样做过,认为它很快。(确实如此)

因此,它提出了一些可以更快的点。例如,有许多类似这些的循环 实际上很慢,因为循环内部有字符串操作和比较。我必须告诉你,这段代码被调用了数百万次!在几分钟的时间内!从程序中请求数据。

对于小量的表和小字段,对于一些人来说可能不是什么大问题,

但是在大量的表上,延迟更加严重。因此,我决定通过自己替换字符串比较为数字比较来优化subsonic 2!简单。我几乎在每个性能分析器指出的缓慢点都进行了更改。我还更改了所有可以更快的小点,并禁用了一些不太使用的功能。

结果,在NorthWind数据库上快5%,在我的具有250个表的数据库上快近20%。在northwind上,10秒处理中少了500ms,在我的数据库上,500ms处理时间快了100ms。我没有截图展示它们,因为我用不同的代码、不同的时间制作了它们,并在纸上跟踪了它们。

无论如何,这就是我的故事和问题,你还知道什么可以使它们更快...

对于这些措施,我使用了由我优化的Subsonic 2.2、由我略微优化的Subsonic 3.0.0.3和Dot.Net 3.5。


看起来Subsonic 3测试存在一些问题。可能是配置错误? - Robert Harvey
亲爱的Adam,我已经上传了这个项目,源代码在里面,非常简单,请花点时间下载并自行查看。 - Aristos
Adam没问题,我会发布源代码。我想告诉你这只是一个简单的测试,我已经花了两个多星期来进行工作,并对速度进行了分析,试图找到瓶颈。实际上,你是正确的,这不是一个基准测试,而是它们之间的比较。 - Aristos
我经常使用Subsonic和MySQL,以前我使用自己的类和存储过程。其中一件事是我注意到Subsonic和MySQL需要额外的时间。我曾多次尝试解决这个问题,但Rob向我保证代码本身很快,所以我就将它放下了。不过这只是我使用MySQL时的情况。我的数据库在自己的服务器上,网站和数据库在同一个交换机上,只有1个跳跃。我曾经进行了一次步进调试,从数据库读取数据和写入数据都很快,但是在运行查询等操作时似乎会进行两次构建。但我没有足够的经验来评论质量。 - davethecoder
我没有时间那么担心或烦恼,因为工作太多了,客户很满意,所以我就这样放着。如果客户抱怨,那就会成为一个问题。 - davethecoder
显示剩余7条评论
5个回答

3
亲爱的Aristos,我遇到了一个问题。你在我们的小组里发了一个问题,我们进行了23封邮件的交流。你坚称SubSonic 3存在问题,并问我为什么没有修复这个“慢、不可用的工具”。
我试图向你解释,在233个表中,SubSonic必须在加载时读取每个表的模式。虽然这不是SubSonic 3的典型用法,但我们这样做实际上比SubSonic 2在后续的加载中更快。
你却无视了我的解释。我正在回答你。RBarry在上面留下了一条评论,说我在“贬低”你。我非常沮丧。你似乎认为我没有对这个东西进行基准测试,但事实上我已经测试过很多次了。我不能推出像你所建议的那样有问题的ORM,也确实没有。
你必须明白,如果SubSonic运行查询需要10秒钟,那么它就不会被使用。
所以,答案是:233个表作为类脚本化,需要在第一次运行时加载到提供程序内存中。
这太多了。SubSonic不是你的工具。

亲爱的Rob,我已经告诉你很多次了,我有4个数据库,只有一个有233个表,其他只有10个表。即使在那些只有10个表的数据库中也存在延迟问题。我的所有工作和报告都是为了帮助找出延迟原因,并修复它,或者告诉我如何纠正它。但是请注意,这里的测试是使用Northwind数据库。 - Aristos
Rob,我必须要给你表扬和感激之情,对于Subsonic 2和3。Subsonic 2很优秀,快速、易用,经过一些额外的优化后更加快速(为什么你没有赢得这些额外优化的源代码呢?)。我开始使用Subsonic 3,它更加简单、酷炫、美好,我很喜欢它 - 然而需要解决一下速度问题,接受并思考如何修复。实际上我很想问你,你使用了哪个工具来测量它们的速度?你看到了我的速度分析截图吗?你是否看到了Subsonic 3内部的实际延迟? - Aristos
Rob,这里非常有趣的是,你仍然否认问题的存在,并且不尝试看看你能做些什么来改进你的程序。你认为这个延迟不存在吗?这是一个罕见的情况吗?是我的错吗?为什么不接受它并尝试修复它?为什么不试着改进它?通过避免批评或告诉任何人“Subsonic不是你的工具”,你永远不会以这种方式制作出完美的工具,因为他们发现了需要改进的错误和改进。Rob,我对你没有任何意见,正如我所说,Subsonic 2非常酷且值得推荐,但Subsonic 3还需要改进。 - Aristos
2
提交一个补丁或者离开。我有点厌倦你的过度指责。 - user1151

1

根据您的示例,您可以通过使用以下代码来提高性能:

 StringBuilder Test = new StringBuilder();
 int[] MiaSeira = { 5, 6, 10, 100, 7 };
 for (int i = 0; i < 100; i++)
 {
     foreach (int EnaID in MiaSeira)
     {
         var Products = (from product in Product.
             where MiaSeira.Contains(product.ProductID)
             select product).ToList();

         if (Products == null || Products.Count == 0)
             continue;

         foreach (Product product in Products)
         {
            Test.Append("<br />");
            Test.Append(product.ProductName);
         }
     }
 }

 txtDebug.Text = Test.ToString();

Adam,感谢您花时间给我提供这个,但实际上我有其他想法。因此,我更新了文章,提供一个更好的想法。 - Aristos
3
我给出了一个解决方案,但你立刻改变了问题,现在你有什么想法? - Adam Cooper
我认为当以这种方式使用时,Products永远不会为空。而且,你可以使用Products.Any()代替Products.Count,它会返回列表中是否有记录的真假值。 - John Boker

1

我认为要更好地测试这些内容,你应该在 SQL Profiler 中检查时间,而不是在 Google Chrome 中,因为在浏览器中可能会有很多因素影响页面加载速度。


我已经禁用了所有的Google Chrome扩展,但是如果这个额外时间存在,那么对于所有的测试来说都是一样的。 - Aristos
这意味着如果您为一个ORM刷新页面,您将得到相同的数字,这是结果吗? - Amr Elgarhy
是的!你得到了相同的数字 - 我刷新页面1次进行编译,然后3次查看数字是否相同,然后我获得了截图。 - Aristos
对我来说,我使用的工具的速度非常关键,所以我需要知道并与他人分享这种经验,也许还能发现我犯过的任何错误。选择正确的工具至关重要,因为我会花时间去学习它,并在几个月甚至几年的开发中使用它。如果我发现自己犯了错误,那么回头再使用其他工具将是痛苦的。 - Aristos
亲爱的Amr,我已经更新了这篇文章,以证明谷歌浏览器实际上计算了我所要求的内容,同时我还加入了更多措施和更多细节。 - Aristos
感谢您提供这些信息的支持,真的很有帮助。 - Amr Elgarhy

1

你的速度测试是一个网页,我认为它看起来像你正在测试加载所需的时间。SubSonic并不是那么慢,而在网页中测试加载时间相当荒谬。

如果你想真正地对某个东西进行基准测试,你需要使用控制台,并运行针对索引数据的读取循环。你所做的是创建一个网页,并说“让我们看看在加载时会发生什么”。

这种方法存在很多缺陷。首先,所有编写的代码都需要从IL编译到ML。因为SubSonic为您生成代码,而且因为我知道您在这里有很多表(如果我没记错的话有300多个),您可以想象在初次加载时会有一些工作正在进行中。

说实话,在这里你的无经验正在破坏我为免费完成的大量工作,比如发布“它很慢,还没准备好”的言论。我不在乎人们是否使用SubSonic,但我很在乎人们是否做出愚蠢的事情(比如基准测试Web测试)并将责任归咎于我。


亲爱的罗布,我测量的速度是获取数据所需的时间。加载页面的时间是接下来的一个。这里有一个例子,请拿去随意制作新的例子,或改进此例子。 - Aristos
Rob,请花点时间自己进行一些测试,下载Chrome来看看它是如何工作和显示的。有一种非常简单的方法可以显示什么是慢的,什么不是 - 然而,某人不需要Chrome来测量速度,因为差异非常大,你可以立即感受到它的缓慢,这就是我理解的缓慢并开始进行测试的方式。 - Aristos
你的经验不足正在毁掉我免费付出的许多工作 - 免费并不是获取任何非工作内容的借口。你很有经验,为什么不加速呢?我想在这里指出,你没有谈论主题,即慢速度,而是攻击我说我经验不足,你的第二个论点是它是免费的。即使这两个论点是正确的,它们也不能改变我在这里发布的速度!!! - Aristos
3
因为你与问题的主题有个人关联而贬低一个诚实、聪明和经过深入研究的问题是不合适和不专业的。帖子作者的语言困难不是借口。 - RBarryYoung
Rob 在这里是正确的,SubSonic 在许多表上确实有显著的启动时间。就我所看,对于任何 Web 应用程序来说,这应该真的不是问题。15 秒的延迟来启动一个在服务器上运行不知道多长时间的 Web 应用程序。你真的应该调整基准测试,以在每个提供程序返回其第一个查询后计数。 - JTtheGeek
显示剩余4条评论

0

我对subsonic没有第一手的经验,但如果它正在执行大量的代码生成,您可能需要为第一个请求(冷启动)和后续请求的平均值(热启动)发布单独的结果。您还应该使用计时器来计时数据提取部分,以便您不会将其他时间混合到您的数据中。


好的,我会尽快完成,请给我一些时间。 - Aristos
Jimmy,我已经更新了文章,现在包括连续捕获4-5个请求以及许多其他信息。 - Aristos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接