Tuesday 1 March 2016

All Armstrong numbers calculator

Briefly, an Armstrong number  "is a number that is the sum of its own digits each raised to the power of the number of digits". For example `8208` is an Armstrong number because 8208 = 8^4 + 2^4 + 0^4 + 8^4. We will say that `8208` is a level-4 A-number and call the power sum of its digits, an aSum. Single digit numbers are obviously (level-1) Armstrong numbers , all the A-numbers up to level 4 are:
    1 2 3 4 5 6 7 8 9 
    153 370 371 407 
    1634 8208 9474
There is a finite number of A-numbers, this is because the magnitude of a number grows quicker then it's aSum so that after certain point, the aSum falls behind. The largest A-number is a level-39ner.
This code calculates all A-numbers up to level-39 with the following timings *:
  
  Level-15 0  sec.   41 numbers
  Level-18 2  sec.   46 numbers
  Level-20 6  sec.   51 numbers
  Level-21 11 sec.   53 numbers
  Level-22 15 sec    53 numbers
  Level-23 21 sec.   58 numbers
  Level-25 46 sec    66 numbers
  Level-39 3518 sec. (58 min) 88 numbers

* i7-4790K CPU @ 4.00GHz

Thursday 18 February 2016

Synchronized vs ReentrantLock

Java Concurrency in Practice (2006) has a section titled "Choosing Between Synchronized and ReentrantLock". As far a performance in concerned we have "The performance of ReentrantLock appears to dominate that of intrinsic locking, winning slightly on Java 6 and dramatically on Java 5.0" as well as "Future performance improvements are likely to favor synchronized over ReentrantLock".

Here is a quick throughput benchmark comparing the two on the current Java 8

The setup
Java version:
  > java -version                                                 
  java version "1.8.0_71"                                         
  Java(TM) SE Runtime Environment (build 1.8.0_71-b15)            
  Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode) 
wmic cpu output (partial):
Name                                      NumberOfCores
Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz  4              
In the JMH benchmark attached bellow, a shared counter is incremented by multiple threads. Before incrementing, a thread acquires a lock using either synchronized or a ReentrantLock. It is executed with N = [1..4]:
> java -jar target\benchmarks.jar concurrent -t N -wi 10 -i 20 -rf csv -tu ms -si true  
Here is the complete source (Gist link):
package concurrent;

/**
 * java -jar target\benchmarks.jar concurrent -t N -wi 10 -i 20 -rf csv -tu ms -si true
 */

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@State(Scope.Benchmark)
public class ReentrantLockVsSynchronized {

    @Param({"ReentrantLock", "Synchronized"})
    private String lockMode;

    @State(Scope.Benchmark)
    public static class Counter {
        private static long value;
    }

    @State(Scope.Benchmark)
    public static class JvmLock {
        private static Object lock = new Object();
    }

    @State(Scope.Benchmark)
    public static class RLock {
        private static Lock lock = new ReentrantLock();
    }

    @Benchmark
    public void measure(JvmLock jvmLock, RLock rLock, Counter counter) {
        switch (lockMode) {
            case "Synchronized":
                doSynchronized(jvmLock, counter);
            case "ReentrantLock":
                doReentrantLock(rLock, counter);
        }
    }

    public void doReentrantLock(RLock rLock, Counter counter) {
        rLock.lock.lock();
        try {
            Counter.value++;
        } finally {
            rLock.lock.unlock();
        }
    }

    public void doSynchronized(JvmLock jvmLock, Counter counter) {
        synchronized (jvmLock.lock) {
            Counter.value++;
        }
    }
}


The results
In these tests, the throughput of the ReentrantLock is two to three times higher than that of synchronized. There is also a funny dip when N = 2, this was observed before here .

Friday 22 January 2016

MongoDb - inserting documents throughput

Code comparing various approaches to inserting documents into MongoDB. The sources along with a more detailed description are on GitHub. Here is little chart showing the throughput of each approach.


More details in README.md