// Copyright 2006 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.services;

import org.apache.tapestry5.ioc.internal.util.ConcurrentBarrier;

import static java.lang.String.format;
import static java.lang.System.out;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Tests single-thread synchronization overhead using different techniques. Note that we're fudging things a bit by
 * getting a read lock for a write operation .... it's just that I'm more concerned about read locks (which will be very
 * common) than about write locks (very rare). Another concern is that hotspot is going to mess up our synchronization
 * when it see we're not really doing anything multi-threaded.
 * <p/>
 * The results show that using the {@link org.apache.tapestry5.internal.annotations.Concurrent} aspect (which used a
 * {@link java.util.concurrent.locks.ReentrantReadWriteLock} under the covers) is about 4x as expensive as just using
 * the synchronized keyword. There are some anomolous results ... for example, ReadWriteLockRunner is consistently
 * slower than ReadWriteLockAspectRunner (one would expect it to be the other way around ... must be something about how
 * AspectJ weaves the code ... and it's use of static methods in many cases).
 * <p/>
 * Well, the Concurrent aspect is gone, replaced with the {@link ConcurrentBarrier} utility.
 */
public class SyncCostBench
{
    /**
     * Calculates a fibunacci series.
     */
    static class Worker implements Runnable
    {
        private long[] series = { 1, 1 };

        public void run()
        {
            long value = series[0] + series[1];

            // Now shift the values down to prepare for the next iteration.

            series[0] = series[1];
            series[1] = value;
        }
    }

    static class SimpleRunner implements Runnable
    {
        private final Runnable delegate;

        public SimpleRunner(Runnable delegate)
        {
            this.delegate = delegate;
        }

        public void run()
        {
            delegate.run();
        }
    }

    static class SynchronizedRunner implements Runnable
    {
        private final Runnable delegate;

        public SynchronizedRunner(Runnable delegate)
        {
            this.delegate = delegate;
        }

        public synchronized void run()
        {
            delegate.run();
        }
    }

    static class ReadWriteLockAspectRunner implements Runnable
    {
        private final ConcurrentBarrier barrier = new ConcurrentBarrier();

        private final Runnable delegate;

        public ReadWriteLockAspectRunner(Runnable delegate)
        {
            this.delegate = delegate;
        }

        public void run()
        {
            barrier.withRead(delegate);
        }
    }

    static class ReadWriteLockRunner implements Runnable
    {
        private final Runnable delegate;

        private final ReadWriteLock lock = new ReentrantReadWriteLock();

        public ReadWriteLockRunner(Runnable delegate)
        {
            this.delegate = delegate;
        }

        public void run()
        {

            try
            {
                lock.readLock().lock();

                delegate.run();
            }
            finally
            {
                lock.readLock().unlock();
            }

        }
    }

    private static final int WARMUP_BLOCK_SIZE = 1000;

    private static final int BLOCK_SIZE = 5 * 1000 * 1000;

    static class BlockRunner implements Runnable
    {
        private final Runnable delegate;

        private final int blockSize;

        public BlockRunner(int blockSize, Runnable delegate)
        {
            this.blockSize = blockSize;
            this.delegate = delegate;
        }

        public void run()
        {
            for (int i = 0; i < blockSize; i++)
                delegate.run();
        }
    }

    public static void main(String[] args) throws Exception
    {
        Runnable simple = new SimpleRunner(new Worker());
        Runnable synched = new SynchronizedRunner(new Worker());
        Runnable rw = new ReadWriteLockRunner(new Worker());
        Runnable aspect = new ReadWriteLockAspectRunner(new Worker());

        out.println(format("%40s %9s %9s %9s", ",simple", ",synched", ",rw", ",aspect"));

        stage("warmup");

        go(WARMUP_BLOCK_SIZE, simple);
        go(WARMUP_BLOCK_SIZE, synched);
        go(WARMUP_BLOCK_SIZE, rw);
        go(WARMUP_BLOCK_SIZE, aspect);

        out.println();

        for (int i = 0; i < 10; i++)
        {
            Thread.sleep(5 * 1000);
            System.gc();

            stage(format("stage #%d", i + 1));
            go(BLOCK_SIZE, simple);
            go(BLOCK_SIZE, synched);
            go(BLOCK_SIZE, rw);
            go(BLOCK_SIZE, aspect);

            out.println();
        }
    }

    private static void stage(String name)
    {
        out.print(format("%30s", name));
    }

    private static void go(int blockSize, Runnable runner) throws InterruptedException
    {

        Thread t = new Thread(new BlockRunner(blockSize, runner));

        long tick = System.nanoTime();

        t.start();

        // Now wait for it to finish.

        t.join();

        long tock = System.nanoTime();

        out.print(format(",%9d", tock - tick));
    }
}
