Ответ 1
Я не использовал AspectJ, поэтому не могу ручаться за то, как легко его использовать. Я использовал ASM, чтобы создать собственный профилировщик кода, это было около двух дней работы. Усилия по синхронизации инструмента должны быть схожими. AspectJ должен быть быстрее и легче, когда вы достигнете скорости с учетом аспектов.
Я реализовал отслеживание тупика для нашего сервера на базе С++. Вот как я это сделал:
- Когда вы когда-либо приобретаете или отпускаете блокировку, я отслеживаю:
-
<time> <tid> <lockid> <acquiring|releasing> <location in code>
-
- Этот дополнительный след повлиял на производительность довольно резко и не использовался в производстве.
- Итак, когда был обнаружен возможный тупик, я использовал файл журнала, чтобы выяснить, что происходит вокруг тупика. Затем воспроизведите эту функциональность в тестовой среде с включенной трассировкой.
- Затем я запустил script в файле журнала, чтобы узнать, существует ли взаимоблокировка и как. Я использовал awk script, используя этот алгоритм:
- Линия
- при приобретении
- добавить lockid в список текущих блокировок для этого потока
- добавьте каждую пару блокировок в этот список к наборам пар блокировки для этого потока. например, для списка
Lock A -> Lock B -> Lock C
генерируют пары(Lock A, Lock B), (Lock A, Lock C), (Lock B, Lock C)
- при выпуске
- удалить текущий lockid из хвоста списка для этого потока
- при приобретении
- Для каждой пары замков найдите все остальные потоки пар обратной блокировки, каждое совпадение является потенциальным тупиком, поэтому напечатайте пары и потоки, затронутые
- Вместо того, чтобы сделать алгоритм более умным, я столкнулся с проверкой того, что захват блокировки, чтобы увидеть, был ли он реальным тупиком.
- Линия
Я сделал это после того, как не смог найти причину тупика в течение нескольких дней, потребовалось еще несколько дней и несколько часов, чтобы найти тупик.
Если вы рассматриваете этот подход в Java, нужно рассмотреть следующие вопросы:
- Используете ли вы только
synchronized
для защиты своих критических разделов? Используете ли вы классы в java.lang.concurrent? (для этого может потребоваться специальная обработка/контрольно-измерительная техника). - Насколько легко печатать местоположение кода с помощью аспектов /ASM? Я использовал
__FILE__
и__LINE__
в С++. ASM предоставит вам имя класса, имя метода и подпись. - Вы не можете использовать блокировки, используемые для защиты трассировки/регистрации.
- Вы можете оптимизировать свои инструменты, если вы используете файл журнала для каждого потока и создаете локальное хранилище для файлового объекта.
- Как вы однозначно идентифицируете объекты, на которых вы синхронизируете? Может быть, toString() и System.identityHashCode() будет достаточно, но может потребоваться больше. Я использовал адрес объекта в С++.