Pull to refresh

Comments 20

Самое главное-то и не рассказали: был ли этот код потом убран — или так и остался на продашкене? :)
Но как узнать, где порождается такое большое количество объектов? Искать по коду? Не вариант, придется делать поиск по всей системе, а времени в обрез – заказчик уже весь синеет.

Я конечно извиняюсь, но вроде бы, поднятие общих бизнес сущностей выносят в отдельные классы, тогда и связность системы понизилась бы, поиск с модификацией кода работающего с entity стали куда проще, да и необходимость у программистов сто первый раз писать велосипед, вроде того поднятия entity не было бы. Плюс часто делают свои обертки над классами JPA'а, вроде entityManager'a, чтобы, например, было проще отлаживать и профилировать поднятие entity (на самом деле, так ещё куча других полезных вещей). Тогда не нужно было делать всех этих хаков с конструктором.

Хорошо, допустим, сущность «поднимается» всего в одном методе, а метод вызывается в 100500 местах. Что-то изменилось от замены конструктора на метод? Стало ли проще найти то место, где этот метод вызывается чаще всего?
Ну, смотрите делаем, например, грубо говоря такой сервис

public interface ServicePayment {
  Payment getPaymentById(String id);
  Payment getAllPayment();
  Payment getPaymentByQuery(String query);
}

Теперь нам не нужно искать вообще все Payment'ы, достаточно сделать поиск по getAllPayment и getPaymentByQuery и понять где программисты промахнулись. Крайне редко проблема будут в цикле с getPaymentById.
Ну вот нашли вы 100400 мест, где используются getAllPayment или getPaymentByQuery. Что дальше?
Если бы нашел 100400 мест, где используются getAllPayment, прибил бы архитектора. Шутка. Вызовы getAllPayment на 2 млн. entity, скорее всего могут должны использоваться только для задач интеграции, обслуживание БД и т.п. Если такой метод используется в обычных модулях это уже повод понять зачем.

Если есть куча мест где используется getPaymentByQuery(«name = ?»), то это повод выделить его в отдельный метод getPaymentByName, создать индекс по полю name, сделать тест производительности метода на реальной базе и т.д. Также для всех подобных методах, в результате большинство частых запросов можно будет выделить в отдельные методы. А дальше всегда можно использовать профайл и т.п. методики на отдельных методах. Метод getPaymentByQuery имеет смысл именно для действительно уникальных случаев и опять-таки ловится профайлером, логированием времени работы и т.п. методами

Ну, например что будет узнаете ли вы когда нибудь, что у вас используется в 100400 мест запросы вида «Payment.name = ?», но индекс по поля name вы сделать забыли, отчего вся ваша система дико тормозит? Ни один профайлер не сможет собрать такие запросы из 100400 мест, насколько я знаю.
Но вы понимаете, что в сумме по всем методам число мест, откуда они вызываются, будет постоянным, как их не переименовывай?

PS убийство архитектора в отсутствии машины времени проблему не решает.
Да, в сумме, как не проектируй и какие патерны не применяй, количество вызовов методов практически не меняется. Ладно, убеждать вас ни в чем не буду.
И да, что такое legacy системы мне прекрасно знакомо, и как в них внедрять более современные правила проектирования тоже.
А профайлер бы не показал наиболее часто вызываемые и «долгоиграющие» методы?
Может быть и показал бы, но как однозначно узнать, что именно в нем создается куча объектов? Тем более, что есть и другие «долгие» методы.
jmap -histo[:live] PID позволит узнать каких доменных объектов было создано много.
hh --dead какие часто умирают
Ну а потом ловить места вызова создания объектов аспектами или btrace или в дебагере
Можно было бы похожее сделать с помощью AspectJ и не писать в лог, а писать в set сам StackTraceElement и сделать каунтер. Плюсы — без модификации кода и можно поймать точку вызова конструктора
Это если AspectJ у вас под рукой и есть тот, кто знает как им пользоваться… Можно при желании и свой профилировщик написать…
Так и делает мой коллега.
Это если AspectJ у вас под рукой

Он есть всегда и со всеми зависимостями
org.aspectjaspectjrt1.8.4
И научиться пользоваться им гораздо проще чем разгребать гигабайты логов!
Такая же ситуация была, с аналогичным скриптом. Тоже горе хапнули
А почему не использовали Flight Recorder из Java Mission Control ?

Без видимых снижений производительности (всего около 2%) можно на боевом окружении увидеть проблемы с памятью:
— Allocation By Class — как раз то что вы написали
— Allocation By Thread

Sign up to leave a comment.

Articles