Как «разогреть» Entity Framework? Когда становится «холодно»?

118

Нет, ответ на мой второй вопрос - не зима.

Предисловие:

В последнее время я проводил много исследований Entity Framework, и что-то, что меня беспокоит, - это его производительность, когда запросы не разогреваются, так называемые холодные запросы.

Я просмотрел статью о производительности для Entity Framework 5.0. Авторы представили концепцию теплых и холодных запросов и их различия, что я тоже заметил, не зная об их существовании. Здесь, наверное, стоит упомянуть, что за моей спиной всего полгода опыта.

Теперь я знаю, какие темы я могу дополнительно изучить, если хочу лучше понять фреймворк с точки зрения производительности. К сожалению, большая часть информации в Интернете является устаревшей или чрезмерно субъективной, поэтому я не могу найти какую-либо дополнительную информацию по теме запросов « Теплый или холодный» .

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

Мы будем переходить на Windows Server 2012, IIS8 и SQL Server 2012, и, будучи младшим, я действительно получил возможность протестировать их раньше остальных. Я очень рад, что они представили модуль разминки, который подготовит мое приложение к этому первому запросу. Однако я не уверен, как продолжить разогрев Entity Framework.

То, что я уже знаю, стоит сделать:

  • Создавайте мои просмотры заранее, как было предложено.
  • Со временем перенесу свои модели в отдельную сборку.

Что я считаю своим делом, исходя из здравого смысла, вероятно, неправильным подходом :

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

Вопросы:

  • Каков наилучший подход к обеспечению высокой доступности моей Entity Framework в любое время?
  • В каких случаях Entity Framework снова становится "холодным"? (Перекомпиляция, повторное использование, перезапуск IIS и т. Д.)
Питер
источник
Выясните, что вас больше всего волнует: создание представления или компиляция запроса. Если это генерация представления, используйте предварительно скомпилированные представления. Если это запросы - у вас большая сложная иерархия? Обратите внимание, что дорогостоящие вещи обычно происходят один раз для каждого домена приложения и кэшируются, поэтому вы видите такие проблемы, когда домен приложения выгружается и создается новый.
Павел
Я уже упоминал генерацию представления @Pawel, иерархия не сложная, даже немного. Но проблема тоже принципиальная. Следуя тому, что вы сказали, я выясню, когда выгружается домен приложения. Однако это по-прежнему не помогает решить другую проблему, которая нагревает Entity Framework в случае, как вы сказали, домен приложения выгружается. На данный момент кажется, что домен приложения выгружается больше, чем следовало бы, и я не уверен, почему, повторное использование происходит только ночью, на холостом ходу установлено значение 0.
Питер
4
Как вы думаете, почему чтение фиктивных данных - неправильный подход?
Джош Хайцман
5
Это просто неправильно, я подумал, что может быть что-то более элегантное, о чем я не подозреваю. Но если это единственное решение, и кто-то с хорошими знаниями может подтвердить, что другого пути нет, я просто выберу его.
Питер
1
Одна из проблем, с которыми я столкнулся при отключении пула приложений после определенного периода бездействия (из-за низкого трафика), - это создание службы, которая делает запрос через заданный интервал времени на одну из ваших страниц. Это предотвращает долгую задержку перед перезапуском пула приложений по первому запросу. Или вы можете использовать бесплатную службу, например www.pingalive.com, для проверки связи с вашим доменом / IP-адресом. Это также помогает предотвратить очистку кэшированных объектов до истечения срока их действия.
hatsrumandcode

Ответы:

55
  • Каков наилучший подход к обеспечению высокой доступности моей Entity Framework в любое время?

Вы можете использовать сочетание предварительно созданных представлений и статических скомпилированных запросов.

