On Sun, 15 May 2022 14:17:41 GMT, Piotr Tarsa <d...@openjdk.java.net> wrote:

>> iaroslavski has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>>   
>>   * Improved mixed insertion sort
>>   * Optimized insertion sort
>>   * Improved merging sort
>>   * Optimized soring tests
>
> i think it would make much more sense to have the extra buffer size limit in 
> bytes, not in elements. for single-threaded sorting the limit should be low, 
> e.g. 1/64 of the heap, not 1/8 (in case of sorting e.g. longs as each long is 
> 8 byte long). multi-threaded sorting could be more aggressive when it comes 
> to resource usage as it's less likely to be used in resource constrained 
> environment.

@tarsa  Hi Piotr,
 
Thank you for your interest to sorting and your point to allocation of buffers 
in sorting.
 
Let’s I share my thoughts.
 
The number of elements of any array is not more than ~2 billion
(max positive int value) and therefore the size (in bytes) of
int array is not more than ~2 GB * 4 = ~8 GB.
 
We need additional buffer for int, long, float and double types only.
 
We will have 2 constants which limit the number of int/float and
long/double elements in array, like this:
 
    private static final int MAX_BUFFER_LENGTH_1 =              // for int/float
            (int) Math.min(Runtime.getRuntime().maxMemory() >> 10, 
Integer.MAX_VALUE);
 
    private static final int MAX_BUFFER_LENGTH_2 =             // for 
long/double
            (int) Math.min(Runtime.getRuntime().maxMemory() >> 11, 
Integer.MAX_VALUE);
 
See, that the max number of elements for long/double is in 2 times less than 
for int/float,
because long/double occupies 2 times more bytes.
 
I take factors 10 and 11 as example, it may be other values, but the first is 
less than the second by 1.
 
Why do we need to use Math.min(…, Integer.MAX_VALUE)? We must do it in this 
case:
if  Runtime.getRuntime().maxMemory() >> 11 is larger than max int (for example, 
we have power server),
casting to int will produce negative value. So, limit by 2 Gb max is required.
 
And the method tryAllocate will look like this:
 
private static Object tryAllocate(Object a, int length) {
    try {
        if (a instanceof int[]) {
            return length > MAX_BUFFER_LENGTH_1 ? null : new int[length];
        }
        if (a instanceof long[]) {
            return length > MAX_BUFFER_LENGTH_2 ? null : new long[length];
        }
        if (a instanceof float[]) {
            return length > MAX_BUFFER_LENGTH_1 ? null : new float[length];
        }
        if (a instanceof double[]) {
            return length > MAX_BUFFER_LENGTH_2 ? null : new double[length];
        }
        throw new IllegalArgumentException("Unknown array: " + 
a.getClass().getName());
    } catch (OutOfMemoryError e) {
        return null;
    }
}
 
What do you think, what value of shift is the best, 6, 7, 8, 9, 10, 11, 12 etc.?
Runtime.getRuntime().maxMemory() >> 10??
 
Do you have actual scenarios? Actual requirements? Your feedback are welcome!

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

PR: https://git.openjdk.java.net/jdk/pull/3938

Reply via email to