Что я могу сделать, чтобы программно предотвратить или ограничить ресурсные споры?

Я создал приложение, которое, учитывая достаточное количество данных, не может быть завершено: "Журнал транзакций для базы данных" tempdb "заполнен из-за ACTIVE_TRANSACTION". " и "Не удается найти таблицу 0".

Хранимая процедура, используемая в отчете, явно не ссылается на "tempdb", поэтому она должна быть чем-то, что SQL Server управляет самостоятельно.

Во всяком случае, я провел анализ "Resource Contention" в Visual Studio 2013 через Analyze > Performance and Diagnostics.

Когда он закончил, он сообщил мне в "Отчете о профилировании параллелизма", что было 30 790 общих конфликтов, причем "Handle2" и "Multiple Handles 1" составляли более 99% "Наиболее конфликтующих ресурсов" и "_CorExeMain", идентификатора потока 4936 как "Самая обсуждаемая тема"

Думаю, все это достаточно интересно, но теперь, когда я это знаю, что я могу с этим поделать?

Является ли 30,790 чрезмерным количеством общих споров? Звучит так, но я не знаю. Но опять же, если предположить, что эта информация на самом деле не говорит мне ничего ценного, а именно: что я могу сделать, чтобы улучшить ситуацию? Как программно предотвратить или ограничить конфликт ресурсов и / или потоков?

В сгенерированном отчете не было ошибок, и шесть сообщений были "только для информации". Было одно предупреждение:

Предупреждение 1 DA0022: Коллекции # Gen 1 / Коллекции # Gen 2 = 2.52; Относительно высокий уровень сбора мусора в Gen 2. Если, по замыслу, большинство структур данных вашей программы выделены и сохраняются в течение длительного времени, это обычно не является проблемой. Однако, если это поведение непреднамеренно, ваше приложение может прикреплять объекты. Если вы не уверены, вы можете собрать данные о распределении памяти.NET и информацию о времени жизни объекта, чтобы понять, как распределено использование памяти вашим приложением.

... но сохранение структур данных в течение "долгого времени", действительно, задумано.

ОБНОВИТЬ

Затем я запустил отчет ".NET Memory Allocation", и здесь я тоже не уверен, что с ним делать:

введите описание изображения здесь

Является ли 124 миллиона байтов избыточным? Есть ли что-то плохое в функциях, выделяющих наибольшее количество памяти, или на какие типы выделяется наибольшее количество памяти?

Я также не понимаю, почему красная вертикальная линия перемещается после создания отчета; сначала он был около 616, затем переместился на 0 (как видно на скриншоте выше), а теперь около 120.

ОБНОВЛЕНИЕ 2

Теперь я вижу (после выполнения окончательной проверки производительности (Instrumentation)), что вертикальная красная линия - это просто лемминг - она ​​следует за курсором, куда бы вы его ни перетащили. Это имеет какую-то цель, я думаю...

1 ответ

Решение

Вот что в итоге сработало: двусторонняя атака:

0) Гуру базы данных реорганизовал хранимую процедуру, чтобы сделать ее более эффективной.

1) Я переработал код чтения данных, разбив его на две части. Я определил первую половину данных, которые нужно извлечь, и получил их, затем последовал короткую паузу со вторым проходом, извлекая остальные данные. Короче что раньше было так:

. . .
ReadData(_unit, _monthBegin, _monthEnd, _beginYearStr, _endYearStr);
. . .

... теперь это:

. . .
if // big honkin' amount of data
{
    string monthBegin1 = _monthBegin;
    string monthEnd1 = GetEndMonthOfFirstHalf(_monthBegin, _monthEnd, _beginYearStr, _endYearStr);
    string monthBegin2 = GetBeginMonthOfSecondHalf(_monthBegin, _monthEnd, _beginYearStr, _endYearStr);
    string monthEnd2 = _monthEnd;

    string yearBegin1 = _beginYearStr;
    string yearEnd1 = GetEndYearOfFirstHalf(_monthBegin, _monthEnd, _beginYearStr, _endYearStr);
    string yearBegin2 = GetBeginYearOfSecondHalf(_monthBegin, _monthEnd, _beginYearStr, _endYearStr);
    string yearEnd2 = _endYearStr;

    ReadData(_unit, monthBegin1, monthEnd1, yearBegin1, yearEnd1);
    Thread.Sleep(10000);
    ReadData(_unit, monthBegin2, monthEnd2, yearBegin2, yearEnd2);
}
else // a "normal" Unit (not an overly large amount of data to be processed)
{
    ReadData(_unit, _monthBegin, _monthEnd, _beginYearStr, _endYearStr);
}
. . .

Теперь он успешно работает до завершения без каких-либо исключений. Я не знаю, была ли проблема полностью связана с базой данных, или если все действия Excel Interop также были проблемными, но теперь я могу сгенерировать файлы Excel размером 1341 КБ с помощью этой операции.

Другие вопросы по тегам