Current implementations of TimSort and ComparableTimSort both have fast path 
for the case when the size of array = 1 i.e. such array is considered to be 
sorted.

My proposal is to add similar fast path for the case when the size of the array 
= 2. In this case it's enough to check if the first item is greater than the 
second one and swap them.
Otherwise array is considered to be sorted.

I have attached the patch to this mail.

As for performance I have measured array sort with size = 2 using JDK-provided 
and patched implementations of TimSort and ComparableTimSort both execution 
time and throughput in two environments:

1)  Intel Core i5-4690 3,50 GHz
2)  Intel Core i3-3220 3,30 GHz

On both environments I have Java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

Measurement results are

1)

Benchmark                                                        Mode  Cnt   
Score     Error   Units

SortingBenchmark.measureConventionalSort  avgt    500  17,692 ± 0,040  ns/op
SortingBenchmark.measureEnhancedSort       avgt    500  13,206 ± 0,025  ns/op

SortingBenchmark.measureConventionalSort  thrpt    500  56,962 ± 0,051  ops/us
SortingBenchmark.measureEnhancedSort       thrpt    500  72,278 ± 0,724  ops/us

2)

Benchmark                                                        Mode  Cnt   
Score    Error  Units

SortingBenchmark.measureConventionalSort  avgt    500  26,173 ± 0,251  ns/op
SortingBenchmark.measureEnhancedSort       avgt    500  18,191 ± 0,106  ns/op

SortingBenchmark.measureConventionalSort  thrpt    500  36,987 ± 0,437  ops/us
SortingBenchmark.measureEnhancedSort       thrpt    500  53,499 ± 0,456  ops/us

So in both cases patched implementation demonstrates better throughput and 
execution time for the case array.lenght = 2.

Regards,
Sergei Tsypanov
diff --git a/src/java.base/share/classes/java/util/ComparableTimSort.java b/src/java.base/share/classes/java/util/ComparableTimSort.java
--- a/src/java.base/share/classes/java/util/ComparableTimSort.java
+++ b/src/java.base/share/classes/java/util/ComparableTimSort.java
@@ -183,6 +183,17 @@
         if (nRemaining < 2)
             return;  // Arrays of size 0 and 1 are always sorted
 
+        //when array's size is 2 we just need to swap items
+        //if the first item is greater than the second one
+        if (nRemaining == 2) {
+            Comparable o0 = (Comparable) a[0];
+            Object o1 = a[1];
+
+            if (o0.compareTo(o1) > 0) {
+                a[0] = o1;
+                a[1] = o0;
+            }
+            return;
+        }
+
         // If array is small, do a "mini-TimSort" with no merges
         if (nRemaining < MIN_MERGE) {
             int initRunLen = countRunAndMakeAscending(a, lo, hi);
diff --git a/src/java.base/share/classes/java/util/TimSort.java b/src/java.base/share/classes/java/util/TimSort.java
--- a/src/java.base/share/classes/java/util/TimSort.java
+++ b/src/java.base/share/classes/java/util/TimSort.java
@@ -215,6 +215,17 @@
         if (nRemaining < 2)
             return;  // Arrays of size 0 and 1 are always sorted
 
+        //when array's size is 2 we just need to swap items
+        //if the first item is greater than the second one
+        if (nRemaining == 2) {
+            T o0 = a[0];
+            T o1 = a[1];
+            if (c.compare(o0, o1) > 0) {
+                a[0] = o1;
+                a[1] = o0;
+            }
+            return;
+        }
+
         // If array is small, do a "mini-TimSort" with no merges
         if (nRemaining < MIN_MERGE) {
             int initRunLen = countRunAndMakeAscending(a, lo, hi, c);

Reply via email to