Discussion:
[groovy-dev] Primitive array min() and max()
Yu Kobayashi
2015-02-23 17:21:51 UTC
Permalink
Hello.

http://jira.codehaus.org/browse/GROOVY-7319
I want to add min() and max() to primitive arrays.

https://github.com/groovy/groovy-core/pull/616
Then there is of course the course of action regarding those primitive type comparators. Maybe that should be discussed on the mailing list instead of here
Iterable.min(Comparator) have to create Integer instance every time
and it is very slow.

https://github.com/yukoba/groovy-core/blob/PrimitiveArrayMinMax/src/main/groovy/util/function/IntComparator.java
So I want to add int[].min(IntComparator)

IntComparator is
int compare(int v1, int v2).
java.util.Comparator is
int compare(T o1, T o2).

As Java 8 puts those methods in java.util.function package,
I put them in groovy.util.function package.

I can use like this.
def ary = [-1, -2, -3] as int[]
ary.min { int a, int b -> -a <=> -b }

I noticed the following problem when I am writing this e-mail.

One big problem of this way is
I am ignoring one argument version of Iterable.min(Closure).

One solution is to add two methods instead of min().
ary.minCompare { int a, int b -> -a <=> -b }
ary.minApply { int v -> -v }
I have to add groovy.util.function.IntUnaryOperator for minApply().

Another solution is to add two argument types.
ary.min({ int a, int b -> -a <=> -b } as IntComparator})
ary.min({ int v -> -v } as IntUnaryOperator})
I don't like this one because this is complicated.

Are there any other problems?
--
Yu Kobayashi <***@gmail.com>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Jochen Theodorou
2015-02-25 11:58:13 UTC
Permalink
Post by Yu Kobayashi
Hello.
http://jira.codehaus.org/browse/GROOVY-7319
I want to add min() and max() to primitive arrays.
https://github.com/groovy/groovy-core/pull/616
Then there is of course the course of action regarding those primitive type comparators. Maybe that should be discussed on the mailing list instead of here
Iterable.min(Comparator) have to create Integer instance every time
and it is very slow.
https://github.com/yukoba/groovy-core/blob/PrimitiveArrayMinMax/src/main/groovy/util/function/IntComparator.java
So I want to add int[].min(IntComparator)
IntComparator is
int compare(int v1, int v2).
java.util.Comparator is
int compare(T o1, T o2).
As Java 8 puts those methods in java.util.function package,
I put them in groovy.util.function package.
problem: groovy.util, is public API, so I would like to hear an other
opinion than mine on this.

If we compare this to Java8, then I see two things..
(1) Performance
You would maybe use a Stream on java8 and then they use the normal
Comperator interface, even in case of the primitive streams. It is true,
that this will cause boxing once (min and max can be kept in boxed
form) for every element of the array. So it seems they did not see this
as either an often occuring operation or as not as expensive as it
seems. In fact, if no dynamic callsite is involved I assume that the JVM
can eliminate the boxing. If the intended use is with our open blocks,
the question is if that proxy will not prevent the possible advantage.

So I made a test in standard Groovy and with indy and could not find an
advantage using java 8u25. The differences of the results stayed within
the variation.

Maybe if you have a benchmark illustrating the gain?

(2) API
should we really add those to groovy.util? Plus, there is no speed
advantage for a byte version if we have an int version. So versions for
int, long and double would most probably be enough. (For reference the
primitive streams in java8 are also limited to those types, since those
are the usual result types in Java anyway)


[...]
Post by Yu Kobayashi
One big problem of this way is
I am ignoring one argument version of Iterable.min(Closure).
One solution is to add two methods instead of min().
ary.minCompare { int a, int b -> -a <=> -b }
ary.minApply { int v -> -v }
I have to add groovy.util.function.IntUnaryOperator for minApply().
Another solution is to add two argument types.
ary.min({ int a, int b -> -a <=> -b } as IntComparator})
ary.min({ int v -> -v } as IntUnaryOperator})
I don't like this one because this is complicated.
the joys of lambda transformations in Java ;)

bye blackdrag
--
Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
blog: http://blackdragsview.blogspot.com/
german groovy discussion newsgroup: de.comp.lang.misc
For Groovy programming sources visit http://groovy-lang.org


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Yu Kobayashi
2015-02-25 15:51:21 UTC
Permalink
Hello, Blackdrag.
Post by Jochen Theodorou
(1) Performance
You would maybe use a Stream on java8 and then they use the normal
Comperator interface, even in case of the primitive streams. It is true,
that this will cause boxing once (min and max can be kept in boxed form)
for every element of the array. So it seems they did not see this as either
an often occuring operation or as not as expensive as it seems. In fact, if
no dynamic callsite is involved I assume that the JVM can eliminate the
boxing. If the intended use is with our open blocks, the question is if that
proxy will not prevent the possible advantage.
Oh, I forget one important thing.

I think boxing is actually slow, but this code
{ int v1, int v2 -> -v1 <=> -v2 } as IntComparator
do boxing! Closure always do boxing in Groovy.

To avoid boxing, I have to write like this in Groovy.
new IntComparator() { int compare(int v1, int v2) { -v1 <=> -v2 } }

I wrote a test code to prove this.
https://gist.github.com/yukoba/5cc70dc000e4a23e1716

test1: 7100 ms
test2: 7100 ms
test3: 940 ms
test4: 940 ms

The machine is Windows 8.1 + Java 8u31 + Groovy 2.4.1.

I strongly believe Java 8 VM cannot remove boxing automatically.

I think Blackdrag is writing this part in Groovy,
could you please translate this code
{ int v1, int v2 -> -v1 <=> -v2 } as IntComparator
to this code at static compile?
new IntComparator() { int compare(int v1, int v2) { -v1 <=> -v2 } }
--
Yu Kobayashi <***@gmail.com>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Loading...