Подтвердить что ты не робот

SNIReadSyncOverAsync и WaitForSingleObject блокируют работу EF?

Я занимаюсь профилированием службы WCF, использующей EF (System.Data.Entities) для чтения из SQL-кода. Когда я разворачиваю несколько параллельных клиентов, которые попадают в службу, все процессоры идут на 100%, производительность - это, как правило, танки, и все болит.

Профилируя это с помощью профилировщика concurrency, я обнаружил, что 85% времени тратится на синхронизацию, причем фактическое выполнение кода составляет около 4%. Глядя глубже в трассировку стека, большая часть синхронизации, похоже, связана с вызовом WaitForSingleObject в System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync. Стек показывает, что вызов переходит к оболочке нативного метода, а затем завершается в kernel32.dll! _WaitForSingleObject.

Кто-нибудь испытал это раньше? Есть ли способ сделать что-то по этому поводу? Я на самом деле не набрасываю на него абсурдную нагрузку, всего около 20 параллельных клиентов, и все это доступно только для чтения, поэтому я удивляюсь, что нити будут даже синхронизироваться.

Я боролся с этим в течение недели, и я просто не могу это объяснить. Любая помощь будет оценена!

4b9b3361

Ответ 1

Можете ли вы перевести его на небольшой образец кода, который воспроизводит проблему? Какую версию EF вы используете?

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

EF Async

Все, что меньше EF 6, всегда синхронно. С EF 6 вы можете использовать асинхронные методы вместо. Однако не делайте этого, если ваша служба WCF также не использует шаблон async.

WCF Async

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

Если вы используете один из вышеуказанных методов, но не оба, ваш код не будет асинхронным, но будет нести излишнюю нагрузку на синхронизацию. Особенно избегайте Task.Run() или эквивалентов, так как они просто переместят работу в другой поток, фактически не улучшив пропускную способность.

Инициализация

Наконец, еще одна несвязанная идея. Может ли ваша проблема быть связана с инициализацией EF? Когда EF создает метаданные для модели, она делает это один раз для строки подключения. Если несколько потоков пытаются использовать одну и ту же модель и эта модель еще не была инициализирована, все потоки будут блокироваться до завершения инициализации. Чтобы убедиться, что это ваша проблема, сделайте один звонок в службу и позвольте ей выполнить. Затем отправьте 20 параллельных запросов. Неужели они все еще не работают с процессором?