Статические CompiledQuerys хороши тем, что их легко и быстро писать, и они помогают повысить производительность. Однако с EF5 нет необходимости компилировать все ваши запросы, поскольку EF автоматически компилирует запросы. Единственная проблема в том, что эти запросы могут потеряться при очистке кеша. Таким образом, вы по-прежнему хотите хранить ссылки на свои собственные скомпилированные запросы для тех, которые встречаются очень редко, но стоят дорого. Если вы поместите эти запросы в статические классы, они будут скомпилированы, когда они потребуются впервые. Это может быть слишком поздно для некоторых запросов, поэтому вы можете принудительно скомпилировать эти запросы во время запуска приложения.

Как вы упомянули, еще одна возможность - предварительное создание представлений. Особенно для тех запросов, которые очень долго компилируются и которые не меняются. Таким образом вы переносите накладные расходы на производительность со времени выполнения на время компиляции. Также это не приведет к задержкам. Но, конечно, это изменение попадает в базу данных, так что с этим не так-то легко справиться. Код более гибкий.

Не используйте много наследования TPT (это общая проблема производительности в EF). Ни в коем случае не выстраивайте иерархию наследования слишком глубоко или слишком широко. Только 2-3 свойств, относящихся к некоторому классу, может быть недостаточно, чтобы требовать собственный тип, но их можно обрабатывать как необязательные (допускающие значение NULL) свойства для существующего типа.

Не цепляйтесь за один контекст надолго. Каждый экземпляр контекста имеет свой собственный кеш первого уровня, который снижает производительность по мере его увеличения. Создание контекста обходится дешево, но управление состоянием внутри кэшированных сущностей контекста может стать дорогостоящим. Другие кеши (план запроса и метаданные) используются разными контекстами и умрут вместе с доменом приложения.

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

  • В каких случаях Entity Framework снова становится "холодным"? (Перекомпиляция, повторное использование, перезапуск IIS и т. Д.)

По сути, каждый раз, когда вы теряете свой AppDomain. IIS выполняет перезапуск каждые 29 часов , поэтому вы никогда не можете гарантировать наличие ваших экземпляров. Также после некоторого времени бездействия AppDomain также отключается. Вам следует снова попытаться быстро подняться. Возможно, вы можете выполнить некоторую инициализацию асинхронно (но остерегайтесь проблем с многопоточностью). Вы можете использовать запланированные задачи, которые вызывают фиктивные страницы в вашем приложении в периоды, когда нет запросов, чтобы предотвратить смерть AppDomain, но в конечном итоге это произойдет.

Я также предполагаю, что когда вы измените свой файл конфигурации или измените сборки, произойдет перезагрузка.

Andreas
источник
Спасибо, Андре, это было то, что мне было нужно.
Питер
@Andreas На самом деле, даже со статическими скомпилированными запросами первый запуск слишком долгий. Есть ли какой-либо способ разогреть их, кроме: Выполнение фиктивных данных, считываемых при запуске приложения, чтобы разогреть, сгенерировать и проверить модели.
manishKungwani 04
@Andreas Так Entity framework5 нужен или нет? Что изменится, если использовать его на ef5 (я имею в виду все еще медленное или мало тестируемого или не другое?)
qakmak
«Статические CompiledQuerys хороши тем, что их легко и быстро писать, и они помогают снизить производительность». Сниженная производительность?
Mathemats
9

Если вы ищете максимальную производительность для всех вызовов, вам следует тщательно продумать свою архитектуру. Например, может иметь смысл предварительно кэшировать часто используемые поисковые запросы в оперативной памяти сервера при загрузке приложения вместо использования вызовов базы данных для каждого запроса. Этот метод обеспечит минимальное время отклика приложения для часто используемых данных. Однако вы должны быть уверены, что у вас правильно настроенная политика истечения срока действия, или всегда очищайте кеш всякий раз, когда вносятся изменения, которые влияют на кэшированные данные, чтобы избежать проблем с параллелизмом.

В общем, вы должны стремиться разрабатывать распределенные архитектуры, требующие запросов данных на основе ввода-вывода только тогда, когда локально кэшированная информация становится устаревшей или должна быть транзакционной. Любой запрос данных "по сети" обычно занимает в 10-1000 раз больше времени для получения, чем получение локального запроса в кэше памяти. Уже один этот факт часто делает обсуждение «холодных и теплых данных» несущественным по сравнению с вопросом «локальные или удаленные» данные.

