/*
 * Copyright (c) 2009-2010 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package jme3test.app;

import com.jme3.math.Vector3f;
import com.jme3.util.TempVars;

public class TestTempVars {

    private static final int ITERATIONS = 10000000;
    private static final int NANOS_TO_MS = 1000000;
    
    private static final Vector3f sumCompute = new Vector3f();
    
    public static void main(String[] args) {
        long milliseconds, nanos;
        
        for (int i = 0; i < 4; i++){
            System.gc();
        }
        
//        sumCompute.set(0, 0, 0);
//        long nanos = System.nanoTime();
//        for (int i = 0; i < ITERATIONS; i++) {
//            recursiveMethod(0);
//        }
//        long milliseconds = (System.nanoTime() - nanos) / NANOS_TO_MS;
//        System.out.println("100 million TempVars calls with 5 recursions: " + milliseconds + " ms");
//        System.out.println(sumCompute);
        
        sumCompute.set(0, 0, 0);
        nanos = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            methodThatUsesTempVars();
        }
        milliseconds = (System.nanoTime() - nanos) / NANOS_TO_MS;
        System.out.println("100 million TempVars calls: " + milliseconds + " ms");
        System.out.println(sumCompute);

        sumCompute.set(0, 0, 0);
        nanos = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            methodThatUsesAllocation();
        }
        milliseconds = (System.nanoTime() - nanos) / NANOS_TO_MS;
        System.out.println("100 million allocation calls: " + milliseconds + " ms");
        System.out.println(sumCompute);
        
        nanos = System.nanoTime();
        for (int i = 0; i < 10; i++){
            System.gc();
        }
        milliseconds = (System.nanoTime() - nanos) / NANOS_TO_MS;
        System.out.println("cleanup time after allocation calls: " + milliseconds + " ms");
    }

    public static void methodThatUsesAllocation(){
        Vector3f vector = new Vector3f();
        vector.set(0.1f, 0.2f, 0.3f);
        sumCompute.addLocal(vector);
    }
    
    public static void recursiveMethod(int recurse) {
        TempVars vars = TempVars.get();
        {
            vars.vect1.set(0.1f, 0.2f, 0.3f);

            if (recurse < 4) {
                recursiveMethod(recurse + 1);
            }

            sumCompute.addLocal(vars.vect1);
        }
        vars.release();
    }

    public static void methodThatUsesTempVars() {
        TempVars vars = TempVars.get();
        {
            vars.vect1.set(0.1f, 0.2f, 0.3f);
            sumCompute.addLocal(vars.vect1);
        }
        vars.release();
    }
}
