// (c) 2007 Abdulla Abdurakhmanov

// MyParentClass file
abstract class MyParentClass
{    
    private    String pField = "Hello ";
    private    String cField;
    private    long pField2 = 0xFF;
    public abstract String vMethod(String val);

    public final String sMethod(String val)
    {
        cField = pField + val;
        return cField;
    }

    public final long lMethod (long v)
    {
        return v*10;
    }

    public abstract long vlMethod(long val);

    public final void l2Method (long r)
    {
        pField2 = r;
    }
}

// MyClass file
import java.util.Calendar;
import java.net.*;
import java.nio.channels.*;
import java.nio.*;

class MyClass extends MyParentClass
{   
    public String vMethod(String val)
    {
        return this.sMethod(val);
    }

    public long vlMethod (long v)
    {
        return v*10;
    }


    private static final int OBJ_COUNT = 1000000;

    public static void main(String args[]) {
        long startTime, endTime;
        System.out.println("Creating "+OBJ_COUNT+" objects");
        startTime = Calendar.getInstance().getTimeInMillis();
        MyParentClass[] objs = new MyParentClass [OBJ_COUNT];
        for(int i=0;i<OBJ_COUNT;i++)
        {
            objs[i] = new MyClass();
        }
        endTime = Calendar.getInstance().getTimeInMillis();
        System.out.println("Elapsed time for "+OBJ_COUNT+" objects: " + ((endTime-startTime)/1000.0));

        System.out.println("Calling a usual non-virtual method on "+OBJ_COUNT+" objects");
        startTime = Calendar.getInstance().getTimeInMillis();
        for(int i=0;i<OBJ_COUNT;i++)
        {
            for(int j=0;j<10;j++)
                objs[i].sMethod(objs[i].sMethod("Vasya"));
        }
        endTime = Calendar.getInstance().getTimeInMillis();
        System.out.println("Elapsed time for "+OBJ_COUNT+" objects: " + ((endTime-startTime)/1000.0));

        System.out.println("Calling a virtual method on "+OBJ_COUNT+" objects");
        startTime = Calendar.getInstance().getTimeInMillis();
        for(int i=0;i<OBJ_COUNT;i++)
        {
            for(int j=0;j<10;j++)
                objs[i].vMethod(objs[i].vMethod("Vasya"));
        }
        endTime = Calendar.getInstance().getTimeInMillis();
        System.out.println("Elapsed time for "+OBJ_COUNT+" objects: " + ((endTime-startTime)/1000.0));


        System.out.println("Calling a usual non-virtual method for long on "+OBJ_COUNT+" objects");
        startTime = Calendar.getInstance().getTimeInMillis();
        for(int i=0;i<OBJ_COUNT;i++)
        {
            for(int j=0;j<500;j++)
            {
                objs[i].l2Method( objs[i].lMethod(j) );
            }
        }
        endTime = Calendar.getInstance().getTimeInMillis();
        System.out.println("Elapsed time for "+OBJ_COUNT+" objects: " + ((endTime-startTime)/1000.0));

        System.out.println("Calling virtual method for long on "+OBJ_COUNT+" objects");
        startTime = Calendar.getInstance().getTimeInMillis();
        for(int i=0;i<OBJ_COUNT;i++)
        {
            for(int j=0;j<500;j++)
            {
                objs[i].l2Method( objs[i].vlMethod(j) );
            }
        }
        endTime = Calendar.getInstance().getTimeInMillis();
        System.out.println("Elapsed time for "+OBJ_COUNT+" objects: " + ((endTime-startTime)/1000.0));

        try {
            networkTest(10000, 256);
            networkTest(100000, 256);
            networkTest(1000000, 256);
            networkTest(50000, 512);

        }
        catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void networkTest(int count, int pktSize) throws Exception {
            System.out.println ( "Network perf test. Iter count: "+count+". Packet size: "+pktSize );
            SocketChannel channel = SocketChannel.open();
            channel.configureBlocking(true);
            channel.connect(new InetSocketAddress("localhost", 5555));
            ByteBuffer buffer = ByteBuffer.allocate(pktSize);
            buffer.put( new byte[pktSize] );
            buffer.position(0);
            int totalBytesSnt = 0;
            int totalBytesRcv = 0;
            long startTime = Calendar.getInstance().getTimeInMillis();
            for(int i=0;i<count;i++)
            {
                long bt = channel.write(buffer);
                if(bt>0)
                    totalBytesSnt+=bt;
                else
                    System.err.println("Write error!\n");
                buffer.clear();
                bt = channel.read(buffer);
                buffer.position(0);
                if(bt>0)
                    totalBytesRcv+=bt;
                else
                    System.err.println("Read error!\n");
            }
            long endTime = Calendar.getInstance().getTimeInMillis();
            System.out.println ( "Elapsed time for network perf is : " + ((endTime - startTime)/1000.0));
            channel.close();
    }
}