Subsonic 与simplerepository相比,使用activerecord的亚音速linq速度非常慢

Subsonic 与simplerepository相比,使用activerecord的亚音速linq速度非常慢,subsonic,performance,Subsonic,Performance,有人知道为什么linq查询在使用active record和simplerepository进行查询时速度要慢6倍吗? 下面的代码运行速度比我使用简单存储库查询数据时慢6倍。此代码在循环中执行1000次 提前谢谢 string ret = ""; // if (plan == null) { plan =VOUCHER_PLAN.SingleOrDefault(x => x.TENDER_TYPE ==

有人知道为什么linq查询在使用active record和simplerepository进行查询时速度要慢6倍吗? 下面的代码运行速度比我使用简单存储库查询数据时慢6倍。此代码在循环中执行1000次

提前谢谢

        string ret = "";            
//      if (plan == null)
        {
           plan =VOUCHER_PLAN.SingleOrDefault(x => x.TENDER_TYPE == tenderType);
        }
        if (plan == null)
           throw new InvalidOperationException("voucher type does not exist." + tenderType);

        seq = plan.VOUCHER_SEQUENCES.First();
        int i = seq.CURRENT_NUMBER;
        seq.CURRENT_NUMBER += seq.STEP;
        seq.Save();

通过缓存在构造函数/init过程中创建的数据库实例,我能够在性能上产生巨大的差异。我现在看到的是~2-3倍的加速,这取决于情况和跑步

1)如果只调用默认构造函数,用静态实例替换_db的方法效果很好,并且具有相同的速度优势

// MyProject.MyDB _db;
// replace with a static instance, and remove the "this." from other lines
static MyProject.MyDB _db = new MyDB();

public MyClass() {
    //_db=new MyProject.MyDB();
    Init();
}
2)我为DB条目编写了一个小的缓存类,并在所有使用“new()”的旧位置从我的ActiveRecord.tt文件中调用它

// REPLACE "MyDB" with the name of your DB.  Alternately, include this 
// class in Context.tt and have it generate the correct name.  

class ContextDatabaseCache {        

    public static MyDB GetMyDB()
    {
        return GetInstance("~~default~~", () => new MyDB());
    }

    public static MyDB GetMyDB(string connectionString) {
        return GetInstance(connectionString, () => new MyDB(connectionString));
    }

    public static MyDB GetMyDB(string connectionString, string providerName)
    {
        return GetInstance(connectionString + providerName, () => new MyDB(connectionString, providerName));
    }

    private static Dictionary<string, MyDB> _dict = new Dictionary<string, MyDB>();
    private static MyDB GetInstance(string key, Func<MyDB> createInstance)
    {
        if (!_dict.ContainsKey(key)) {               
            lock (_dict) {
                if (!_dict.ContainsKey(key)) {
                    _dict.Add(key, createInstance());
                }
            }
        }
        return _dict[key];
    }

    ///<summary>Call this when the "DefaultConnection" string changes in the
    ///         App.exe.config file so that a new db instance will be created
    ///         and pick up the changed value. </summary>
    public static void Clear() {
         _dict.Clear();
    }

}
//用数据库的名称替换“MyDB”。或者,包括这个
//在Context.tt中初始化,并使其生成正确的名称。
类ContextDatabaseCache{
公共静态MyDB GetMyDB()
{
返回GetInstance(“~~默认值~~”,()=>newmydb());
}
公共静态MyDB GetMyDB(字符串连接字符串){
返回GetInstance(connectionString,()=>newmydb(connectionString));
}
公共静态MyDB GetMyDB(字符串连接字符串,字符串提供程序名称)
{
返回GetInstance(connectionString+providerName,()=>newMyDB(connectionString,providerName));
}
私有静态字典_dict=new Dictionary();
私有静态MyDB GetInstance(字符串键,Func createInstance)
{
如果(!_dict.ContainsKey(key)){
锁{
如果(!_dict.ContainsKey(键)){
_dict.Add(key,createInstance());
}
}
}
返回_dict[键];
}
///当“DefaultConnection”字符串在
///App.exe.config文件,以便创建新的db实例
///并提取更改后的值。
公共静态无效清除(){
_格言(Clear);
}
}
这是在ActiveRecord.tt文件中进行的替换类型:

public <#=tbl.ClassName#>(){
    _db=new <#=Namespace#>.<#=DatabaseName#>DB();
    Init();            
}

    // becomes this: 
public <#=tbl.ClassName#>(){
    _db= <#=Namespace#>.ContextDatabaseCache.Get<#=DatabaseName#>DB();
    Init();            
}
public(){
_db=new.db();
Init();
}
//变成这样:
公众(){
_db=.ContextDatabaseCache.GetDB();
Init();
}
显然,亚音速“不是问题”,尽管他们知道这是存在的。它不会被修复。您必须使用蹩脚的批处理查询语法才能获得此结果,没有人会这么做

我不明白的是,这是90%的情况。从表中获取记录列表。它应该是快的,而不是慢的。每个人都这样做,无论何时何地


亚音速有很多问题。我不得不为DB field=>object field查找写缓存,因为它们也非常慢。

我们对此做了一些分析,发现亚音速的记录。SingleOrDefault(x=>x.id=someval)比通过Codinghoror完成的相同查询慢20倍。在此处记录:

探查器在ExecutionBuilder.cs中指出了这一点:

// this sucks, but since we don't track true SQL types through the query, and ADO throws exception if you
// call the wrong accessor, the best we can do is call GetValue and Convert.ChangeType
Expression value = Expression.Convert(
    Expression.Call(typeof (Convert), "ChangeType", null,
                    Expression.Call(reader, "GetValue", null, Expression.Constant(iOrdinal)),
                    Expression.Constant(TypeHelper.GetNonNullableType(column.Type), typeof(Type))
        ),
    column.Type
    );
令人失望,因为我真的很喜欢亚音速/Linq


最后我们放弃了,我写了这个-。移植后,我们的负载测试显示每秒请求数增加,CPU负载从大约80%下降到5%。

您是否比较了为ActiveRecord/SimpleRepository执行的SQL?您是否按照Adam的建议执行了。我很想知道你是否能找到答案。有趣的是,我分析了SQL,没有呼叫需要超过几毫秒的时间。它似乎在应用程序中的某个地方受到了瓶颈制约:/你注意到你的凭单计划构造函数被呼叫了很多次吗?你可能会有某种ToList()在那里实例化你所有的值,但除了尝试SimpleRepository,我真的不知道如何避免它。我也有同样的问题,这让我发疯。获取350条记录的列表和查询/otw时间甚至无法测量。但是,由于未知的原因,创建这些对象仍然需要2秒多的时间。嗨,安德鲁,你说得对。使用1.0.3时,我非常喜欢亚音速。加快发展,加快实施。但是当我们把它移植到3.0时,我遇到了很多与速度有关的麻烦。我们现在正在尝试2.1,因为我们无法完全改变亚音速。Linq查询的执行时间是以前的两倍。谢谢你关于数据库缓存的帖子。请提供DB field=>对象字段查找的代码。这会有很大的帮助。(删除电子邮件地址)谢谢教授,我查阅了我所有的代码,没有看到亚音速的.TT变化。这是以前的工作,所以我可能不会带着它们。我认为它只是遵循了正常的“查找它的位置,编写一个简单的基于hashmap的缓存,然后使用它”模式,就像这里一样