【问题标题】:Enum implementing traits - memory issues?枚举实现特征 - 内存问题?
【发布时间】:2023-03-13 02:25:01
【问题描述】:

我正在尝试DRY 我的代码,我第一次使用traits 来增强我的enums

我想要做的是:对于给定的字符串数组,找到与至少一个关键字匹配的所有枚举(不区分大小写)

下面的代码似乎运行良好,但我认为当方法 getSymbolFromIndustries 被调用数千次时它会产生内存泄漏。

这是运行大约 10 分钟后从 VisualVM 捕获的内容,Live Objects 列在每次快照后总是增加,与第二行相比,项目的数量是如此巨大......

我的堆大小也一直在增加...

特点:

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 方法?

谢谢。

【问题讨论】:

    标签: java groovy memory-leaks traits dry


    【解决方案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 ]
    }
    

    然后衡量性能

    【讨论】:

    • 我喜欢你清理trait 的方式!我从没想过 @Memoized 也没有在 groovy 中使用 Set 但我每次都在 node/react 中这样做 ^^ 已经谢谢了!我会尽快做基准测试,结果出来后我会评论/批准你的解决方案;)非常感谢你花时间审查我的代码:)
    • 添加了disjoint 以使代码更加简单。顺便说一句,我正在使用从 groovy 中学到的技巧;)
    • 这是真的,es6groovy 有很多相似之处! :D 基准测试的第一个结果似乎更好,Live Objects 经常被清理,Allocated Object 仍在增长,如果我忘记了任何“死引用”,我会仔细检查我是如何使用该方法的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多