Roslyn Api, Или Почему Pvs-Studio Так Долго Анализировал Проект

Кто из вас использовал сторонние библиотеки при написании кода? Вопрос риторический, ведь без использования сторонних библиотек разработка некоторых продуктов затянулась бы на очень и очень долгое время, ведь для решения каждой проблемы пришлось бы «изобретать велосипед».

Однако, помимо преимуществ, у использования сторонних библиотек есть и недостатки.

Один из таких недостатков недавно коснулся анализатора PVS-Studio для C#.

Анализатор долго не мог закончить анализ большого проекта из-за использования метода SymbolFinder.FindReferencesAsync из Roslyn API в диагностике V3083.

Roslyn API, или почему PVS-Studio так долго анализировал проект

Жизнь в PVS-Studio, как всегда, шла своим чередом.

Были разработаны новые диагностики, усовершенствован статический анализатор, написаны новые статьи.

Внезапно! У одного из пользователей нашего анализатора в своем большом проекте анализ шел целый день и не смог его завершить.

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

Детальное изучение проблемы выявило, что дольше всех работала 3 диагностики C#.

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

V3083 предупреждает о неправильных вызовах событий C#.

Например, в коде:

   

public class IncorrectEventUse { public event EventHandler EventOne; protected void InvokeEventTwice(object o, Eventers args) { if (EventOne != null) { EventOne(o, args); EventOne.Invoke(o, args); } } }

V3083 будет указывать вызовы обработчиков событий.

EventOne в методе InvokeEventTwice .

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

Внешне логика V3083 очень проста:

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

Из-за этой простоты становится еще интереснее понять причину длительного времени диагностики.



Причина замедления

На самом деле логика немного сложнее.

V3083 в каждом файле для каждого типа создает только один триггер анализатора на одно событие, куда записывает номера всех строк (для навигации в различных плагинах: Визуальная Студия , Райдер , СонарКуб ), где событие возникает неправильно.

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

Для подобной задачи в Roslyn API уже есть метод SymbolFinder.FindReferencesAsync , который использовался в V3083, чтобы не «изобретать велосипед».

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

Однако чем больше кодовая база проекта, тем дольше этот метод будет работать.

Мы в этом на 100% убедились только после замены V3083.

Ускорение V3083 после изменений

При изменении диагностического кода или ядра анализатора необходимо убедиться, что ничего из того, что работало ранее, не сломалось.

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

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

Перед изменением V3083 у нас уже был запущен анализатор на этой базе.

Остается только сделать аналогичный прогон после замены V3083 и узнать выигрыш во времени.

Результаты нас приятно удивили.

Без использования SymbolFinder.FindReferencesAsync в V3083 мы получили ускорение на 9% в тестах.

Если кому-то эти цифры показались незначительными, вот характеристики компьютера, на котором проводились измерения:

Roslyn API, или почему PVS-Studio так долго анализировал проект

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

Заключение

Пусть эта заметка станет предупреждением для всех, кто использует Roslyn API! И вы не повторите наших ошибок.

Причем это касается не только метода SymbolFinder.FindReferencesAsync , но и все остальные методы класса Microsoft.CodeAnaанализ.

FindSymbols.SymbolFinder , которые используют тот же механизм.

Также советую всем разработчикам внимательнее и тщательнее изучать используемые вами библиотеки.

Я говорю это не просто так! Чтобы понять, почему это так важно, советую изучить две другие наши заметки: первый , второй .

Они обсуждают этот вопрос более подробно.

Помимо диагностики мы взялись за другие оптимизации анализатора PVS-Studio, о которых поговорим в следующих статьях и заметках.

Диагностическое изменение V3083 еще не выпущено, поэтому версия анализатора 7.12 работает с использованием SymbolFinder.FindReferencesAsync .

Как уже говорилось ранее, замедление работы анализатора было обнаружено еще в двух C#-диагностиках, кроме V3083. Ради интереса предлагаю читателям оставить в комментариях свои догадки о том, что это за диагностики.

Когда будет более 50 предположений, я приоткрою завесу тайны и назову цифры этих диагностик.

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

Roslyn API: почему PVS-Studio так долго анализировал проект .

Теги: #Управление разработкой #api #pvs-studio #csharp #pvs #статический анализ кода #статический анализатор кода #pvs-studio бесплатно #pvs-studio бесплатно

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.