jdk icon indicating copy to clipboard operation
jdk copied to clipboard

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

Open iaroslavski opened this issue 4 years ago • 52 comments
trafficstars

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

Progress

  • [ ] Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • [x] Change must not contain extraneous whitespace
  • [x] Commit message must refer to an issue

Error

 ⚠️ OCA signatory status must be verified

Issue

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

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/3938/head:pull/3938
$ git checkout pull/3938

Update a local copy of the PR:
$ git checkout pull/3938
$ git pull https://git.openjdk.org/jdk pull/3938/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 3938

View PR using the GUI difftool:
$ git pr show -t 3938

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/3938.diff

iaroslavski avatar May 08 '21 20:05 iaroslavski

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

bourgesl avatar May 09 '21 20:05 bourgesl

Hi @iaroslavski, welcome to this OpenJDK project and thanks for contributing!

We do not recognize you as Contributor and need to ensure you have signed the Oracle Contributor Agreement (OCA). If you have not signed the OCA, please follow the instructions. Please fill in your GitHub username in the "Username" field of the application. Once you have signed the OCA, please let us know by writing /signed in a comment in this pull request.

If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please use "Add GitHub user iaroslavski" as summary for the issue.

If you are contributing this work on behalf of your employer and your employer has signed the OCA, please let us know by writing /covered in a comment in this pull request.

bridgekeeper[bot] avatar May 10 '21 13:05 bridgekeeper[bot]

@iaroslavski The following label will be automatically applied to this pull request:

  • core-libs

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

openjdk[bot] avatar May 10 '21 13:05 openjdk[bot]

/signed

iaroslavski avatar May 10 '21 13:05 iaroslavski

Thank you! Please allow for up to two weeks to process your OCA, although it is usually done within one to two business days. Also, please note that pull requests that are pending an OCA check will not usually be evaluated, so your patience is appreciated!

bridgekeeper[bot] avatar May 10 '21 13:05 bridgekeeper[bot]

@iaroslavski This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

bridgekeeper[bot] avatar Jun 26 '21 12:06 bridgekeeper[bot]

Still waiting OCA approval

iaroslavski avatar Jun 26 '21 20:06 iaroslavski

Still waiting for individual OCA approval

bourgesl avatar Jul 24 '21 11:07 bourgesl

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 .

iaroslavski avatar Jul 26 '21 15:07 iaroslavski

@iaroslavski This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

bridgekeeper[bot] avatar Aug 23 '21 17:08 bridgekeeper[bot]

Still waiting OCA approval

iaroslavski avatar Aug 23 '21 18:08 iaroslavski

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.

iaroslavski avatar Oct 07 '21 20:10 iaroslavski

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

bourgesl avatar Oct 08 '21 07:10 bourgesl

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

bourgesl avatar Oct 08 '21 07:10 bourgesl

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?

iaroslavski avatar Nov 15 '21 20:11 iaroslavski

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

bourgesl avatar Nov 15 '21 21:11 bourgesl

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

bourgesl avatar Nov 18 '21 07:11 bourgesl

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.

iaroslavski avatar Nov 18 '21 14:11 iaroslavski

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

bourgesl avatar Nov 29 '21 07:11 bourgesl

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 🥳

bourgesl avatar Dec 12 '21 18:12 bourgesl

@iaroslavski This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

bridgekeeper[bot] avatar Jan 09 '22 22:01 bridgekeeper[bot]

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

bourgesl avatar Jan 12 '22 08:01 bourgesl

Please review optimized sorting code.

iaroslavski avatar Jan 12 '22 18:01 iaroslavski

@iaroslavski This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

bridgekeeper[bot] avatar Feb 09 '22 20:02 bridgekeeper[bot]

New update is coming

iaroslavski avatar Feb 25 '22 21:02 iaroslavski

@iaroslavski This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

bridgekeeper[bot] avatar Apr 11 '22 23:04 bridgekeeper[bot]

waiting testing result from Laurent

iaroslavski avatar Apr 25 '22 20:04 iaroslavski

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.

bourgesl avatar May 06 '22 13:05 bourgesl

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.

tarsa avatar May 13 '22 17:05 tarsa