package com.singularsys.jepexamples.diagnostics;

import com.singularsys.jep.ComponentSet;
import com.singularsys.jep.Evaluator;
import com.singularsys.jep.FunctionTable;
import com.singularsys.jep.Jep;
import com.singularsys.jep.NodeFactory;
import com.singularsys.jep.NumberFactory;
import com.singularsys.jep.OperatorTable;
import com.singularsys.jep.Parser;
import com.singularsys.jep.PrintVisitor;
import com.singularsys.jep.VariableFactory;
import com.singularsys.jep.VariableTable;
import com.singularsys.jep.configurableparser.StandardConfigurableParser;
import com.singularsys.jep.misc.LightWeightComponentSet;
import com.singularsys.jep.misc.NullParser;
import com.singularsys.jep.parser.StandardParser;
import com.singularsys.jep.standard.DoubleNumberFactory;
import com.singularsys.jep.standard.StandardEvaluator;
import com.singularsys.jep.standard.StandardFunctionTable;
import com.singularsys.jep.standard.StandardOperatorTable;
import com.singularsys.jep.standard.StandardVariableTable;

/**
 * Used to examine the memory used to initialise a Jep instance.
 * Typical values are
 * <ul>
 * <li>With a StandardParser: 56661
 * <li>With a ConfigurableParser: 14033
 * <li>With a NullParser: 5265
 * </ul>
 */
public class ExamineSizes {
    static final int N=100;
    enum ParserType { STANDARD, CONFIG, NULL }
    static ParserType pt = ParserType.CONFIG;
    void run() {
        printMem("Init "+N+" instances ");

        NumberFactory nuf[]=new NumberFactory[N];
        VariableFactory vf[]=new VariableFactory[N];
        NodeFactory nf[] = new NodeFactory[N];
        FunctionTable[] ft = new FunctionTable[N];
        VariableTable vt[] = new VariableTable[N];
        OperatorTable ot[] = new OperatorTable[N];
        Parser p[] = new Parser[N];
        Evaluator e[] = new Evaluator[N];
        PrintVisitor pv[] = new PrintVisitor[N];
        Jep j[] = new Jep[N];
        Jep j2[] = new Jep[N];
        ComponentSet cs = new ComponentSet();

        long initMem = printMem("Init arrays");

        for(int i=0;i<N;++i)
            nuf[i] = new DoubleNumberFactory();
        printMem("DoubleNumberFactory");

        for(int i=0;i<N;++i)
            vf[i] = new VariableFactory();
        printMem("VariableFactory");

        for(int i=0;i<N;++i)
            nf[i] = new NodeFactory();
        printMem("NodeFactory");

        for(int i=0;i<N;++i)
            ft[i] = new StandardFunctionTable();
        printMem("StandardFunctionTable");

        for(int i=0;i<N;++i)
            vt[i] = new StandardVariableTable(vf[i]);
        printMem("StandardVariableTable");

        for(int i=0;i<N;++i)
            ot[i] = new StandardOperatorTable();
        printMem("StandardOperatorTable");

        switch(pt) {
        case STANDARD:
            for(int i=0;i<N;++i)
                p[i] = new StandardParser();
            printMem("StandardParser");
            break;
        case CONFIG:
            for(int i=0;i<N;++i)
                p[i] = new StandardConfigurableParser();
            printMem("ConfigurableParser");
            break;
        case NULL:
            for(int i=0;i<N;++i)
                p[i] = new NullParser();
            printMem("NullParser");
            break;
        }

        for(int i=0;i<N;++i)
            e[i] = new StandardEvaluator();
        printMem("StandardEvaluator");

        for(int i=0;i<N;++i)
            pv[i] = new PrintVisitor();
        printMem("PrintVisitor");

        for(int i=0;i<N;++i) {
            cs.setNumberFactory(nuf[i]);
            cs.setVariableFactory(vf[i]);
            cs.setNodeFactory(nf[i]);
            cs.setVariableTable(vt[i]);
            cs.setFunctionTable(ft[i]);
            cs.setOperatorTable(ot[i]);
            cs.setEvaluator(e[i]);
            cs.setParser(p[i]);
            cs.setPrintVisitor(pv[i]);
            j[i] = new Jep(cs);
        }
        long finalMem = printMem("Jep");
        System.out.println("Average total memory per instance " + ((finalMem-initMem)/N));

        for(int i=0;i<N;++i) {
            LightWeightComponentSet lwcs = new LightWeightComponentSet(j[i]);
            j2[i] = new Jep(lwcs);
        }
        long lwMem = printMem("LightWeightJep");
        System.out.println("Average total memory per light weight instance " + ((lwMem-finalMem)/N));

    }

    long curMem=0;
    long printMem(String s) {
        Runtime rt = Runtime.getRuntime();
        rt.gc();
        long newMem = rt.totalMemory()-rt.freeMemory();
        //		System.out.println(
        //			"Total "+rt.totalMemory()+" free "+rt.freeMemory()+" max "+rt.maxMemory()+" diff "+newMem);
        System.out.printf("%-25s%8d%n",s, (newMem-curMem));
        //    	System.out.println(s+"\t"+ (newMem-curMem));
        curMem = newMem;
        return newMem;
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        ExamineSizes ex = new ExamineSizes();
        ex.run();
    }

}
