#java #groovy #memory-leaks #traits #dry
#java #groovy #утечки памяти #Трейты #сухой
Вопрос:
Я пытаюсь ВЫСУШИТЬ свой код, и я впервые использовал для этого, traits
чтобы улучшить свой enums
.
Что я хочу сделать, так это: для заданного массива строк найдите все перечисления, соответствующие хотя бы одному ключевому слову (без учета регистра)
Приведенный ниже код, похоже, работает нормально, но я думаю, что он вызывает у меня утечки памяти, когда метод getSymbolFromIndustries
вызывается тысячи раз.
Вот запись из VisualVM примерно через 10 минут выполнения, столбец «Живые объекты» всегда увеличивается после каждого снимка, а количество элементов по сравнению со второй строкой настолько велико…
Мой размер кучи тоже всегда увеличивается…
Черта :
trait BasedOnCategories {
String[] categories
static getSymbolFromIndustries(Collection<String> candidates) {
values().findAll {
value -> !value.categories.findAll {
categorie -> candidates.any {
candidate -> categorie.equalsIgnoreCase(candidate)
}
}
.unique()
.isEmpty()
}
}
}
Одно из нескольких перечислений, которые у меня есть, реализует trait
enum KTC implements BasedOnCategories, BasedOnValues {
KTC_01([
'industries': ['Artificial Intelligence','Machine Learning','Intelligent Systems','Natural Language Processing','Predictive Analytics','Google Glass','Image Recognition', 'Apps' ],
'keywords': ['AI','Voice recognition']
]),
// ... more values
KTC_43 ([
'industries': ['Fuel','Oil and Gas','Fossil Fuels'],
'keywords': ['Petroleum','Oil','Petrochemicals','Hydrocarbon','Refining']
]),
// ... more values
KTC_60([
'industries': ['App Discovery','Apps','Consumer Applications','Enterprise Applications','Mobile Apps','Reading Apps','Web Apps','App Marketing','Application Performance Management', 'Apps' ],
'keywords': ['App','Application']
])
KTC(value) {
this.categories = value.industries
this.keywords = value.keywords
}
Мои тесты, основанные на данных
def "GetKTCsFromIndustries"(Collection<String> actual, Enum[] expected) {
expect:
assert expected == KTC.getSymbolFromIndustries(actual)
where:
actual | expected
[ 'Oil and Gas' ] | [KTC.KTC_43]
[ 'oil and gas' ] | [KTC.KTC_43]
[ 'oil and gas', 'Fossil Fuels' ] | [KTC.KTC_43]
[ 'oil and gas', 'Natural Language Processing' ] | [KTC.KTC_01, KTC.KTC_43]
[ 'apps' ] | [KTC.KTC_01, KTC.KTC_60]
[ 'xyo' ] | []
}
Мои вопросы :
- Если у кого-то есть какие-то подсказки, которые помогут мне исправить эти утечки…
- Есть ли более элегантный способ написания
getSymbolFromIndustries
метода?
Спасибо.
Ответ №1:
Не уверен в проблемах с производительностью, но я бы изменил вашу черту таким образом:
https://groovyconsole.appspot.com/script/5205045624700928
trait BasedOnCategories {
Set<String> categories
void setCategories( Collection<String> cats ) {
categories = new HashSet( cats*.toLowerCase() ).asImmutable()
}
@groovy.transform.Memoized
static getSymbolFromIndustries(Collection<String> candidates) {
def lowers = candidates*.toLowerCase()
values().findAll{ value -> !lowers.disjoint( value.categories ) }
}
}
Теперь остальная часть контекста
trait BasedOnValues {
Set<String> keywords
}
enum KTC implements BasedOnCategories, BasedOnValues {
KTC_01([
'industries': ['Artificial Intelligence','Machine Learning','Intelligent Systems','Natural Language Processing','Predictive Analytics','Google Glass','Image Recognition'],
'keywords': ['AI','Voice recognition']
]),
// ... more values
KTC_43 ([
'industries': ['Fuel','Oil and Gas','Fossil Fuels'],
'keywords': ['Petroleum','Oil','Petrochemicals','Hydrocarbon','Refining']
]),
// ... more values
KTC_60([
'industries': ['App Discovery','Apps','Consumer Applications','Enterprise Applications','Mobile Apps','Reading Apps','Web Apps','App Marketing','Application Performance Management'],
'keywords': ['App','Application']
])
KTC(value) {
this.categories = value.industries
this.keywords = value.keywords
}
}
// some tests
[
[ [ 'Oil and Gas' ], [KTC.KTC_43] ],
[ [ 'oil and gas' ], [KTC.KTC_43] ],
[ [ 'oil and gas', 'Fossil Fuels' ], [KTC.KTC_43] ],
[ [ 'oil and gas', 'Natural Language Processing' ], [KTC.KTC_01, KTC.KTC_43] ],
[ [ 'xyo' ], [] ],
].each{
assert KTC.getSymbolFromIndustries( it[ 0 ] ) == it[ 1 ]
}
а затем измерьте производительность
Комментарии:
1. Мне нравится, как вы очищаете
trait
! Я никогда не думал о@Memoized
nor aSet
в groovy, но я делаю это каждый раз в node / react ^^ спасибо за это уже! Я проведу тест как можно скорее, и я прокомментирую / одобрю ваше решение после результатов;) большое спасибо, что нашли время для просмотра моего кода 🙂2. добавлено
disjoint
, чтобы сделать код еще проще. Кстати, в react я использую приемы, которые я узнал от groovy 😉3. Это правда,
es6
иgroovy
у них много общего! : D Первые результаты теста кажутся лучше,Live Objects
часто очищаются,Allocated Object
все еще растут, я дважды проверю, как я использую метод, если я забыл какие-либо «мертвые ссылки»