Tuesday, August 9, 2011

Comparing Collections speeds..!

The speed of different collections tends to depend on their usage pattern however it can be useful to have an idea of their relative performance.

The test:

In this test I compare both single thread and thread safe collections of different sizes.

Adding is from lowest to highest values. Removal is from start and end,
finishing with the middle value. This disadvantages ArrayList and
LinkedList relatively equally.


CollectionSizeAddingIteratingRemoving
ArrayList100,00030.114.567,359
ArrayList10,0008.311.26,323
ArrayList1,0006.49.4585
ArrayList1006.89.592.9
ArrayList109.713.236.6
LinkedList100,00046.441.4139,326
LinkedList10,0009.330.313,413
LinkedList1,0008.727.61,025
LinkedList1007.819.8110
LinkedList1011.230.338.7
HashSet100,00028.611569.5
HashSet10,00025.732458.6
HashSet1,00026.02,52159.2
HashSet10030.024,49064.6
HashSet1051.7244,045131
LinkedHashSet100,00035.910369.2
LinkedHashSet10,00030.310165.0
LinkedHashSet1,00029.210065.8
LinkedHashSet10031.598.860.6
LinkedHashSet1045.411069.8
TreeSet100,000159106187
TreeSet10,00099.677.6111
TreeSet1,00078.557.593.7
TreeSet10054.047.983.7
TreeSet1030.251.049.4
newSetFromMap IdentityHashMap100,00074.1216153
newSetFromMap IdentityHashMap10,00065.5370126
newSetFromMap IdentityHashMap1,00060.41,644115
newSetFromMap IdentityHashMap10021.114,21648.9
newSetFromMap IdentityHashMap1046.7140,162109
newSetFromMap WeakHashMap100,00052.414887.4
newSetFromMap WeakHashMap10,00033.521771.2
newSetFromMap WeakHashMap1,00032.91,08872.2
newSetFromMap WeakHashMap10032.19,71764.3
newSetFromMap WeakHashMap1048.098,76993.0

Thread Safe Collections
synchronized ArrayList100,00022.610198,735
synchronized ArrayList10,00012.110110,084
synchronized ArrayList1,00011.599.51,023
synchronized ArrayList10011.4101144
synchronized ArrayList1014.011154.0
Vector100,00023.929864,333
Vector10,00020.43725,919
Vector1,00019.4372612
Vector10019.3375145
Vector1022.939797.5
synchronized LinkedList100,00037.6100132,660
synchronized LinkedList10,00019.299.613,049
synchronized LinkedList1,00022.299.11,005
synchronized LinkedList10023.7102134
synchronized LinkedList1026.111562.6
synchronized HashSet100,00050.113895.7
synchronized HashSet10,00043.034793.1
synchronized HashSet1,00042.72,55595.3
synchronized HashSet10047.024,60897.4
synchronized HashSet1085.7245,343204
synchronized LinkedHashSet100,00048.610393.1
synchronized LinkedHashSet10,00045.610188.1
synchronized LinkedHashSet1,00048.710694.6
synchronized LinkedHashSet10048.110186.8
synchronized LinkedHashSet1057.811493.4
synchronized TreeSet100,000116105179
synchronized TreeSet10,00074.175.4122
synchronized TreeSet1,00063.553.9103
synchronized TreeSet10050.846.290.4
synchronized TreeSet1029.149.157.6
CopyOnWriteArrayList100,00035,35465.8165,197
CopyOnWriteArrayList10,0002,11597.736,269
CopyOnWriteArrayList1,00021775.11,828
CopyOnWriteArrayList10060.063.4227
CopyOnWriteArrayList1048.271.0103
CopyOnWriteArraySet100,000106,11663.3165,708
CopyOnWriteArraySet10,00028,73691.229,820
CopyOnWriteArraySet1,0001,14375.11,852
CopyOnWriteArraySet10013463.4233
CopyOnWriteArraySet1055.373.0109
newSetFromMap ConcurrentHashMap100,00070.6291149
newSetFromMap ConcurrentHashMap10,00057.2485120
newSetFromMap ConcurrentHashMap1,00053.42,869121
newSetFromMap ConcurrentHashMap10054.724,150140
newSetFromMap ConcurrentHashMap1068.793,921197
newSetFromMap ConcurrentSkipListMap100,00013596.8365
newSetFromMap ConcurrentSkipListMap10,00011395.1285
newSetFromMap ConcurrentSkipListMap1,00097.894.7234
newSetFromMap ConcurrentSkipListMap10083.395.2192
newSetFromMap ConcurrentSkipListMap1064.2112151

THe code that performs the above given test:

/*
 * MailTodoNew - AddIterateRemoveTest.java, Aug 9, 2011 5:23:37 PM
 *
 * Copyright 2011 MindTree Ltd, Inc. All rights reserved.
 * MindTree proprietary/confidential. Use is subject to license terms.
 */
