Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-25 Thread iaroslavski
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

This change will not lead to more crashes.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-25 Thread quincunx-45
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

Will the VM still exit if 
-XX:+ExitOnOutOfMemoryError/-XX:+CrashOnOutOfMemoryError/-XX:OnOutOfMemoryError/...
 was specified? I.e. can this change lead to more (avoidable) crashes?

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-25 Thread Laurent Bourgès
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

Well explained, vladimir.

I propose to adopt max_heap / 128 min to stay less than 1% footprint.

Then factors are 7 for ints, 8 for long, min.

For 1gb heap, it gives 8mb, so 2m ints or 1m long.

Laurent

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-25 Thread iaroslavski
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

Hi Piotr,

I agree that catching out-of-memory-error is very rarely in prod.
I can say that LSD Radix sort works 3-5 times faster than Quicksort
(array of int 2M elements), merging sort works 10-30 (!) times faster
than Quicksort (structured array of int 2M elements), therefore it
is worth to use algorithms with additional buffers.

If we allocate buffer like 'new int[size]' and there is no free memory,
sorting fails with OOME. If we catch memory error, we switch to
in-place algorithms and sorting will be completed successfully.
I checked such use case, it works fine.

It doesn't matter if we run several threads or not. Some threads
may use additional buffers, some threads - not, but finally
all threads will be completed without errors.

The known problem with OOME is handling inside catch block.
If we try to create new object, try to log message with details,
we can face with new OOME. In DualPivotQuicksort we return null only,
no any actions, no new objects etc.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-21 Thread Piotr Tarsa
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

hi Vladimir,

the main reason i raise the issue with catching out-of-memory-error is that 
it's done very rarely in production code and also it's rather unpredictable 
when multiple things are going on (e.g. one thread can allocate a lot of 
memory, but other threads receive `oome`).

i've searched through /src/ in openjdk/jdk repository for `oome` (i.e. this 
one) and found that most times the `oome` is caught is in `java.desktop` module 
(probably this means the `oome` was related to native memory or other resources 
external to jvm), so i've narrowed search to `java.base`: 
https://github.com/search?q=outofmemoryerror+repo%3Aopenjdk%2Fjdk+path%3A%2Fsrc%2Fjava.base%2F+language%3AJava=Code=advsearch=Java
 and found just 2 cases of catching `oome` without always rethrowing it:
-  
https://github.com/openjdk/jdk/blob/d8b0b32f9f4049aa678809aa068978e3a4e29457/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java#L1304
 (but this rethrows if it internally fails with `oome` for a second time)
- 
https://github.com/openjdk/jdk/blob/739769c8fc4b496f08a92225a12d07414537b6c0/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java#L1171

overall, it seems that swallowing `oome` (i.e. in this case: catching and not 
rethrowing) is definitely not a readily used approach.

> 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:
> (...)
> 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.

sounds good

> Why do we need to use Math.min(…, Integer.MAX_VALUE)? (...) So, limit by 2 Gb 
> max is required.

yep, understood

> 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!

keeping the extra buffer size below 1% of max memory should be safe enough. 
currently the code is:

private static final int MAX_BUFFER_LENGTH =
(int) Math.min(Runtime.getRuntime().maxMemory() >> 6, 256L << 20);
// ...
private static Object tryAllocate(Object a, int length) {
if (length > MAX_BUFFER_LENGTH) {
return null;
}
try {
if (a instanceof int[]) {
return new int[length];
}
if (a instanceof long[]) {
return new long[length];
}
...

which means that in the worst case `sizeof(long) * (max memory >> 6) == 12.5% 
of heap size limit` would be used which is a lot when someone runs java code in 
memory constrained environment and that is rather common nowadays 
(microservices, containers, etc).

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-20 Thread iaroslavski
On Sun, 15 May 2022 14:17:41 GMT, Piotr Tarsa  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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-15 Thread Piotr Tarsa
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-15 Thread Laurent Bourgès
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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 checked the latest code: line 128:

Max length of additional buffer, limited by max_heap / 64 or 256mb elements 
(2gb max).

private static final int MAX_BUFFER_LENGTH =
(int) Math.min(Runtime.getRuntime().maxMemory() >> 6, 256L << 20);

So the current upper limit concerns the max length = max_heap_bytes / 64 (max 
heap/8) or 2gb (if heap is huge).

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-15 Thread Laurent Bourgès
On Fri, 13 May 2022 17:48:50 GMT, Piotr Tarsa  wrote:

> allocating extra buffers and catching OOME when sorting primitives is rather 
> unsatisfactory. you're not giving a reliable option for sorting under low 
> memory conditions. IMO at least the single-threaded primitives (ints, longs, 
> floats, etc all non-objects) sorting should be frugal when it comes to memory 
> usage.
> 
> just my 2 cents.

DPQS uses several sorting algorithms, merge sort & new radix sort need an extra 
buffer in contrary to isort, mixed isort, single and dual pivot quick sort.
In this PR an upper limit on the heap usage is in use min(max heap / 16, 128mb) 
to reduce the memory footprint. 
Anyway catching OOME now permits DPQS to use in-place but slower algorithms if 
the extra buffer can not be allocated.
Possibly the upper limit could be made configurable using system properties if 
it is really critical.
To sum up, low allocations are now under control in this PR.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-13 Thread Piotr Tarsa
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

allocating extra buffers and catching OOME when sorting primitives is rather 
unsatisfactory. you're not giving a reliable option for sorting under low 
memory conditions. IMO at least the single-threaded primitives (ints, longs, 
floats, etc all non-objects) sorting should be frugal when it comes to memory 
usage.

just my 2 cents.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-05-06 Thread Laurent Bourgès
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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 am improving test code (jmh + robust estimators) to have more robust results 
on small arrays (20 - 1000).
I do hope having new results within 1 or 2 weeks.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-04-25 Thread iaroslavski
On Mon, 14 Mar 2022 19:12:29 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> 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

waiting testing result from Laurent

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v12]

2022-03-14 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

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

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/95f15386..8a373741

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=11
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=10-11

  Stats: 2935 lines in 3 files changed: 1092 ins; 1401 del; 442 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v11]

2022-02-25 Thread iaroslavski
On Wed, 12 Jan 2022 14:22:03 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   * Updated javadoc
>   * Improved mixed insertion
>   * Optimized sort networking
>   * Improved pivot partitioning

New update is coming

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v11]

2022-01-12 Thread iaroslavski
On Wed, 12 Jan 2022 14:22:03 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   * Updated javadoc
>   * Improved mixed insertion
>   * Optimized sort networking
>   * Improved pivot partitioning

Please review optimized sorting code.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v11]

2022-01-12 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  * Updated javadoc
  * Improved mixed insertion
  * Optimized sort networking
  * Improved pivot partitioning

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/41b92f67..95f15386

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=10
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=09-10

  Stats: 798 lines in 1 file changed: 230 ins; 226 del; 342 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v10]

2022-01-12 Thread Laurent Bourgès
On Mon, 29 Nov 2021 21:16:32 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   * Updated javadoc
>   * Optimized insertion sort threshold
>   * Refactored parallel sorting section
>   * Improved step for pivot candidates
>   * Changed condition for Radix sort

Please review this PR, it is ready for months, or give comments, please !

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v10]

2021-12-12 Thread Laurent Bourgès
On Mon, 29 Nov 2021 21:16:32 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   * Updated javadoc
>   * Optimized insertion sort threshold
>   * Refactored parallel sorting section
>   * Improved step for pivot candidates
>   * Changed condition for Radix sort

Vladimir,
I updated the benchmarking code and here are the complete test results: system 
vs dpqs 21.5 vs 21.11:
https://github.com/bourgesl/nearly-optimal-mergesort-code/blob/master/sort-bench/results/2021/2021-12-final/DPQS-sort-1k-1M-stats.out

Full results:
https://github.com/bourgesl/nearly-optimal-mergesort-code/blob/master/sort-bench/results/2021/2021-12-final/sort-1k-1M-stats.out

All good, on 1k, 10k, 100k, 1m integer arrays.
Congratulations
拾

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v10]

2021-11-29 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  * Updated javadoc
  * Optimized insertion sort threshold
  * Refactored parallel sorting section
  * Improved step for pivot candidates
  * Changed condition for Radix sort

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/4baa9a39..41b92f67

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=09
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=08-09

  Stats: 128 lines in 2 files changed: 14 ins; 48 del; 66 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v9]

2021-11-28 Thread Laurent Bourgès
On Mon, 15 Nov 2021 16:20:07 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Updated comments for partitioning

As jdk18 Ramp Down 0 is approaching and jdk19 is being opened soon, maybe this 
PR review should be planned for jdk19 build 1 ?

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v9]

2021-11-18 Thread iaroslavski
On Mon, 15 Nov 2021 16:20:07 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Updated comments for partitioning

Hi all,

Not only Dual-Pivot Quicksort has been optimized, but I also improved test 
classes.
I measured coverage of these tests. It was shown that all methods, all branches 
are invoked.
So, we have full test coverage.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v9]