mcstar
источник
Это хороший момент, который я часто игнорирую, в то время как пребываю в восторге от сырой производительности entity framework. Я изучу это подробнее и подробнее изучу принципы кеширования. Тем не менее, «холодное против теплого» с точки зрения EF - это то, что я все еще хочу понять лучше.
Питер
2
«Уже один этот факт часто делает обсуждение« холодных и теплых данных »несущественным по сравнению с вопросом« локальные или удаленные »данные». На самом деле, нет. Если у вас нет его кэширования локально (чего вы не хотите изначально), вам все равно нужно нажать EF и испытать боль инициализации, чтобы заполнить кеш. В тех же местах, где ваш кеш неинициализирован, EF не будет инициализирован. Таким образом, добавление уровня кеширования может не помочь, если единственной проблемой является время инициализации EF, но это добавит еще один уровень сложности ...
MikeJansen 07
8

Общие советы.

  • Тщательно ведите журнал, включая то, к чему обращаются, и время запроса .
  • Выполняйте фиктивные запросы при инициализации приложения для очень медленных запросов горячей загрузки, которые вы выбрали на предыдущем шаге.
  • Не трудитесь оптимизировать, если это не реальная проблема, свяжитесь с потребителем приложения и спросите. Получите комфортную непрерывную обратную связь, хотя бы для того, чтобы понять, что нужно оптимизировать .

Теперь объясним, почему фиктивные запросы не являются неправильным подходом .

  • Меньше сложности - вы разогреваете приложение таким образом, чтобы оно работало независимо от изменений во фреймворке, и вам не нужно выяснять, возможно, фанковые API / внутренности фреймворка, чтобы сделать это правильно .
  • Большее покрытие - вы прогреваете сразу все уровни кеширования, связанные с медленным запросом.

Чтобы объяснить, когда кэш становится "холодным".

Это происходит на любом уровне вашей структуры, который применяет кеш, хорошее описание есть в верхней части страницы производительности .

  • Когда когда-либо кеш должен быть проверен после потенциального изменения, которое делает кеш устаревшим, это может быть тайм-аут или более интеллектуальный (например, изменение кэшированного элемента).
  • Когда элемент кэша вытесняется, алгоритм для этого описан в разделе «Алгоритм вытеснения кэша» в статье о производительности, которую вы связали , но вкратце.
    • Кэш LFRU (наименее часто - недавно использованный) по количеству обращений и возрасту с ограничением в 800 элементов.

Другие вещи, о которых вы упомянули, в частности, перекомпиляция и перезапуск IIS, очищают либо части, либо все кеши памяти.

udoprog
источник
Это еще один полезный ответ, который мы очень ценим.
Питер
3

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

Извлечено из вашей ссылки : «Когда представления создаются, они также проверяются. С точки зрения производительности, подавляющая часть затрат на создание представлений фактически приходится на проверку представлений»

Это означает, что при построении сборки модели произойдет снижение производительности. Затем ваш объект контекста пропустит «холодный запрос» и останется отзывчивым в течение всего жизненного цикла объекта контекста, а также последующих контекстов нового объекта.

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

Ярлык ...

  1. Пропустите всю эту дополнительную работу с предварительно созданными представлениями
  2. Создайте свой объектный контекст
  3. Запустите этот сладкий неуместный запрос
  4. Затем просто сохраните ссылку на контекст вашего объекта на время всего процесса (не рекомендуется).
hotpie
источник
2

У меня нет опыта в этой сфере. Но в других контекстах, например, в Solr, полностью фиктивные чтения не будут иметь большого смысла, если вы не сможете кэшировать всю БД (или индекс).

Лучшим подходом было бы регистрировать запросы, извлекать из журналов наиболее распространенные и использовать их для разогрева. Просто убедитесь, что не регистрировали запросы на прогрев и не удаляли их из журналов, прежде чем продолжить.

estani
источник