2010-05-13 4 views
0

Я написал следующие тесты для сравнения производительности Linq2SQL и NHibernate, и я нахожу результаты несколько странными. Отображения являются прямыми и идентичными для обоих. Оба работают против живой БД. Хотя я не удаляю Кампании в случае Linq, но это не должно влиять на производительность более чем на 10 мс.Linq2SQL против производительности NHibernate (я сошел с ума?)

Linq:

[Test] 
    public void Test1000ReadsWritesToAgentStateLinqPrecompiled() 
    { 
     Stopwatch sw = new Stopwatch(); 
     Stopwatch swIn = new Stopwatch(); 
     sw.Start(); 
     for (int i = 0; i < 1000; i++) 
     { 
      swIn.Reset(); 
      swIn.Start(); 
      ReadWriteAndDeleteAgentStateWithLinqPrecompiled(); 
      swIn.Stop(); 
      Console.WriteLine("Run ReadWriteAndDeleteAgentState: " + swIn.ElapsedMilliseconds + " ms"); 
     } 

     sw.Stop(); 
     Console.WriteLine("Total Time: " + sw.ElapsedMilliseconds + " ms"); 
     Console.WriteLine("Average time to execute queries: " + sw.ElapsedMilliseconds/1000 + " ms"); 
    } 

    private static readonly Func<AgentDesktop3DataContext, int, EntityModel.CampaignDetail> 
     GetCampaignById = 
      CompiledQuery.Compile<AgentDesktop3DataContext, int, EntityModel.CampaignDetail>(
       (ctx, sessionId) => (from cd in ctx.CampaignDetails 
            join a in ctx.AgentCampaigns on cd.CampaignDetailId equals a.CampaignDetailId 
            where a.AgentStateId == sessionId 
            select cd).FirstOrDefault()); 

    private void ReadWriteAndDeleteAgentStateWithLinqPrecompiled() 
    { 
     int id = 0; 
     using (var ctx = new AgentDesktop3DataContext()) 
     { 
      EntityModel.AgentState agentState = new EntityModel.AgentState(); 
      var campaign = new EntityModel.CampaignDetail { CampaignName = "Test" }; 
      var campaignDisposition = new EntityModel.CampaignDisposition { Code = "123" }; 
      campaignDisposition.Description = "abc"; 
      campaign.CampaignDispositions.Add(campaignDisposition); 
      agentState.CallState = 3; 

      campaign.AgentCampaigns.Add(new AgentCampaign 
      { 
       AgentState = agentState 
      }); 
      ctx.CampaignDetails.InsertOnSubmit(campaign); 
      ctx.AgentStates.InsertOnSubmit(agentState); 
      ctx.SubmitChanges(); 
      id = agentState.AgentStateId; 
     } 

     using (var ctx = new AgentDesktop3DataContext()) 
     { 
      var dbAgentState = ctx.GetAgentStateById(id); 
      Assert.IsNotNull(dbAgentState); 
      Assert.AreEqual(dbAgentState.CallState, 3); 
      var campaignDetails = GetCampaignById(ctx, id); 

      Assert.AreEqual(campaignDetails.CampaignDispositions[0].Description, "abc"); 
     } 

     using (var ctx = new AgentDesktop3DataContext()) 
     { 
      ctx.DeleteSessionById(id); 
     } 
    } 

NHibernate (петля одно и то же):

private void ReadWriteAndDeleteAgentState() 
    { 
      var id = WriteAgentState().Id; 
      StartNewTransaction(); 

      var dbAgentState = agentStateRepository.Get(id); 

      Assert.IsNotNull(dbAgentState); 
      Assert.AreEqual(dbAgentState.CallState, 3); 
      Assert.AreEqual(dbAgentState.Campaigns[0].Dispositions[0].Description, "abc"); 

      var campaignId = dbAgentState.Campaigns[0].Id; 
      agentStateRepository.Delete(dbAgentState); 

      NHibernateSession.Current.Transaction.Commit(); 

      Cleanup(campaignId); 

      NHibernateSession.Current.BeginTransaction(); 
    } 

Результаты:

NHibernate: 
Total Time: 9469 ms 
Average time to execute 13 queries: 9 ms 

Linq: 
Total Time: 127200 ms 
Average time to execute 13 queries: 127 ms 

Linq потеряли 13,5 раза! Событие с предварительно скомпилированными запросами (оба запроса на чтение предварительно скомпилированы).

Это не может быть прав, хотя я ожидал, что NHibernate будет быстрее, это слишком большая разница, поскольку сопоставления идентичны, а NHibernate фактически выполняет больше запросов к БД.

Обновление. Я реорганизовал проект для использования NHibernate вместо Linq2Sql, и увеличение производительности, по-видимому, намного меньше (около 20-30%) по сравнению с тестом, работающим с одними и теми же сопоставлениями. Есть ли у кого-нибудь свои реальные примеры?

+0

Почему вы удивлены? Люди, которые знают ORM (или пишут сами), обычно думают, что LING (и EF) не являются точно «вершиной линии» в данный момент;) 3-й класс. Может быть;) – TomTom

ответ

1

Запустите профилировщик, как в коде .NET, так и в базе данных SQL Server. Также определите, какие операторы SQL выполняются под обложками для обоих сценариев. Где потеряно время для LinqToSql? Если базовые инструкции SQL различны, почему? Скорее всего, вы можете настроить оба ORM на более быструю работу. Вероятно, они должны быть в одном и том же рабочем месте, для простых тестов. Это похоже на проблему конфигурации.

+0

Ну, с одной стороны, вы не можете предварительно компилировать запросы для вставок, обновлений и удалений в linq, в то время как в NH они генерируются один раз во время процесса сопоставления. Я не уверен в фактическом SQL, это не имеет значения, поскольку DB пуст, но Linq больше всего проигрывает в QueryBuilders. –

Смежные вопросы