package com.mt.util.testing;

import org.junit.Test;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * The Class AddIterateRemoveTest.
 *
 * @author Karthikeyan V. Reddy
 * @version 1.0
 */
public class AddIterateRemoveTest
{
   
    /** The Constant RUNS_TIME_MS. */
    static final int RUNS_TIME_MS = 10 * 1000;
   
    /** The Constant LARGEST_SIZE. */
    static final int LARGEST_SIZE = 100 * 1000;
   
    /** The Constant INTS. */
    static final int[] INTS = new int[LARGEST_SIZE];
   
    static
    {
        for (int i = 0; i < LARGEST_SIZE; i++)
            INTS[i] = i;
    }
   
    /**
     * Performance test.
     */
    @Test
    public void performanceTest()
    {
        test(new TreeSet<Integer>());
        test(Collections.synchronizedSortedSet(new TreeSet<Integer>()), "synchronized TreeSet");
        test(new ArrayList<Integer>());
        test(new LinkedList<Integer>());
        test(new HashSet<Integer>());
        test(new LinkedHashSet<Integer>());
        test(Collections.newSetFromMap(new IdentityHashMap<Integer, Boolean>()), "newSetFromMap IdentityHashMap");
        test(Collections.newSetFromMap(new WeakHashMap<Integer, Boolean>()), "newSetFromMap WeakHashMap");
       
        test(Collections.synchronizedList(new ArrayList<Integer>()), "synchronized ArrayList");
        test(new Vector<Integer>());
        test(Collections.synchronizedList(new LinkedList<Integer>()), "synchronized LinkedList");
        test(Collections.synchronizedSet(new HashSet<Integer>()), "synchronized HashSet");
        test(Collections.synchronizedSet(new LinkedHashSet<Integer>()), "synchronized LinkedHashSet");
        test(new CopyOnWriteArrayList<Integer>());
        test(new CopyOnWriteArraySet<Integer>());
        test(Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>()), "newSetFromMap ConcurrentHashMap");
        test(Collections.newSetFromMap(new ConcurrentSkipListMap<Integer, Boolean>()),
                "newSetFromMap ConcurrentSkipListMap");
    }
   
    /**
     * Test.
     *
     * @param ints
     *            the ints
     */
    private void test(Collection<Integer> ints)
    {
        test(ints, ints.getClass().getSimpleName());
    }
   
    /**
     * Test.
     *
     * @param ints
     *            the ints
     * @param collectionName
     *            the collection name
     */
    private void test(Collection<Integer> ints, String collectionName)
    {
        for (int size = LARGEST_SIZE; size >= 10; size /= 10)
        {
            long adding = 0;
            long removing = 0;
            long iterating = 0;
           
            int runs = 0;
            long endTime = System.currentTimeMillis() + RUNS_TIME_MS;
            do
            {
                runs++;
                long start = System.nanoTime();
                testAdding(ints, size);
               
                adding += System.nanoTime() - start;
               
                start = System.nanoTime();
                for (int repeat = 0; repeat < 100; repeat++)
                    testIterating(ints);
                iterating += System.nanoTime() - start;
               
                start = System.nanoTime();
                testRemoving(ints, size);
                removing += (System.nanoTime() - start) * 2;
               
                ints.clear();
            } while (endTime > System.currentTimeMillis());
            System.out.println("<tr><td>" + collectionName + "</td><td aligned=\"right\">" + String.format("%,d", size)
                    + "</td><td aligned=\"right\">" + format(10 * adding / runs / size) + "</td><td aligned=\"right\">"
                    + format(iterating / runs / size) + "</td><td aligned=\"right\">"
                    + format(10 * removing / runs / size) + "</td></tr>");
        }
    }
   
    /**
     * Format.
     *
     * @param l
     *            the l
     * @return the string
     */
    private String format(long l)
    {
        return l < 1000 ? "" + (l / 10.0) : l < 10000 ? "" + l / 10 : String.format("%,d", l / 10);
    }
   
    /**
     * Test adding.
     *
     * @param ints
     *            the ints
     * @param size
     *            the size
     */
    private static void testAdding(Collection<Integer> ints, int size)
    {
        // adding
        for (int i = 0; i < size; i++)
            ints.add(INTS[i]);
    }
   
    /**
     * Test iterating.
     *
     * @param ints
     *            the ints
     * @return the long
     */
    private static long testIterating(Collection<Integer> ints)
    {
        // iterating
        long sum = 0;
        for (Integer i : ints)
            sum += i;
        return sum;
    }
   
    /**
     * Test removing.
     *
     * @param ints
     *            the ints
     * @param size
     *            the size
     */
    private void testRemoving(Collection<Integer> ints, int size)
    {
        // forward and reverse
        for (int i = 0; i < size / 2; i++)
        {
            ints.remove(INTS[i]);
            ints.remove(INTS[size - i - 1]);
        }
    }
}


No comments:

Post a Comment