Hi Ivan,

On 07/29/2017 07:22 PM, Peter Levart wrote:
I tried an approach where sub-sequences are CharSequence objects by delegation and use sub-comparators that don't convert CharSequence(s) to String(s). Here's what this looks like:

http://cr.openjdk.java.net/~plevart/misc/AlphadecimalComparator/alphadecimal-comparator/src/main/java/peter/AlphadecimalComparator.java

Here are the results:

http://cr.openjdk.java.net/~plevart/misc/AlphadecimalComparator/alphadecimal-comparator/bench_results_speed.txt

A simple optimization of above code (manually unrolling the alpha/decimal alteration - i.e. getting rid of 'alpha' boolean flag):

before:

        boolean alpha = true;
        while (true) {
            if (ss1.next(alpha)) {
                if (ss2.next(alpha)) {
                    Comparator<? super CharSequence>
                        comparator = alpha
                                     ? alphaComparator
                                     : decimalComparator;
                    int cmp = comparator.compare(ss1, ss2);
                    if (cmp != 0) {
                        return cmp;
                    }
                } else {
                    return 1;
                }
            } else {
                if (ss2.next(alpha)) {
                    return -1;
                } else {
                    return 0;
                }
            }
            alpha = !alpha;
        }

after:

        while (true) {
            // alpha part
            if (ss1.next(true)) {
                if (ss2.next(true)) {
                    int cmp = alphaComparator.compare(ss1, ss2);
                    if (cmp != 0) {
                        return cmp;
                    }
                } else {
                    return 1;
                }
            } else {
                if (ss2.next(true)) {
                    return -1;
                } else {
                    return 0;
                }
            }
            // decimal part
            if (ss1.next(false)) {
                if (ss2.next(false)) {
                    int cmp = decimalComparator.compare(ss1, ss2);
                    if (cmp != 0) {
                        return cmp;
                    }
                } else {
                    return 1;
                }
            } else {
                if (ss2.next(false)) {
                    return -1;
                } else {
                    return 0;
                }
            }
        }

...yields a noticeable spead-up:

// reference:

Benchmark (_strings) (comparator) Mode Cnt Score Error Units ComparatorBench.test strings1 ivan.NumericComparator avgt 10 1455.789 ± 37.158 ns/op ComparatorBench.test strings2 ivan.NumericComparator avgt 10 13680.131 ± 338.763 ns/op

// before explicit alpha/decimal alteration unrolling:

Benchmark (_strings) (comparator) Mode Cnt Score Error Units ComparatorBench.test strings1 peter.AlphadecimalComparator.CS avgt 10 2065.324 ± 50.532 ns/op ComparatorBench.test strings2 peter.AlphadecimalComparator.CS avgt 10 21118.430 ± 350.769 ns/op

// after explicit alpha/decimal alteration unrolling:

Benchmark (_strings) (comparator) Mode Cnt Score Error Units ComparatorBench.test strings1 peter.AlphadecimalComparator.CS avgt 10 1692.145 ± 2.160 ns/op ComparatorBench.test strings2 peter.AlphadecimalComparator.CS avgt 10 18624.677 ± 1900.779 ns/op


With this mod, AlphadecimalComparator is only about 16 - 35% slower than NumericComparator.


Regards, Peter

Reply via email to