RFR: 8231640: (prop) Canonical property storage

Jaikiran Pai jai.forums2013 at gmail.com
Wed Sep 8 09:37:15 UTC 2021


Hello Andrey,

On 07/09/21 7:50 pm, Andrey Turbanov wrote:
> On Sun, 5 Sep 2021 12:38:20 GMT, Jaikiran Pai <jai.forums2013 at gmail.com> wrote:
>
>> Do you mean that converting the keySet() of an
>> existing Map into an array and then sorting that array and then using
>> that sorted array to iterate and using these keys to do an additional
>> lookup for value against the original Map would be more efficient in
>> this case?
> You can convert entrySet() to array. Not a keySet. In this case there is no need to lookup for values.

I experimented this in a JMH test and the results matched your 
expectations. So, I've updated the PR to use array sorting instead of 
creating a TreeMap. For reference, here's the JMH benchmark code and the 
results:

package org.myapp;

import org.openjdk.jmh.annotations.Benchmark;
import java.util.*;
import java.util.concurrent.*;
import org.openjdk.jmh.annotations.*;

public class MyBenchmark {

     @State(Scope.Thread)
     public static class TestData {
         static final Map<Object, Object> tenItems;
         static final Map<Object, Object> hundredItems;
         static final Map<Object, Object> thousandItems;

         static {
             tenItems = new ConcurrentHashMap<>(8);
             hundredItems = new ConcurrentHashMap<>(8);
             thousandItems = new ConcurrentHashMap<>(8);
             for (int i = 0; i < 1000; i++) {
                 thousandItems.put("foo" + i, "bar");
                 if (i < 100) {
                     hundredItems.put("hello" + i, "world");
                 }
                 if (i < 10) {
                     tenItems.put("good" + i, "morning");
                 }
             }
             System.out.println("Test data created with " + 
tenItems.size() + ", "
                 + hundredItems.size() + " and " + thousandItems.size() 
+ " Map keys");
         }
     }

     @Benchmark
     @BenchmarkMode(Mode.AverageTime)
     @OutputTimeUnit(TimeUnit.MICROSECONDS)
     public void testTenItemsTreeMapSorting(TestData testData) {
         final Map<Object, Object> sorted = new TreeMap(testData.tenItems);
     }

     @Benchmark
     @BenchmarkMode(Mode.AverageTime)
     @OutputTimeUnit(TimeUnit.MICROSECONDS)
     public void testHundredItemsTreeMapSorting(TestData testData) {
         final Map<Object, Object> sorted = new 
TreeMap(testData.hundredItems);
     }

     @Benchmark
     @BenchmarkMode(Mode.AverageTime)
     @OutputTimeUnit(TimeUnit.MICROSECONDS)
     public void testThousandItemsTreeMapSorting(TestData testData) {
         final Map<Object, Object> sorted = new 
TreeMap(testData.thousandItems);
     }

     @Benchmark
     @BenchmarkMode(Mode.AverageTime)
     @OutputTimeUnit(TimeUnit.MICROSECONDS)
     public void testTenItemsArraySorting(TestData testData) {
         var entries = testData.tenItems.entrySet().toArray(new 
Map.Entry<?, ?>[0]);
         Arrays.sort(entries, new Comparator<Map.Entry<?, ?>>() {
             @Override
             public int compare(Map.Entry<?, ?> o1, Map.Entry<?, ?> o2) {
                 return ((String) o1.getKey()).compareTo((String) 
o2.getKey());
             }
         });
     }

     @Benchmark
     @BenchmarkMode(Mode.AverageTime)
     @OutputTimeUnit(TimeUnit.MICROSECONDS)
     public void testHundredItemsArraySorting(TestData testData) {
         var entries = testData.hundredItems.entrySet().toArray(new 
Map.Entry<?, ?>[0]);
         Arrays.sort(entries, new Comparator<Map.Entry<?, ?>>() {
             @Override
             public int compare(Map.Entry<?, ?> o1, Map.Entry<?, ?> o2) {
                 return ((String) o1.getKey()).compareTo((String) 
o2.getKey());
             }
         });
     }

     @Benchmark
     @BenchmarkMode(Mode.AverageTime)
     @OutputTimeUnit(TimeUnit.MICROSECONDS)
     public void testThousandItemsArraySorting(TestData testData) {
         var entries = testData.thousandItems.entrySet().toArray(new 
Map.Entry<?, ?>[0]);
         Arrays.sort(entries, new Comparator<Map.Entry<?, ?>>() {
             @Override
             public int compare(Map.Entry<?, ?> o1, Map.Entry<?, ?> o2) {
                 return ((String) o1.getKey()).compareTo((String) 
o2.getKey());
             }
         });
     }

}

Results:

Benchmark                                    Mode  Cnt    Score Error  Units
MyBenchmark.testHundredItemsArraySorting     avgt   25    8.330 ± 0.147  
us/op
MyBenchmark.testHundredItemsTreeMapSorting   avgt   25    8.637 ± 0.333  
us/op
MyBenchmark.testTenItemsArraySorting         avgt   25    0.261 ± 0.006  
us/op
MyBenchmark.testTenItemsTreeMapSorting       avgt   25    0.422 ± 0.007  
us/op
MyBenchmark.testThousandItemsArraySorting    avgt   25  151.566 ± 1.660  
us/op
MyBenchmark.testThousandItemsTreeMapSorting  avgt   25  163.767 ± 1.911  
us/op


-Jaikiran




More information about the core-libs-dev mailing list