On Tue, 14 Feb 2023 04:48:43 GMT, Xiaowei Lu <d...@openjdk.org> wrote:

> The pr looks promising in terms of performance. What makes sense to do:
> 
> *) Don't rely on external benchmarks. It's fine if such exists, but anyway 
> set of microbenchmarks (using JMH) will be much better. More clear, readable 
> results, etc. E.g., it may show that other operations (for example, sqrt) 
> were speeded up too.
> 
> *) Find boundaries. "divideAndRemainder(bigTenToThe(scaleStep))" may produce 
> non-zero reminder. Find conditions when it happens. How big is performance 
> regression in such cases?
> 
> Some other optimizations: *) Current code checks only the lowest bit (odd or 
> even) to cut off indivisible cases. Making 
> "divideAndRemainder(bigTenToThe(scaleStep))" - you make check scaleStep 
> lowest bits to do cut off. See "BigInteger.getLowestSetBit()"
> 
> *) BigInteger division by int value is faster. It's a special case. What is 
> faster, doing the single division by bigTenToThe(scaleStep) or doing several 
> divisions (split scaleStep to fit into int)? Exploration is required.

Hi. Here are some updates.
About the two optimizations you suggest.
1. Check scaleStep lowest bits is way better than only checking the lowest bit. 
This is indeed a good idea and I have committed this change.
2. As for doing several divisions instead of single division, it seems this 
method will decrease performance by about 5%. The reason, I guess, may be that 
division by int isn't as fast as we expected. The following is benchmark result.

doing several divisions 
DecimalBenchmark.divide_by_2         thrpt    5  1239304.846 ± 29436.222  ops/s
DecimalBenchmark.divide_by_2_to_100  thrpt    5    31218.635 ±   210.539  ops/s
DecimalBenchmark.divide_by_3         thrpt    5  6296749.157 ± 86503.717  ops/s

doing single division by bigTenToThe(scaleStep)
DecimalBenchmark.divide_by_2         thrpt    5  1480401.113 ±   8337.892  ops/s
DecimalBenchmark.divide_by_2_to_100  thrpt    5    33143.697 ±    152.598  ops/s
DecimalBenchmark.divide_by_3         thrpt    5  6188186.598 ± 341272.484  ops/s

The following is how I split scaleStep into int to do such divisions.

    private static BigInteger[] divideByPowerTen(BigInteger intVal, int n) {
        // guarantee n > 0
        int INT_MAX_POWER_OF_TEN = 9; // 10^9 is the max ten power which can be 
contained in an int
        BigInteger qr[];
        BigInteger dividend = intVal;

        // Split n into int value to accelerate the following division.
        do {
            int step = Math.min(INT_MAX_POWER_OF_TEN, n);
            qr = dividend.divideAndRemainder(BIG_TEN_POWERS_TABLE[step]);
            if (qr[1].signum() != 0) {
                break;
            } else {
                n -= step;
                dividend = qr[0];
            }
        } while (n > 0);
        return qr;
    }

-------------

PR: https://git.openjdk.org/jdk/pull/12509

Reply via email to