2021-11-17 Thread Laurent Bourgès
On Mon, 15 Nov 2021 16:20:07 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Updated comments for partitioning

Please core-libs reviewers could you have a look before jdk18 rdp0 or not ?

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v9]

2021-11-15 Thread Laurent Bourgès
On Mon, 15 Nov 2021 16:20:07 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Updated comments for partitioning

As I am not an official openjdk reviewer, I can not approve, but I do support

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v9]

2021-11-15 Thread iaroslavski
On Mon, 15 Nov 2021 16:20:07 GMT, iaroslavski  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Updated comments for partitioning

Hi reviewers!

@jhorstmann
@tarsa
@bourgesl
@richardstartin
@AlanBateman
@neliasso

I applied and tested all ideas/comments from Laurent and Alan,
the sorting sources (3 classes) are in final state.
Could you please review and approve the PR, if you don't have comments?

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v9]

2021-11-15 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  Updated comments for partitioning

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/e1b01cfb..4baa9a39

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=08
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=07-08

  Stats: 54 lines in 1 file changed: 0 ins; 0 del; 54 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v8]

2021-11-12 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  - Set limit for buffer length
  - Radix sort is invoked on fully random data
  - Use 3 steps in Radix sort isntead of 4 for int/float
  - Set better options for parallel sorting

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/ee7f6e82..e1b01cfb

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=07
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=06-07

  Stats: 182 lines in 2 files changed: 46 ins; 59 del; 77 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v7]

2021-10-29 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request with a new target base due to a merge 
or a rebase. The pull request now contains ten commits:

 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Merge with external changes
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Added more comments
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Better naming of methods
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Simplified mixed insertion sort
 - Merge remote-tracking branch 'upstream/master' into 
JDK-8266431-Dual-Pivot-Quicksort-improvements-Radix-sort
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Update target version
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Testing:
   - remove @since and @date, otherwise jtreg tag parser fails
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Sorting:
   
   - move radix sort out from quicksort partitioning
   - rename radixSort to tryRadixSort
   - minor javadoc and comment changes
   
   Testing:
   - rename radixSort to tryRadixSort in helper
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Sorting:
   
   - adopt radix sort for sequential and parallel sorts on 
int/long/float/double arrays (almost random and length > 6K)
   - fix tryMergeRuns() to better handle case when the last run is a single 
element
   - minor javadoc and comment changes
   
   Testing:
   - add new data inputs in tests for sorting
   - add min/max/infinity values to float/double testing
   - add tests for radix sort

-

Changes: https://git.openjdk.java.net/jdk/pull/3938/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jdk=3938=06
  Stats: 1288 lines in 3 files changed: 855 ins; 102 del; 331 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v6]

2021-10-08 Thread Laurent Bourgès
On Wed, 6 Oct 2021 21:21:29 GMT, iaroslavski 
 wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Added more comments

It is possible to use an upper limit on the array size to disable radix sort 
and reduce memory footprint and gc overhead...

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v6]

2021-10-08 Thread Laurent Bourgès
On Wed, 6 Oct 2021 21:21:29 GMT, iaroslavski 
 wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Added more comments

I want to give my point of view on the new memory requirements:
- as radix sort is used for length > 4k, more often a temporary buffer will be 
needed (size = array length), so more often young gen GC passes will happen and 
maybe full gc if this buffer is really big (half heap?)
- if OOME is encountered when the buffer is allocated, then dpqs is used 
(in-place no-alloc) so new sorting is more robust than dpqs in jdk17

Sorting tests could be made with verbose gc to ascertain the increased gc work, 
latency...

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v6]

2021-10-07 Thread iaroslavski
On Wed, 6 Oct 2021 21:21:29 GMT, iaroslavski 
 wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> iaroslavski has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
>   
>   Added more comments

LSD (Least Significant Digit) Radix sort is introduced to improve sorting.
Thшs algorithm requires additional buffer, but has O(n) complexity. At the
same time Quicksort performs at O(n*ln(n)). Radix sort shows extremely better
performance on large random data, whereas Quicksort or merging sort win
on other inputs.
 
We reuse additional buffer, if it is created during merge sort (in case of
parallel sorting on computer with many processors). The same approach is used
during allocation of buffer in merging sort. So, additional buffer is not
created twice.
 
We also check if we have enough memory for the buffer. Otherwise,
sorting is continued with in-place algorithms only.
 
Summary: introduced Radix sort requires the same amount memory
as merge or merging sorts, reuses it if necessary, but works much
faster than Quicksort.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v6]

2021-10-06 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  Added more comments

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/90c08aed..9989de5b

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=05
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=04-05

  Stats: 615 lines in 1 file changed: 295 ins; 173 del; 147 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v5]

2021-10-05 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  Better naming of methods

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/adcc6942..90c08aed

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=04
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=03-04

  Stats: 147 lines in 1 file changed: 0 ins; 0 del; 147 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v4]

2021-09-27 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  Simplified mixed insertion sort

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/6003fb69..adcc6942

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=03
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=02-03

  Stats: 204 lines in 1 file changed: 52 ins; 96 del; 56 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v3]

2021-09-16 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request with a new target base due to a merge 
or a rebase. The incremental webrev excludes the unrelated changes brought in 
by the merge/rebase. The pull request contains five additional commits since 
the last revision:

 - Merge remote-tracking branch 'upstream/master' into 
JDK-8266431-Dual-Pivot-Quicksort-improvements-Radix-sort
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Update target version
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Testing:
   - remove @since and @date, otherwise jtreg tag parser fails
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Sorting:
   
   - move radix sort out from quicksort partitioning
   - rename radixSort to tryRadixSort
   - minor javadoc and comment changes
   
   Testing:
   - rename radixSort to tryRadixSort in helper
 - JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
   
   Sorting:
   
   - adopt radix sort for sequential and parallel sorts on 
int/long/float/double arrays (almost random and length > 6K)
   - fix tryMergeRuns() to better handle case when the last run is a single 
element
   - minor javadoc and comment changes
   
   Testing:
   - add new data inputs in tests for sorting
   - add min/max/infinity values to float/double testing
   - add tests for radix sort

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/189f547a..6003fb69

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=02
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=01-02

  Stats: 781419 lines in 7625 files changed: 627030 ins; 118369 del; 36020 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort) [v2]

2021-09-14 Thread iaroslavski
> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

iaroslavski has updated the pull request incrementally with one additional 
commit since the last revision:

  JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)
  
  Update target version

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/3938/files
  - new: https://git.openjdk.java.net/jdk/pull/3938/files/2d972887..189f547a

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=3938=01
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=3938=00-01

  Stats: 3 lines in 2 files changed: 0 ins; 0 del; 3 mod
  Patch: https://git.openjdk.java.net/jdk/pull/3938.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/3938/head:pull/3938

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-14 Thread Richard Startin
On Tue, 14 Sep 2021 10:57:17 GMT, Alan Bateman  wrote:

