Quantcast

Performance conundrum ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Performance conundrum ?

alanlit
Given  a List<T>  I want compute a Map<T, Integer> where each entry in the map is the # of occurrences of that object in the list. It seems to me the idiomatic way to do this is

Map<T, Integer> listToMultiplicies(List<T> list) { list.collectEntries{ [it, list.count(it)]} }

which works. As does this

     Map<T, Integer> listToMultiplicies(List<T> list) {
        Map<T, Integer> result = [:]
        Integer c

        list.each {
            result[it] = (null != (c = result[it])) ? c + 1 : 1
        }
        result
    }

The issue is that (even when CompileStatic'd) the idiomatic way is *orders of magnitude* slower than the 'Groovy as Java' way. Am I missing something obvious here ??

Alan
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Performance conundrum ?

paulk_asert
There are numerous trade-offs between functional and imperative styles
(a general statement not specific to Groovy). Often you'll lose
performance to gain the more declarative coding style. In fact it's a
big part of implementation design (and an on-going research topic) to
make functional style code work efficiently.

There are sometimes things that can be done within the language to
improve performance in such cases and sometimes you can choose smarter
approaches when choosing the particular functional techniques you are
using.

My guess is count is very slow and maybe something like:
list.groupBy().collectEntries{ k, v -> [k, v.size()] }
would remain fairly declarative while yielding better performance. I
haven't benchmarked it though.

Cheers, Paul.


On Fri, Jan 27, 2017 at 12:24 PM, alanlit <[hidden email]> wrote:

> Given  a List<T>  I want compute a Map<T, Integer> where each entry in the
> map is the # of occurrences of that object in the list. It seems to me the
> idiomatic way to do this is
>
> Map<T, Integer> listToMultiplicies(List<T> list) { list.collectEntries{ [it,
> list.count(it)]} }
>
> which works. As does this
>
>      Map<T, Integer> listToMultiplicies(List<T> list) {
>         Map<T, Integer> result = [:]
>         Integer c
>
>         list.each {
>             result[it] = (null != (c = result[it])) ? c + 1 : 1
>         }
>         result
>     }
>
> The issue is that (even when CompileStatic'd) the idiomatic way is *orders
> of magnitude* slower than the 'Groovy as Java' way. Am I missing something
> obvious here ??
>
> Alan
>
>
>
> --
> View this message in context: http://groovy.329449.n5.nabble.com/Performance-conundrum-tp5738144.html
> Sent from the Groovy Users mailing list archive at Nabble.com.
Loading...