Вопрос

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

Итак, знает ли кто-нибудь о каких-либо инструментах или методах, которые помогли бы анализировать и документировать все взаимодействия между потоками?FWIW, кодовая база в Linux - C ++, но мне было бы интересно услышать об инструментах для других сред.


Обновить

Я ценю полученные ответы, но я надеялся на что-то более сложное или систематическое, чем совет, который по сути сводится к "добавлению сообщений журнала, выяснению того, что происходит, и исправлению этого". Существует множество инструментов для анализа и документирования потока управления в однопоточных программах;неужели нет ничего доступного для многопоточных программ?


Смотрите также Отладка многопоточных приложений

Это было полезно?

Решение

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

Я думаю, что есть пробная версия, которую вы можете скачать, так что, возможно, стоит попробовать.Я использовал только версию для Windows, но, взглянув на веб-страницу VTune, я увидел, что там также есть версия для Linux.

Другие советы

В качестве отправной точки у меня возникло бы желание добавить сообщения журнала отслеживания в стратегические точки вашего приложения.Это позволит вам проанализировать, как взаимодействуют ваши потоки, без опасности того, что процесс наблюдения за потоками изменит их поведение (как это могло бы быть в случае пошаговой отладки).Мой опыт работы связан с платформой .NET, и моим любимым инструментом ведения журнала был бы log4net, поскольку он бесплатный, имеет широкие возможности настройки и, если вы разбираетесь в том, как вы реализуете ведение журнала, это не будет заметно снижать производительность вашего приложения.В качестве альтернативы, в .NET есть встроенный класс Debug (или Trace) в System.Пространство имен Diagnostics.

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

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

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

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

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

Инструмент, который может сработать для вас, - это ШАХМАТЫ (хотя, к сожалению, это доступно только для Windows). ВЗРЫВ это еще один довольно мощный инструмент, но он очень сложен в использовании и может не работать с C ++.Википедия также перечисляет Steam, о котором я раньше не слышал, но, похоже, у вас это может сработать:

StEAM - это средство проверки моделей для C ++.Он обнаруживает взаимоблокировки, ошибки сегментации, переменные вне диапазона и не завершающиеся циклы.

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

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

В Java у вас есть варианты, такие как FindBugs (для статического анализа байт-кода), чтобы найти определенные виды несогласованной синхронизации, или множество динамических анализаторов потоков от таких компаний, как Coverity, JProbe, OptimizeIt и т.д.

Разве UML не может помочь вам здесь?

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

Это также покажет "объекты данных", которые являются общими, и объекты, зависящие от потока.

Если вы нарисуете большую диаграмму классов и удалите все "объекты данных", то вы сможете оформить эту диаграмму в виде облаков, каждое облако которых является потоком - или группой потоков, если только связь и когезия базы кода не ужасны.

Это даст вам только одну часть головоломки, но это может быть полезно ;Я просто надеюсь, что в этом случае ваша кодовая база не слишком мутная или слишком "процедурная" ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top