Как правильно профилировать Entity Framework? - PullRequest
21 голосов
/ 07 июля 2011

Какой минимальный объем кода я могу написать, чтобы получить один обратный вызов от EF 4.1, который обеспечивает следующее:

  • OnSQLExecuted(DbCommand cmd, DateTime start, double durationMS, string stacktrace)

В данный моментмы используем неприятный хак, который, похоже, снижает производительность, мне интересно, как мы можем добиться этого обратного вызова с минимальным влиянием на приложение.


Мы можем подключить это в Mini Profiler путем хакерства вокруг - изначально мы изменили Database.DefaultConnectionFactory, однако при взломе с заводскими настройками по умолчанию вы можетене иметь двух профилирующих фабрик, работающих одновременно.Поэтому мы пошли по более агрессивному маршруту.


Обычно используемая техника довольно проста, вы реализуете: DbProviderFactory, IDbConnectionFactory, DbProviderServices, DbConnection, DbCommand и DbDataReader таким образом, что ониперехватывать звонки и профиль.

Пока просто, просто ... однако, когда вы пытаетесь подключить это, все становится грязно:

   try
    {
        // ensure all the factories are loaded 
        DbProviderFactories.GetFactory("...");
    }
    catch (ArgumentException)
    {
    }

    Type type = typeof(DbProviderFactories);

    DataTable table;
    // SUPER UGLY - Can this be done in another way? 
    object setOrTable = (type.GetField("_configTable", BindingFlags.NonPublic | BindingFlags.Static) ??
                    type.GetField("_providerTable", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
    if (setOrTable is DataSet)
    {
        table = ((DataSet)setOrTable).Tables["DbProviderFactories"];
    }

    table = (DataTable)setOrTable;

    foreach (DataRow row in table.Rows.Cast<DataRow>().ToList())
    {
        DbProviderFactory factory;
        try
        {
            factory = DbProviderFactories.GetFactory(row);
        }
        catch (Exception)
        {
            continue;
        }

        var profType = typeof(MvcMiniProfiler.Data.EFProfiledDbProviderFactory<>).MakeGenericType(factory.GetType());


        DataRow profiled = table.NewRow();
        profiled["Name"] = row["Name"];
        profiled["Description"] = row["Description"];
        profiled["InvariantName"] = row["InvariantName"];
        profiled["AssemblyQualifiedName"] = profType.AssemblyQualifiedName;
        table.Rows.Remove(row);
        table.Rows.Add(profiled);

    }

Требуется несколько взломов отражений и полных бомб на последней версии EF:

FileLoadException: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)

Это было задокументировано как Франс и Айенде .

Как подключить мои профилирующие фабрики инадежную и элегантную семью?
Есть ли другой способ вернуть мой звонок?

Ответы [ 4 ]

10 голосов
/ 07 июля 2011

Самый простой способ - использовать оболочки трассировки Entity Framework и подключиться к EFTracingConnection s CommandFinished. Он не дает вам времени начала, но он дает вам продолжительность (которая, вычитаемая из Now, вероятно, достаточно близка).

Я бы назвал влияние кода «умеренным», поскольку вам нужно изменить ссылки на существующий класс контекста. Впрочем, это довольно просто.

Если вам просто нужна трассировка и вам не нужен реальный обратный вызов, пакет NuGet имеет простую систему трассировки по умолчанию .

Редактировать (добавлена ​​трассировка стека): Оболочки трассировки EF не дают трассировки стека. Вы можете получить исходный код и добавить его без особых проблем, но я думаю, что это повлияет на производительность.

7 голосов
/ 07 июля 2011

Хотя это коммерческий продукт, я бы настоятельно рекомендовал посмотреть EF Prof .Этот инструмент был разработан Ayende (орен Eini spelling?), Который также сделал NH Prof, Uber Prof (NH + EF Prof) и RavenDB среди других продуктов.был неоценим, и я ожидал, что EF Prof будет таким же ценным, соответственно.

0 голосов
/ 29 августа 2011

Я могу порекомендовать Entity Framework Profiler, и месячная подписка подходит для вас с минимальной стоимостью 16 долларов США в месяц. У нас были некоторые проблемы с производительностью DbContext, и он предоставил хорошую визуальную информацию для их устранения. Вы можете интегрировать EF Profiler со своим сервером непрерывной интеграции и постоянно повышать свою производительность.

http://efprof.com/

0 голосов
/ 08 июля 2011

Во-первых: если вы ищете пользовательскую реализацию, где вы можете инициировать собственное событие непосредственно в EF, забудьте об этом.Команда ADO.NET почему-то забыла реализовать какие-либо точки расширения, и они даже забыли реализовать какую-либо запись в журнал (кроме преобразования ObjectQuery / DbQuery в SQL, но он не обрабатывает отложенную загрузку или изменение данных).

Я полагаю, что каждая реализация трассировки, используемая в EF, создается путем создания пользовательской DbProviderFactory, которая упаковывает настоящую фабрику и упаковывает реальные Connection, Command и т. Д. Это очень четко описано в упомянутых оболочках трассировки.

Есть коммерческие инструменты, которые уже делают то, что вы хотите

  • Упомянутое EF Prof - отличный инструмент, но он стоит 300 долларов за место.
  • Альтернатива Huagati Query Profiler .Особенно этот снимок экрана выглядит так, как вы ищете.Цена намного ниже (40 долларов за место), и он поддерживает Linq-to-sql, Entity Framework и LLBLGen.

Оба инструмента имеют бесплатную пробную версию, поэтому вы можете скачать их и попробовать их.

Btw.возможно, вы можете получить много информации, которую вы ищете от Intelli Trace, если у вас VS 2010 Ultimate.Вы можете прочитать обо всех доступных в настоящее время альтернативах в журнале MSDN .

Я думаю, что есть один большой вопросительный знак - используете ли вы DbContext или ObjectContext (вы упомянули EFv4.1)?Упомянутые инструменты и оболочки трассировки были созданы для API ObjectContext, поэтому я не уверен, как они работают с API DbContext.Вы все еще можете получить ObjectContext из DbContext, но если инструмент ожидает EntityConnection вместо обычного соединения, это будет проблемой.

...