>>> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
>>> believe this work derives from an unsigned radix sort I implemented on 
>>> 10/04/2021 
>>> [richardstartin/radix-sort-benchmark@ab4da23#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226](https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226)
>>>  which has numerous structural similarities to this work:
>>> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated 
>>> with me about doing so. On 25/04/2021 there was a new implementation of 
>>> `DualPivotQuicksort` with a signed radix sort but the same structural 
>>> similarities, and with the same method and variable names in places 
>>> [bourgesl/radix-sort-benchmark@90ff7e4#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609](https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609)
>> 
>> @iaroslavski The attribution is not clear here. Can you provide a summary as 
>> to who is contributing to this patch? I can't tell if all involved have 
>> signed the OCA or not. I'm sure there will be questions about space/time 
>> trade-offs with radix sort but I think it's important to first establish the 
>> origins of this patch first.
>
>> @AlanBateman Vertical pipeline of PR hides comments in the middle and you 
>> have to click on "Show more..." to see all comments. There are no claims 
>> related to the origin of my patch, it doesn't violate any rights.
> 
> There is a comment from richardstartin suggesting that something was derived 
> from code in his repo. Is this a benchmark that is not part of this PR? Only 
> asking because I can't find him on OCA signatories. You can use the Skara 
> /contributor command to list the contributors.

@AlanBateman my claim was that the implementation was derived from my 
implementation, and demonstrated a sequence of name changes after @bourgesl 
forked my repository containing a structurally similar radix sort 
implementation and benchmarks, in order to provide circumstantial evidence for 
my claim. Via email @iaroslavski told me that this was not the case, which I 
decided to accept at face value. So please judge this PR on its merits, and 
disregard the claims made in these comments. I have not signed an OCA but do 
not want to block this PR if the space time tradeoff is deemed acceptable.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-14 Thread iaroslavski
On Tue, 14 Sep 2021 10:57:17 GMT, Alan Bateman  wrote:

>>> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
>>> believe this work derives from an unsigned radix sort I implemented on 
>>> 10/04/2021 
>>> [richardstartin/radix-sort-benchmark@ab4da23#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226](https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226)
>>>  which has numerous structural similarities to this work:
>>> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated 
>>> with me about doing so. On 25/04/2021 there was a new implementation of 
>>> `DualPivotQuicksort` with a signed radix sort but the same structural 
>>> similarities, and with the same method and variable names in places 
>>> [bourgesl/radix-sort-benchmark@90ff7e4#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609](https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609)
>> 
>> @iaroslavski The attribution is not clear here. Can you provide a summary as 
>> to who is contributing to this patch? I can't tell if all involved have 
>> signed the OCA or not. I'm sure there will be questions about space/time 
>> trade-offs with radix sort but I think it's important to first establish the 
>> origins of this patch first.
>
>> @AlanBateman Vertical pipeline of PR hides comments in the middle and you 
>> have to click on "Show more..." to see all comments. There are no claims 
>> related to the origin of my patch, it doesn't violate any rights.
> 
> There is a comment from richardstartin suggesting that something was derived 
> from code in his repo. Is this a benchmark that is not part of this PR? Only 
> asking because I can't find him on OCA signatories. You can use the Skara 
> /contributor command to list the contributors.

Mentioned benchmarking is not a part of this PR. Our benchmarking was done by 
Laurent.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-14 Thread Alan Bateman
On Tue, 14 Sep 2021 09:23:23 GMT, Alan Bateman  wrote:

>> @richardstartin And one more addon: my first version of Radix sort, see my 
>> github https://github.com/iaroslavski/sorting/tree/master/radixsort uses 
>> another name, like skipBytes, then renamed to passLevel.
>> So, the common part is "skip". And this method has different number of 
>> parameters. I don't see any collision with your code.
>
>> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
>> believe this work derives from an unsigned radix sort I implemented on 
>> 10/04/2021 
>> [richardstartin/radix-sort-benchmark@ab4da23#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226](https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226)
>>  which has numerous structural similarities to this work:
>> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated with 
>> me about doing so. On 25/04/2021 there was a new implementation of 
>> `DualPivotQuicksort` with a signed radix sort but the same structural 
>> similarities, and with the same method and variable names in places 
>> [bourgesl/radix-sort-benchmark@90ff7e4#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609](https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609)
> 
> @iaroslavski The attribution is not clear here. Can you provide a summary as 
> to who is contributing to this patch? I can't tell if all involved have 
> signed the OCA or not. I'm sure there will be questions about space/time 
> trade-offs with radix sort but I think it's important to first establish the 
> origins of this patch first.

> @AlanBateman Vertical pipeline of PR hides comments in the middle and you 
> have to click on "Show more..." to see all comments. There are no claims 
> related to the origin of my patch, it doesn't violate any rights.

There is a comment from richardstartin suggesting that something was derived 
from code in his repo. Is this a benchmark that is not part of this PR? Only 
asking because I can't find him on OCA signatories. You can use the Skara 
/contributor command to list the contributors.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-14 Thread iaroslavski
On Tue, 14 Sep 2021 09:23:23 GMT, Alan Bateman  wrote:

>> @richardstartin And one more addon: my first version of Radix sort, see my 
>> github https://github.com/iaroslavski/sorting/tree/master/radixsort uses 
>> another name, like skipBytes, then renamed to passLevel.
>> So, the common part is "skip". And this method has different number of 
>> parameters. I don't see any collision with your code.
>
>> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
>> believe this work derives from an unsigned radix sort I implemented on 
>> 10/04/2021 
>> [richardstartin/radix-sort-benchmark@ab4da23#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226](https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226)
>>  which has numerous structural similarities to this work:
>> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated with 
>> me about doing so. On 25/04/2021 there was a new implementation of 
>> `DualPivotQuicksort` with a signed radix sort but the same structural 
>> similarities, and with the same method and variable names in places 
>> [bourgesl/radix-sort-benchmark@90ff7e4#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609](https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609)
> 
> @iaroslavski The attribution is not clear here. Can you provide a summary as 
> to who is contributing to this patch? I can't tell if all involved have 
> signed the OCA or not. I'm sure there will be questions about space/time 
> trade-offs with radix sort but I think it's important to first establish the 
> origins of this patch first.

@AlanBateman There was discussion with Richard Startin, where Laurent and I 
explained the origin of my patch. There was misunderstanding based on git 
changes only. Finally Richard wrote comment in PR on May 13, 2021,
I duplicate it here:

"In private correspondence with Vladimir, it was explained that where 
Vladimir's code and Laurent's code are identical, including typos (Vladimir's 
code, Laurent's code) it is because Vladimir sent the code to Laurent, not the 
other way around, therefore Vladimir's code does not derive from Laurent's, and 
it does not derive from mine. I can only trust that this is the case, so please 
disregard my claim that this is derivative work when reviewing this PR."

@AlanBateman Vertical pipeline of PR hides comments in the middle and you have 
to click on "Show more..." to see all comments. There are no claims related to 
the origin of my patch, it doesn't violate any rights.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-14 Thread Alan Bateman
On Thu, 13 May 2021 11:31:49 GMT, iaroslavski 
 wrote:

>> Perhaps we can resolve this issue in private - my email address is on my 
>> profile (or in the commits in `radix-sort-benchmark`)?
>
> @richardstartin And one more addon: my first version of Radix sort, see my 
> github https://github.com/iaroslavski/sorting/tree/master/radixsort uses 
> another name, like skipBytes, then renamed to passLevel.
> So, the common part is "skip". And this method has different number of 
> parameters. I don't see any collision with your code.

> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
> believe this work derives from an unsigned radix sort I implemented on 
> 10/04/2021 
> [richardstartin/radix-sort-benchmark@ab4da23#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226](https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226)
>  which has numerous structural similarities to this work:
> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated with 
> me about doing so. On 25/04/2021 there was a new implementation of 
> `DualPivotQuicksort` with a signed radix sort but the same structural 
> similarities, and with the same method and variable names in places 
> [bourgesl/radix-sort-benchmark@90ff7e4#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609](https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609)

@iaroslavski The attribution is not clear here. Can you provide a summary as to 
who is contributing to this patch? I can't tell if all involved have signed the 
OCA or not. I'm sure there will be questions about space/time trade-offs with 
radix sort but I think it's important to first establish the origins of this 
patch first.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Fri, 14 May 2021 17:50:11 GMT, Piotr Tarsa 
 wrote:

>> I made a JMH test on jdk16 to test count4 (xor) performance:
>> https://github.com/bourgesl/nearly-optimal-mergesort-code/tree/master/sort-bench/results/count_xor
>> 
>> 
>> Benchmark (size) Mode Cnt Score Error Units
>> ArrayXorBenchmark.arrayAndOriginal 100 avgt 20 684561,951 ± 2177,120 
>> ns/op
>> ArrayXorBenchmark.arrayXorOriginal 100 avgt 20 777255,465 ± 1815,136 
>> ns/op
>> ArrayXorBenchmark.arrayXor_Masked 100 avgt 20 814163,377 ± 2665,436 ns/op
>> ArrayXorBenchmark.arrayXor_Unsafe 100 avgt 20 707273,922 ± 2994,380 ns/op
>> 
>> Masked xor does not get optimized by c2 too.
>> 
>> Using Unsafe is better, see:
>> https://github.com/bourgesl/nearly-optimal-mergesort-code/blob/master/sort-bench/src/main/java/edu/sorting/bench/ArrayXorBenchmark.java
>> 
>> If you want, I could make another radixsort() using on or off heap count 
>> buffers and Unsafe, as I did in Marlin to avoid bound checks...
>
> I think an uncontroversial and efficient solution would be to replace
> 
> count4[(a[i] >>> 24) ^ 0x80]--;
> 
> with
> 
> count4[(a[i] >>> 24) & 0xFF]--;
> 
> and after finishing counting, first half of `count4` should be swapped with 
> second half of `count4`.

FYI I made another radixsortNew() using Unsafe to access to all count arrays:
https://github.com/bourgesl/nearly-optimal-mergesort-code/blob/dbfbd731ffd798defc75528cc1db04063bdb4619/src/edu/sorting/DualPivotQuicksort202105.java#L795

But it is only 2% faster in radix-sort-benchmark (1M arrays):
https://github.com/bourgesl/radix-sort-benchmark/blob/main/results/2021-ref/cmp-16-1M-full.log

It looks not worth the extra complexity for few percents, I think.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Nils Eliasson
On Thu, 20 May 2021 08:03:03 GMT, Nils Eliasson  wrote:

>> I agree with Laurent (bourgesl), see his comment on May 15 regarding to xor:
>> using Unsafe is only 2% faster, not worth the extra complexity for few 
>> percent.
>
> A small update of the XorINodes type calculation makes the bound check go 
> away. Testing now.

That bounds check shouldn't be there, it's an obvious case and will be fixed: 
https://github.com/openjdk/jdk/pull/4136

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Nils Eliasson
On Tue, 18 May 2021 19:58:35 GMT, iaroslavski 
 wrote:

>> https://bugs.openjdk.java.net/browse/JDK-8267332
>
> I agree with Laurent (bourgesl), see his comment on May 15 regarding to xor:
> using Unsafe is only 2% faster, not worth the extra complexity for few 
> percent.

A small update of the XorINodes type calculation makes the bound check go away. 
Testing now.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread iaroslavski
On Tue, 18 May 2021 18:06:21 GMT, Nils Eliasson  wrote:

>> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 672:
>> 
>>> 670: count2[(a[i] >>>  8) & 0xFF]--;
>>> 671: count3[(a[i] >>> 16) & 0xFF]--;
>>> 672: count4[(a[i] >>> 24) ^ 0x80]--;
>> 
>> It seems that C2 can't eliminate the bounds check here because of the `xor`, 
>> even though this can't possibly exceed 256. The three masked accesses above 
>> are all eliminated. Maybe someone could look in to improving that.
>
> https://bugs.openjdk.java.net/browse/JDK-8267332

I agree with Laurent (bourgesl), see his comment on May 15 regarding to xor:
using Unsafe is only 2% faster, not worth the extra complexity for few percent.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Sat, 8 May 2021 20:54:48 GMT, iaroslavski 
 wrote:

> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

src/java.base/share/classes/java/util/DualPivotQuicksort.java line 672:

> 670: count2[(a[i] >>>  8) & 0xFF]--;
> 671: count3[(a[i] >>> 16) & 0xFF]--;
> 672: count4[(a[i] >>> 24) ^ 0x80]--;

It seems that C2 can't eliminate the bounds check here because of the `xor`, 
even though this can't possibly exceed 256. The three masked accesses above are 
all eliminated. Maybe someone could look in to improving that.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Thu, 20 May 2021 21:21:26 GMT, Nils Eliasson  wrote:

>> A small update of the XorINodes type calculation makes the bound check go 
>> away. Testing now.
>
> That bounds check shouldn't be there, it's an obvious case and will be fixed: 
> https://github.com/openjdk/jdk/pull/4136

Thanks for fixing hotspot C2 (xor) so quickly !

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread iaroslavski
On Tue, 11 May 2021 14:37:21 GMT, Jörn Horstmann 
 wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 669:
> 
>> 667: 
>> 668: for (int i = low; i < high; ++i) {
>> 669: count1[ a[i] & 0xFF]--;
> 
> Not a reviewer, but having recently implemented a radixsort myself I'm 
> wondering what is the logic or benefit of decrementing and counting backwards 
> here?
> 
> One thing I did differently, and I'm not fully sure is an optimization, is 
> remembering the last bucket for each of the 4 counts. Checking whether the 
> data is already sorted by that digit can then be done by checking 
> `count[last_bucket] == size`, which avoids the first loop in `passLevel`. 
> Again, not sure whether it is actually faster, maybe the two separate simple 
> loops like here are better.

@jhorstmann In counting backwards we perform comparing with 0 in a loop, 
Comparing with 0 may be faster than comparing with other value. In general, 
backward or forward moving is your favor.

Keeping last_bucket and use check count[last_bucket] == size sounds good, but 
we need to run benchmarking and compare. I think we will not see big difference 
because the size of count array is too small, 256 only, whereas we scan whole 
array with size at least 6K. The corner case when we can see max effect of 
using last_bucket is array with all equal elements (4 count arrays will have 
only one non-zero element). but such array will be caught by tryMerge method.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Piotr Tarsa
On Fri, 14 May 2021 13:18:27 GMT, Laurent Bourgès  wrote:

>> I don't know Laurent, I find the handling of signed order over-complicated. 
>> Subtracting `Integer.MIN_VALUE` is really cheap...
>
> I made a JMH test on jdk16 to test count4 (xor) performance:
> https://github.com/bourgesl/nearly-optimal-mergesort-code/tree/master/sort-bench/results/count_xor
> 
> 
> Benchmark (size) Mode Cnt Score Error Units
> ArrayXorBenchmark.arrayAndOriginal 100 avgt 20 684561,951 ± 2177,120 ns/op
> ArrayXorBenchmark.arrayXorOriginal 100 avgt 20 777255,465 ± 1815,136 ns/op
> ArrayXorBenchmark.arrayXor_Masked 100 avgt 20 814163,377 ± 2665,436 ns/op
> ArrayXorBenchmark.arrayXor_Unsafe 100 avgt 20 707273,922 ± 2994,380 ns/op
> 
> Masked xor does not get optimized by c2 too.
> 
> Using Unsafe is better, see:
> https://github.com/bourgesl/nearly-optimal-mergesort-code/blob/master/sort-bench/src/main/java/edu/sorting/bench/ArrayXorBenchmark.java
> 
> If you want, I could make another radixsort() using on or off heap count 
> buffers and Unsafe, as I did in Marlin to avoid bound checks...

I think an uncontroversial and efficient solution would be to replace

count4[(a[i] >>> 24) ^ 0x80]--;

with

count4[(a[i] >>> 24) & 0xFF]--;

and after finishing counting, first half of `count4` should be swapped with 
second half of `count4`.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Nils Eliasson
On Thu, 13 May 2021 20:47:48 GMT, Richard Startin 
 wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 672:
> 
>> 670: count2[(a[i] >>>  8) & 0xFF]--;
>> 671: count3[(a[i] >>> 16) & 0xFF]--;
>> 672: count4[(a[i] >>> 24) ^ 0x80]--;
> 
> It seems that C2 can't eliminate the bounds check here because of the `xor`, 
> even though this can't possibly exceed 256. The three masked accesses above 
> are all eliminated. Maybe someone could look in to improving that.

https://bugs.openjdk.java.net/browse/JDK-8267332

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Jörn Horstmann
On Sat, 8 May 2021 20:54:48 GMT, iaroslavski 
 wrote:

> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

src/java.base/share/classes/java/util/DualPivotQuicksort.java line 669:

> 667: 
> 668: for (int i = low; i < high; ++i) {
> 669: count1[ a[i] & 0xFF]--;

Not a reviewer, but having recently implemented a radixsort myself I'm 
wondering what is the logic or benefit of decrementing and counting backwards 
here?

One thing I did differently, and I'm not fully sure is an optimization, is 
remembering the last bucket for each of the 4 counts. Checking whether the data 
is already sorted by that digit can then be done by checking 
`count[last_bucket] == size`, which avoids the first loop in `passLevel`. 
Again, not sure whether it is actually faster, maybe the two separate simple 
loops like here are better.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Fri, 14 May 2021 07:41:19 GMT, Richard Startin 
 wrote:

>> Great analysis on C2, richard.
>> 
>> maybe (x ^ 0x80) &0xFF would help C2 to eliminate bound checks...
>
> I don't know Laurent, I find the handling of signed order over-complicated. 
> Subtracting `Integer.MIN_VALUE` is really cheap...

I made a JMH test on jdk16 to test count4 (xor) performance:
https://github.com/bourgesl/nearly-optimal-mergesort-code/tree/master/sort-bench/results/count_xor


Benchmark (size) Mode Cnt Score Error Units
ArrayXorBenchmark.arrayAndOriginal 100 avgt 20 684561,951 ± 2177,120 ns/op
ArrayXorBenchmark.arrayXorOriginal 100 avgt 20 777255,465 ± 1815,136 ns/op
ArrayXorBenchmark.arrayXor_Masked 100 avgt 20 814163,377 ± 2665,436 ns/op
ArrayXorBenchmark.arrayXor_Unsafe 100 avgt 20 707273,922 ± 2994,380 ns/op

Masked xor does not get optimized by c2 too.

Using Unsafe is better, see:
https://github.com/bourgesl/nearly-optimal-mergesort-code/blob/master/sort-bench/src/main/java/edu/sorting/bench/ArrayXorBenchmark.java

If you want, I could make another radixsort() using on or off heap count 
buffers and Unsafe, as I did in Marlin to avoid bound checks...

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Thu, 13 May 2021 09:53:37 GMT, Richard Startin 
 wrote:

>> Laurent, the date in this class is not the date of our last commit,
>> this date is the date when I have final idea regarding to Radix sort,
>> therefore, I prefer to keep 2020.06.14
>
> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
> believe this work derives from an unsigned radix sort I implemented on 
> 10/04/2021 
> https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226
>  which has numerous structural similarities to this work:
> * Producing all four histograms in one pass
> * Skipping passes based on detecting the total in the histogram
> * Bailing out of the skip detection if a nonzero value not equal to the total 
> is encountered
> * Manually unrolling the LSD radix sort loop in order to avoid array copies
> 
> My implementation from 10th April is below for reference:
> 
>   public static void unrollOnePassHistogramsSkipLevels(int[] data) {
> int[] histogram1 = new int[257];
> int[] histogram2 = new int[257];
> int[] histogram3 = new int[257];
> int[] histogram4 = new int[257];
> 
> for (int value : data) {
>   ++histogram1[(value & 0xFF) + 1];
>   ++histogram2[((value >>> 8) & 0xFF) + 1];
>   ++histogram3[((value >>> 16) & 0xFF) + 1];
>   ++histogram4[(value >>> 24) + 1];
> }
> boolean skipLevel1 = canSkipLevel(histogram1, data.length);
> boolean skipLevel2 = canSkipLevel(histogram2, data.length);
> boolean skipLevel3 = canSkipLevel(histogram3, data.length);
> boolean skipLevel4 = canSkipLevel(histogram4, data.length);
> 
> if (skipLevel1 && skipLevel2 && skipLevel3 && skipLevel4) {
>   return;
> }
> int[] copy = new int[data.length];
> 
> int[] source = data;
> int[] dest = copy;
> 
> if (!skipLevel1) {
>   for (int i = 1; i < histogram1.length; ++i) {
> histogram1[i] += histogram1[i - 1];
>   }
>   for (int value : source) {
> dest[histogram1[value & 0xFF]++] = value;
>   }
>   if (!skipLevel2 || !skipLevel3 || !skipLevel4) {
> int[] tmp = dest;
> dest = source;
> source = tmp;
>   }
> }
> 
> if (!skipLevel2) {
>   for (int i = 1; i < histogram2.length; ++i) {
> histogram2[i] += histogram2[i - 1];
>   }
>   for (int value : source) {
> dest[histogram2[(value >>> 8) & 0xFF]++] = value;
>   }
>   if (!skipLevel3 || !skipLevel4) {
> int[] tmp = dest;
> dest = source;
> source = tmp;
>   }
> }
> 
> if (!skipLevel3) {
>   for (int i = 1; i < histogram3.length; ++i) {
> histogram3[i] += histogram3[i - 1];
>   }
>   for (int value : data) {
> dest[histogram3[(value >>> 16) & 0xFF]++] = value;
>   }
>   if (!skipLevel4) {
> int[] tmp = dest;
> dest = source;
> source = tmp;
>   }
> }
> 
> if (!skipLevel4) {
>   for (int i = 1; i < histogram4.length; ++i) {
> histogram4[i] += histogram4[i - 1];
>   }
>   for (int value : source) {
> dest[histogram4[value >>> 24]++] = value;
>   }
> }
> if (dest != data) {
>   System.arraycopy(dest, 0, data, 0, data.length);
> }
>   }
> 
>   private static boolean canSkipLevel(int[] histogram, int dataSize) {
> for (int count : histogram) {
>   if (count == dataSize) {
> return true;
>   } else if (count > 0) {
> return false;
>   }
> }
> return true;
>   }
> 
> 
> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated with 
> me about doing so. On 25/04/2021 there was a new implementation of 
> `DualPivotQuicksort` with a signed radix sort but the same structural 
> similarities, and with the same method and variable names in places 
> https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609
> 
> 
> // TODO add javadoc
> private static void radixSort(Sorter sorter, int[] a, int low, int high) {
> int[] b;
> // LBO: prealloc (high - low) +1 element:
> if (sorter == null || (b = sorter.b) == null || b.length < (high - 
> low)) {
> // System.out.println("alloc b: " + (high - low));
> b = new int[high - low];
> }
> 
> int[] count1, count2, count3, count4;
> if (sorter != null) {
> sorter.resetRadixBuffers();
> count1 = sorter.count1;
> count2 = sorter.count2;
> count3 = sorter.count3;
> count4 = sorter.count4;
> } else {
> // System.out.println("alloc radix buffers(4x256)");
> count1 = new int[256];
> count2 = new int[256];
> count3 = new int[256];
>  

Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Thu, 13 May 2021 10:22:57 GMT, Laurent Bourgès  wrote:

>> Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I 
>> believe this work derives from an unsigned radix sort I implemented on 
>> 10/04/2021 
>> https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226
>>  which has numerous structural similarities to this work:
>> * Producing all four histograms in one pass
>> * Skipping passes based on detecting the total in the histogram
>> * Bailing out of the skip detection if a nonzero value not equal to the 
>> total is encountered
>> * Manually unrolling the LSD radix sort loop in order to avoid array copies
>> 
>> My implementation from 10th April is below for reference:
>> 
>>   public static void unrollOnePassHistogramsSkipLevels(int[] data) {
>> int[] histogram1 = new int[257];
>> int[] histogram2 = new int[257];
>> int[] histogram3 = new int[257];
>> int[] histogram4 = new int[257];
>> 
>> for (int value : data) {
>>   ++histogram1[(value & 0xFF) + 1];
>>   ++histogram2[((value >>> 8) & 0xFF) + 1];
>>   ++histogram3[((value >>> 16) & 0xFF) + 1];
>>   ++histogram4[(value >>> 24) + 1];
>> }
>> boolean skipLevel1 = canSkipLevel(histogram1, data.length);
>> boolean skipLevel2 = canSkipLevel(histogram2, data.length);
>> boolean skipLevel3 = canSkipLevel(histogram3, data.length);
>> boolean skipLevel4 = canSkipLevel(histogram4, data.length);
>> 
>> if (skipLevel1 && skipLevel2 && skipLevel3 && skipLevel4) {
>>   return;
>> }
>> int[] copy = new int[data.length];
>> 
>> int[] source = data;
>> int[] dest = copy;
>> 
>> if (!skipLevel1) {
>>   for (int i = 1; i < histogram1.length; ++i) {
>> histogram1[i] += histogram1[i - 1];
>>   }
>>   for (int value : source) {
>> dest[histogram1[value & 0xFF]++] = value;
>>   }
>>   if (!skipLevel2 || !skipLevel3 || !skipLevel4) {
>> int[] tmp = dest;
>> dest = source;
>> source = tmp;
>>   }
>> }
>> 
>> if (!skipLevel2) {
>>   for (int i = 1; i < histogram2.length; ++i) {
>> histogram2[i] += histogram2[i - 1];
>>   }
>>   for (int value : source) {
>> dest[histogram2[(value >>> 8) & 0xFF]++] = value;
>>   }
>>   if (!skipLevel3 || !skipLevel4) {
>> int[] tmp = dest;
>> dest = source;
>> source = tmp;
>>   }
>> }
>> 
>> if (!skipLevel3) {
>>   for (int i = 1; i < histogram3.length; ++i) {
>> histogram3[i] += histogram3[i - 1];
>>   }
>>   for (int value : data) {
>> dest[histogram3[(value >>> 16) & 0xFF]++] = value;
>>   }
>>   if (!skipLevel4) {
>> int[] tmp = dest;
>> dest = source;
>> source = tmp;
>>   }
>> }
>> 
>> if (!skipLevel4) {
>>   for (int i = 1; i < histogram4.length; ++i) {
>> histogram4[i] += histogram4[i - 1];
>>   }
>>   for (int value : source) {
>> dest[histogram4[value >>> 24]++] = value;
>>   }
>> }
>> if (dest != data) {
>>   System.arraycopy(dest, 0, data, 0, data.length);
>> }
>>   }
>> 
>>   private static boolean canSkipLevel(int[] histogram, int dataSize) {
>> for (int count : histogram) {
>>   if (count == dataSize) {
>> return true;
>>   } else if (count > 0) {
>> return false;
>>   }
>> }
>> return true;
>>   }
>> 
>> 
>> Moreover, @bourgesl forked my repository on 11/04/2021 and communicated with 
>> me about doing so. On 25/04/2021 there was a new implementation of 
>> `DualPivotQuicksort` with a signed radix sort but the same structural 
>> similarities, and with the same method and variable names in places 
>> https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609
>> 
>> 
>> // TODO add javadoc
>> private static void radixSort(Sorter sorter, int[] a, int low, int high) 
>> {
>> int[] b;
>> // LBO: prealloc (high - low) +1 element:
>> if (sorter == null || (b = sorter.b) == null || b.length < (high - 
>> low)) {
>> // System.out.println("alloc b: " + (high - low));
>> b = new int[high - low];
>> }
>> 
>> int[] count1, count2, count3, count4;
>> if (sorter != null) {
>> sorter.resetRadixBuffers();
>> count1 = sorter.count1;
>> count2 = sorter.count2;
>> count3 = sorter.count3;
>> count4 = sorter.count4;
>> } else {
>> // System.out.println("alloc radix buffers(4x256)");
>> count1 = new int[256];
>> count2 = new int[256];
>> count3 = new int[256];
>> count4 = new int[256];
>> }
>> 
>> 

Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Thu, 13 May 2021 21:44:38 GMT, Richard Startin 
 wrote:

>> For what it's worth, I benchmarked this implementation radix sort ([adapted 
>> here to fit in to my 
>> harness](https://github.com/richardstartin/radix-sort-benchmark/commit/07169e8e8602152cfda859baa159db165bf5fcab#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR681-R710782))
>>  against a [signed 
>> variant](https://github.com/richardstartin/radix-sort-benchmark/commit/07169e8e8602152cfda859baa159db165bf5fcab#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR396-R478)
>>  of what I have claimed this work was derived from and the proposed 
>> implementation does not perform favourably on uniformly random data:
>> 
>> 
>> 
>> Benchmark (bits)  (padding)  
>> (scenario)  (seed)   (size)  Mode  Cnt  Score Error  Units
>> RadixSortBenchmark.jdk17  7 
>> UNIFORM   0  100  avgt5  11301.950 ± 113.691  us/op
>> RadixSortBenchmark.jdk23  7 
>> UNIFORM   0  100  avgt5  11792.351 ±  60.757  us/op
>> RadixSortBenchmark.jdk30  7 
>> UNIFORM   0  100  avgt5  11184.616 ±  67.094  us/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  17  7 
>> UNIFORM   0  100  avgt5   9564.626 ±  69.497  us/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  23  7 
>> UNIFORM   0  100  avgt5   9432.085 ±  58.983  us/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  30  7 
>> UNIFORM   0  100  avgt5  10772.975 ±  51.848  us/op
>> 
>> 
>> 
>> I believe the root cause is a defect in the mechanism employed to skip 
>> passes as can be seen by the increased number of instructions and cycles 
>> here. In the proposed implementation, instructions is roughly constant as a 
>> function of bits. In the case where all passes must be performed (bits = 
>> 30), IPC is superior in `unrollOnePassHistogramsSkipLevelsSigned`.
>> 
>> 
>> Benchmark   
>> (bits)  (padding)  (scenario)  (seed)   (size)  Mode  Cnt Score 
>> Error  Units
>> RadixSortBenchmark.jdk:cycles   
>> 17  7 UNIFORM   0  100  avgt   34976971.877  
>>#/op
>> RadixSortBenchmark.jdk:instructions 
>> 17  7 UNIFORM   0  100  avgt   70121142.003  
>>#/op
>> RadixSortBenchmark.jdk:cycles   
>> 23  7 UNIFORM   0  100  avgt   32369970.385  
>>#/op
>> RadixSortBenchmark.jdk:instructions 
>> 23  7 UNIFORM   0  100  avgt   70201664.963  
>>#/op
>> RadixSortBenchmark.jdk:cycles   
>> 30  7 UNIFORM   0  100  avgt   30789736.602  
>>#/op
>> RadixSortBenchmark.jdk:instructions 
>> 30  7 UNIFORM   0  100  avgt   70180942.122  
>>#/op
>> RadixSortBenchmark.jdk:IPC  
>> 30  7 UNIFORM   0  100  avgt  2.279  
>>   insns/clk
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:cycles 
>> 17  7 UNIFORM   0  100  avgt   26983994.479  
>>#/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:instructions   
>> 17  7 UNIFORM   0  100  avgt   62065304.827  
>>#/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:cycles 
>> 23  7 UNIFORM   0  100  avgt   26161703.124  
>>#/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:instructions   
>> 23  7 UNIFORM   0  100  avgt   63102683.167  
>>#/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:cycles 
>> 30  7 UNIFORM   0  100  avgt   29780103.795  
>>#/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:instructions   
>> 30  7 UNIFORM   0  100  avgt   74437097.025  
>>#/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:IPC
>> 30  7 UNIFORM   0  100  avgt  2.500  
>>   insns/clk
>> 
>> 
>> 
>> The biggest difference in executed code appears to be that bounds checks are 
>> not eliminated in the first counting pass in the proposed implementation:
>> 
>> 
>> [Hottest Region 
>> 

Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Fri, 14 May 2021 07:14:27 GMT, Laurent Bourgès  wrote:

>> So the issue of not skipping passes was my fault in the translation process, 
>> so not something to worry about, though after [fixing 
>> that](https://github.com/richardstartin/radix-sort-benchmark/commit/ccbee984c6a0e0f50c30de59e1a5e9fbcad89510)
>>  the original implementation still has the edge because of the bounds checks 
>> on the `xor` not getting eliminated.
>> 
>> 
>> Benchmark (bits)  (padding)  
>> (scenario)  (seed)   (size)  Mode  Cnt  ScoreError  Units
>> RadixSortBenchmark.jdk17  7 
>> UNIFORM   0  100  avgt5  10432.408 ± 87.024  us/op
>> RadixSortBenchmark.jdk23  7 
>> UNIFORM   0  100  avgt5   9465.990 ± 40.598  us/op
>> RadixSortBenchmark.jdk30  7 
>> UNIFORM   0  100  avgt5  11189.146 ± 50.972  us/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  17  7 
>> UNIFORM   0  100  avgt5   9546.963 ± 41.698  us/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  23  7 
>> UNIFORM   0  100  avgt5   9412.114 ± 43.081  us/op
>> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  30  7 
>> UNIFORM   0  100  avgt5  10823.618 ± 64.311  us/op
>
> Great analysis on C2, richard.
> 
> maybe (x ^ 0x80) &0xFF would help C2 to eliminate bound checks...

I don't know Laurent, I find the handling of signed order over-complicated. 
Subtracting `Integer.MIN_VALUE` is really cheap...

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Thu, 13 May 2021 14:44:28 GMT, Richard Startin 
 wrote:

>> @iaroslavski I would prefer to discuss this in private than here, but my 
>> argument is that the name `skipByte` came from Laurent's code, and that 
>> Laurent's code was clearly derived from my own within a fork of my 
>> repository. I linked the commits where you changed `skipByte` to `passLevel` 
>> and Laurent changed my name `canSkipLevel` to `skipByte`. 
>> 
>> For me, this raises questions about the independence of your work from 
>> Laurent's, and Laurent's work is clearly derived from my own (and I don't 
>> think anyone is disputing the latter). I would be happy to sort this out in 
>> private.
>
> In private correspondence with Vladimir, it was explained that where 
> Vladimir's code and Laurent's code are identical, including typos 
> ([Vladimir's 
> code](https://github.com/iaroslavski/sorting/commit/f076073b8b819a9687613903a164e3ed71821769#diff-4b4d68fc834c2ad12a9fb9d316a812221af7c398338ed2ee907d0a795e7aadafR672),
>  [Laurent's 
> code](https://github.com/bourgesl/radix-sort-benchmark/commit/a693b26b2e2c14cfeedf9c753c9d643096b0e38d#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R719))
>  it is because Vladimir sent the code to Laurent, not the other way around, 
> therefore Vladimir's code does not derive from Laurent's, and it does not 
> derive from mine. I can only trust that this is the case, so please disregard 
> my claim that this is derivative work when reviewing this PR.

For what it's worth, I benchmarked this implementation radix sort ([adapted 
here to fit in to my 
harness](https://github.com/richardstartin/radix-sort-benchmark/commit/07169e8e8602152cfda859baa159db165bf5fcab#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR681-R710782))
 against a [signed 
variant](https://github.com/richardstartin/radix-sort-benchmark/commit/07169e8e8602152cfda859baa159db165bf5fcab#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR396-R478)
 of what I have claimed this work was derived from and the proposed 
implementation does not perform favourably on uniformly random data:



Benchmark (bits)  (padding)  (scenario) 
 (seed)   (size)  Mode  Cnt  Score Error  Units
RadixSortBenchmark.jdk17  7 UNIFORM 
  0  100  avgt5  11301.950 ± 113.691  us/op
RadixSortBenchmark.jdk23  7 UNIFORM 
  0  100  avgt5  11792.351 ±  60.757  us/op
RadixSortBenchmark.jdk30  7 UNIFORM 
  0  100  avgt5  11184.616 ±  67.094  us/op
RadixSortBenchmark.unrollOnePassSkipLevelsSigned  17  7 UNIFORM 
  0  100  avgt5   9564.626 ±  69.497  us/op
RadixSortBenchmark.unrollOnePassSkipLevelsSigned  23  7 UNIFORM 
  0  100  avgt5   9432.085 ±  58.983  us/op
RadixSortBenchmark.unrollOnePassSkipLevelsSigned  30  7 UNIFORM 
  0  100  avgt5  10772.975 ±  51.848  us/op



I believe the root cause is a defect in the mechanism employed to skip passes 
as can be seen by the increased number of instructions and cycles here. In the 
proposed implementation, instructions is roughly constant as a function of 
bits. In the case where all passes must be performed (bits = 30), IPC is 
superior in `unrollOnePassHistogramsSkipLevelsSigned`.


Benchmark   (bits)  
(padding)  (scenario)  (seed)   (size)  Mode  Cnt Score Error  
Units
RadixSortBenchmark.jdk:cycles   17  
7 UNIFORM   0  100  avgt   34976971.877 
#/op
RadixSortBenchmark.jdk:instructions 17  
7 UNIFORM   0  100  avgt   70121142.003 
#/op
RadixSortBenchmark.jdk:cycles   23  
7 UNIFORM   0  100  avgt   32369970.385 
#/op
RadixSortBenchmark.jdk:instructions 23  
7 UNIFORM   0  100  avgt   70201664.963 
#/op
RadixSortBenchmark.jdk:cycles   30  
7 UNIFORM   0  100  avgt   30789736.602 
#/op
RadixSortBenchmark.jdk:instructions 30  
7 UNIFORM   0  100  avgt   70180942.122 
#/op
RadixSortBenchmark.jdk:IPC  30  
7 UNIFORM   0  100  avgt  2.279
insns/clk
RadixSortBenchmark.unrollOnePassSkipLevelsSigned:cycles 17  
7 UNIFORM   0  100  avgt   26983994.479 
#/op

Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Thu, 13 May 2021 20:23:16 GMT, Richard Startin 
 wrote:

>> In private correspondence with Vladimir, it was explained that where 
>> Vladimir's code and Laurent's code are identical, including typos 
>> ([Vladimir's 
>> code](https://github.com/iaroslavski/sorting/commit/f076073b8b819a9687613903a164e3ed71821769#diff-4b4d68fc834c2ad12a9fb9d316a812221af7c398338ed2ee907d0a795e7aadafR672),
>>  [Laurent's 
>> code](https://github.com/bourgesl/radix-sort-benchmark/commit/a693b26b2e2c14cfeedf9c753c9d643096b0e38d#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R719))
>>  it is because Vladimir sent the code to Laurent, not the other way around, 
>> therefore Vladimir's code does not derive from Laurent's, and it does not 
>> derive from mine. I can only trust that this is the case, so please 
>> disregard my claim that this is derivative work when reviewing this PR.
>
> For what it's worth, I benchmarked this implementation radix sort ([adapted 
> here to fit in to my 
> harness](https://github.com/richardstartin/radix-sort-benchmark/commit/07169e8e8602152cfda859baa159db165bf5fcab#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR681-R710782))
>  against a [signed 
> variant](https://github.com/richardstartin/radix-sort-benchmark/commit/07169e8e8602152cfda859baa159db165bf5fcab#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR396-R478)
>  of what I have claimed this work was derived from and the proposed 
> implementation does not perform favourably on uniformly random data:
> 
> 
> 
> Benchmark (bits)  (padding)  
> (scenario)  (seed)   (size)  Mode  Cnt  Score Error  Units
> RadixSortBenchmark.jdk17  7 
> UNIFORM   0  100  avgt5  11301.950 ± 113.691  us/op
> RadixSortBenchmark.jdk23  7 
> UNIFORM   0  100  avgt5  11792.351 ±  60.757  us/op
> RadixSortBenchmark.jdk30  7 
> UNIFORM   0  100  avgt5  11184.616 ±  67.094  us/op
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  17  7 
> UNIFORM   0  100  avgt5   9564.626 ±  69.497  us/op
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  23  7 
> UNIFORM   0  100  avgt5   9432.085 ±  58.983  us/op
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned  30  7 
> UNIFORM   0  100  avgt5  10772.975 ±  51.848  us/op
> 
> 
> 
> I believe the root cause is a defect in the mechanism employed to skip passes 
> as can be seen by the increased number of instructions and cycles here. In 
> the proposed implementation, instructions is roughly constant as a function 
> of bits. In the case where all passes must be performed (bits = 30), IPC is 
> superior in `unrollOnePassHistogramsSkipLevelsSigned`.
> 
> 
> Benchmark   
> (bits)  (padding)  (scenario)  (seed)   (size)  Mode  Cnt Score 
> Error  Units
> RadixSortBenchmark.jdk:cycles   
> 17  7 UNIFORM   0  100  avgt   34976971.877   
>   #/op
> RadixSortBenchmark.jdk:instructions 
> 17  7 UNIFORM   0  100  avgt   70121142.003   
>   #/op
> RadixSortBenchmark.jdk:cycles   
> 23  7 UNIFORM   0  100  avgt   32369970.385   
>   #/op
> RadixSortBenchmark.jdk:instructions 
> 23  7 UNIFORM   0  100  avgt   70201664.963   
>   #/op
> RadixSortBenchmark.jdk:cycles   
> 30  7 UNIFORM   0  100  avgt   30789736.602   
>   #/op
> RadixSortBenchmark.jdk:instructions 
> 30  7 UNIFORM   0  100  avgt   70180942.122   
>   #/op
> RadixSortBenchmark.jdk:IPC  
> 30  7 UNIFORM   0  100  avgt  2.279   
>  insns/clk
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:cycles 
> 17  7 UNIFORM   0  100  avgt   26983994.479   
>   #/op
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:instructions   
> 17  7 UNIFORM   0  100  avgt   62065304.827   
>   #/op
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:cycles 
> 23  7 UNIFORM   0  100  avgt   26161703.124   
>   #/op
> RadixSortBenchmark.unrollOnePassSkipLevelsSigned:instructions   
> 23  7 UNIFORM   0  100  avgt   63102683.167   

Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Thu, 13 May 2021 11:31:49 GMT, iaroslavski 
 wrote:

>> Perhaps we can resolve this issue in private - my email address is on my 
>> profile (or in the commits in `radix-sort-benchmark`)?
>
> @richardstartin And one more addon: my first version of Radix sort, see my 
> github https://github.com/iaroslavski/sorting/tree/master/radixsort uses 
> another name, like skipBytes, then renamed to passLevel.
> So, the common part is "skip". And this method has different number of 
> parameters. I don't see any collision with your code.

@iaroslavski I would prefer to discuss this in private than here, but my 
argument is that the name `skipByte` came from Laurent's code, and that 
Laurent's code was clearly derived from my own within a fork of my repository. 
I linked the commits where you changed `skipByte` to `passLevel` and Laurent 
changed my name `canSkipLevel` to `skipByte`. 

For me, this raises questions about the independence of your work from 
Laurent's, and Laurent's work is clearly derived from my own (and I don't think 
anyone is disputing the latter). I would be happy to sort this out in private.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Thu, 13 May 2021 11:47:58 GMT, Richard Startin 
 wrote:

>> @richardstartin And one more addon: my first version of Radix sort, see my 
>> github https://github.com/iaroslavski/sorting/tree/master/radixsort uses 
>> another name, like skipBytes, then renamed to passLevel.
>> So, the common part is "skip". And this method has different number of 
>> parameters. I don't see any collision with your code.
>
> @iaroslavski I would prefer to discuss this in private than here, but my 
> argument is that the name `skipByte` came from Laurent's code, and that 
> Laurent's code was clearly derived from my own within a fork of my 
> repository. I linked the commits where you changed `skipByte` to `passLevel` 
> and Laurent changed my name `canSkipLevel` to `skipByte`. 
> 
> For me, this raises questions about the independence of your work from 
> Laurent's, and Laurent's work is clearly derived from my own (and I don't 
> think anyone is disputing the latter). I would be happy to sort this out in 
> private.

In private correspondence with Vladimir, it was explained that where Vladimir's 
code and Laurent's code are identical, including typos ([Vladimir's 
code](https://github.com/iaroslavski/sorting/commit/f076073b8b819a9687613903a164e3ed71821769#diff-4b4d68fc834c2ad12a9fb9d316a812221af7c398338ed2ee907d0a795e7aadafR672),
 [Laurent's 
code](https://github.com/bourgesl/radix-sort-benchmark/commit/a693b26b2e2c14cfeedf9c753c9d643096b0e38d#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R719))
 it is because Vladimir sent the code to Laurent, not the other way around, 
therefore Vladimir's code does not derive from Laurent's, and it does not 
derive from mine. I can only trust that this is the case, so please disregard 
my claim that this is derivative work when reviewing this PR.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread iaroslavski
On Thu, 13 May 2021 10:53:48 GMT, Richard Startin 
 wrote:

>> You misunderstood my approach:
>> - vladimir & tagir discussed radix sorts since previous work on DPQS in 2019
>> - I enjoyed reading your blog post testing the performance of your radix 
>> sort vs Arrays.sort()
>> - I tested and forked your radix-sort-benchmark to reproduce your 
>> experiments on openjdk16 (dpqs 19.11)
>> - Vladimir proposed his own radixsort()
>> - I did port DPQS impls in my fork of your benchmark to make a global 
>> comparison: dpqs 11, 19, 21 vs yours + arrays.sort(): it helped comparing 
>> implementations and decide when radix sort wins depending on dataset 
>> presortness
>> - I tried many variants on my github repositories, but Vladimir never merged 
>> any of my change as he is not a regular github user (clone, fork, merge).
>> 
>> Our goal is not to underestimate your work (sort + benchmark) but Vladimir 
>> wrote his own code, me many experiments (tests, benchmarks) to obtain this 
>> original patch, written by Vladimir, with his radix sort implementation 
>> working on any int/long/float/double arrays, following the GPLv2 license.
>> 
>> You gave me motivation to make Arrays.sort() faster and we worked hard to 
>> write, test and benchmark this patch to be ready for OpenJDK 17
>
> Perhaps we can resolve this issue in private - my email address is on my 
> profile (or in the commits in `radix-sort-benchmark`)?

@richardstartin The ideas to take 4 histograms at once or use check to skip 
digits are very simple and come not only from you, for example, see article 
from 2001, http://stereopsis.com/radix.html

When Laurent and I discussed our Radix sort, your code was demonstrated. I 
wrote my implementation and at the first version I took the similar names (even 
not perfect for my cases) and later I renamed them to better values.

You can see that from functional point of view your code and my code are 
different, they process skipped digits in different manner, No your code was 
copied.

Date 2020.06.14 means the start of my activities on Radix sort, not final 
version.

Let me know, if you have any questions

@richardstartin And one more addon: my first version of Radix sort, see my 
github https://github.com/iaroslavski/sorting/tree/master/radixsort uses 
another name, like skipBytes, then renamed to passLevel.
So, the common part is "skip". And this method has different number of 
parameters. I don't see any collision with your code.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Richard Startin
On Wed, 12 May 2021 12:20:09 GMT, iaroslavski 
 wrote:

>> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 47:
>> 
>>> 45:  * @author Doug Lea
>>> 46:  *
>>> 47:  * @version 2020.06.14
>> 
>> Vladimir, I would update to 2021.05.06 (+your hash)
>
> Laurent, the date in this class is not the date of our last commit,
> this date is the date when I have final idea regarding to Radix sort,
> therefore, I prefer to keep 2020.06.14

Hi @iaroslavski I'm unconvinced that this work was from 14/06/2020 - I believe 
this work derives from an unsigned radix sort I implemented on 10/04/2021 
https://github.com/richardstartin/radix-sort-benchmark/commit/ab4da230e1d0ac68e5ee2cee38d71c7e7d50f49b#diff-6c13d3fb74f38906677dbfa1a70a123c8e5baf4a39219c81ef121e078d0013bcR226
 which has numerous structural similarities to this work:
* Producing all four histograms in one pass
* Skipping passes based on detecting the total in the histogram
* Bailing out of the skip detection if a nonzero value not equal to the total 
is encountered
* Manually unrolling the LSD radix sort loop in order to avoid array copies

My implementation from 10th April is below for reference:

  public static void unrollOnePassHistogramsSkipLevels(int[] data) {
int[] histogram1 = new int[257];
int[] histogram2 = new int[257];
int[] histogram3 = new int[257];
int[] histogram4 = new int[257];

for (int value : data) {
  ++histogram1[(value & 0xFF) + 1];
  ++histogram2[((value >>> 8) & 0xFF) + 1];
  ++histogram3[((value >>> 16) & 0xFF) + 1];
  ++histogram4[(value >>> 24) + 1];
}
boolean skipLevel1 = canSkipLevel(histogram1, data.length);
boolean skipLevel2 = canSkipLevel(histogram2, data.length);
boolean skipLevel3 = canSkipLevel(histogram3, data.length);
boolean skipLevel4 = canSkipLevel(histogram4, data.length);

if (skipLevel1 && skipLevel2 && skipLevel3 && skipLevel4) {
  return;
}
int[] copy = new int[data.length];

int[] source = data;
int[] dest = copy;

if (!skipLevel1) {
  for (int i = 1; i < histogram1.length; ++i) {
histogram1[i] += histogram1[i - 1];
  }
  for (int value : source) {
dest[histogram1[value & 0xFF]++] = value;
  }
  if (!skipLevel2 || !skipLevel3 || !skipLevel4) {
int[] tmp = dest;
dest = source;
source = tmp;
  }
}

if (!skipLevel2) {
  for (int i = 1; i < histogram2.length; ++i) {
histogram2[i] += histogram2[i - 1];
  }
  for (int value : source) {
dest[histogram2[(value >>> 8) & 0xFF]++] = value;
  }
  if (!skipLevel3 || !skipLevel4) {
int[] tmp = dest;
dest = source;
source = tmp;
  }
}

if (!skipLevel3) {
  for (int i = 1; i < histogram3.length; ++i) {
histogram3[i] += histogram3[i - 1];
  }
  for (int value : data) {
dest[histogram3[(value >>> 16) & 0xFF]++] = value;
  }
  if (!skipLevel4) {
int[] tmp = dest;
dest = source;
source = tmp;
  }
}

if (!skipLevel4) {
  for (int i = 1; i < histogram4.length; ++i) {
histogram4[i] += histogram4[i - 1];
  }
  for (int value : source) {
dest[histogram4[value >>> 24]++] = value;
  }
}
if (dest != data) {
  System.arraycopy(dest, 0, data, 0, data.length);
}
  }

  private static boolean canSkipLevel(int[] histogram, int dataSize) {
for (int count : histogram) {
  if (count == dataSize) {
return true;
  } else if (count > 0) {
return false;
  }
}
return true;
  }


Moreover, @bourgesl forked my repository on 11/04/2021 and communicated with me 
about doing so. On 25/04/2021 there was a new implementation of 
`DualPivotQuicksort` with a signed radix sort but the same structural 
similarities, and with the same method and variable names in places 
https://github.com/bourgesl/radix-sort-benchmark/commit/90ff7e427da0fa49f374bff0241fb2487bd87bde#diff-397ce8fd791e2ce508cf9127201bc9ab46264cd2a79fd0487a63569f2e4b59b2R607-R609


// TODO add javadoc
private static void radixSort(Sorter sorter, int[] a, int low, int high) {
int[] b;
// LBO: prealloc (high - low) +1 element:
if (sorter == null || (b = sorter.b) == null || b.length < (high - 
low)) {
// System.out.println("alloc b: " + (high - low));
b = new int[high - low];
}

int[] count1, count2, count3, count4;
if (sorter != null) {
sorter.resetRadixBuffers();
count1 = sorter.count1;
count2 = sorter.count2;
count3 = sorter.count3;
count4 = sorter.count4;
} else {
// System.out.println("alloc radix buffers(4x256)");
count1 = new int[256];
count2 = new int[256];
count3 = new int[256];
count4 = new int[256];
}

for (int i = low; i < 

Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Wed, 12 May 2021 12:20:09 GMT, iaroslavski 
 wrote:

>> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 47:
>> 
>>> 45:  * @author Doug Lea
>>> 46:  *
>>> 47:  * @version 2020.06.14
>> 
>> Vladimir, I would update to 2021.05.06 (+your hash)
>
> Laurent, the date in this class is not the date of our last commit,
> this date is the date when I have final idea regarding to Radix sort,
> therefore, I prefer to keep 2020.06.14

as you want, but you should maybe indicate which version corresponds to your 
master code too.

It would help tracking changes between forks (iarosalvskiy/sorting master)

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread iaroslavski
On Sat, 8 May 2021 20:54:48 GMT, iaroslavski 
 wrote:

> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

Still waiting OCA approval

Yes, I ping again, will see what happens

  
>Суббота, 24 июля 2021, 14:47 +03:00 от Laurent Bourgès ***@***.***>:
> 
> 
>Still waiting for individual OCA approval
>—
>You are receiving this because you were mentioned.
>Reply to this email directly,  view it on GitHub , or  unsubscribe .

Still waiting OCA approval

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread iaroslavski
On Wed, 12 May 2021 11:36:09 GMT, Laurent Bourgès  wrote:

>> Sorting:
>> 
>> - adopt radix sort for sequential and parallel sorts on 
>> int/long/float/double arrays (almost random and length > 6K)
>> - fix tryMergeRuns() to better handle case when the last run is a single 
>> element
>> - minor javadoc and comment changes
>> 
>> Testing:
>> - add new data inputs in tests for sorting
>> - add min/max/infinity values to float/double testing
>> - add tests for radix sort
>
> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 47:
> 
>> 45:  * @author Doug Lea
>> 46:  *
>> 47:  * @version 2020.06.14
> 
> Vladimir, I would update to 2021.05.06 (+your hash)

Laurent, the date in this class is not the date of our last commit,
this date is the date when I have final idea regarding to Radix sort,
therefore, I prefer to keep 2020.06.14

> src/java.base/share/classes/java/util/DualPivotQuicksort.java line 288:
> 
>> 286: /*
>> 287:  * Invoke radix sort on large array.
>> 288:  */
> 
> I prefer testing (sorter == null) first as it is always true for sequential 
> sort and avoid testing bits > ... in this case

It makes sense, I will update.

-

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


Re: RFR: JDK-8266431: Dual-Pivot Quicksort improvements (Radix sort)

2021-09-13 Thread Laurent Bourgès
On Sat, 8 May 2021 20:54:48 GMT, iaroslavski 
 wrote:

> Sorting:
> 
> - adopt radix sort for sequential and parallel sorts on int/long/float/double 
> arrays (almost random and length > 6K)
> - fix tryMergeRuns() to better handle case when the last run is a single 
> element
> - minor javadoc and comment changes
> 
> Testing:
> - add new data inputs in tests for sorting
> - add min/max/infinity values to float/double testing
> - add tests for radix sort

Congratulation,
what an amazing job !

DPQS is now 50% faster in average but 2.5 times faster (rms) my favorite !!

Finally OOME is now handled to let sort work under low-mem conditions !

I will work on more benchmarks for long/float/double types.

Laurent

Still waiting for individual OCA approval

src/java.base/share/classes/java/util/DualPivotQuicksort.java line 47:

> 45:  * @author Doug Lea
> 46:  *
> 47:  * @version 2020.06.14

Vladimir, I would update to 2021.05.06 (+your hash)

src/java.base/share/classes/java/util/DualPivotQuicksort.java line 288:

> 286: /*
> 287:  * Invoke radix sort on large array.
> 288:  */

I prefer testing (sorter == null) first as it is always true for sequential 
sort and avoid testing bits > ... in this case

-

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