How to graph by hand the growth rate of a program? - java

Below is a simple for loop. I understand using growth rate analysis to look at a program and determine its rate. However, my question is after a program runs and you actually see the speed of which it works, how would you graph the actual growth rate of the program?
long startTime = System.nanoTime();
int sum = 0;
int N = 1000000;
for (int i=0; i<N; i++)
{
sum += Math.sqrt(i);
}
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println("Here is the time it takes "+ duration);

Big O follows a certain trend depending on the complexity of the program.
Types of Big O Explained
Big O explained
I have listed some resources that I think should be useful.
Also if you don't need to draw it by hand, try looking up some Java resources that generate graphs.

Related

Working of size() method of list in java

I have 2 pieces of code and first part is here
int count = myArrayList.size();
for (int a =0; a< count; a++) {
//any calculation
}
Second part of the code is
for (int a =0; a< myArrayList.size(); a++) {
//any calculation
}
in both piece I am iterating over myArrayList (this is ArrayList) size but in first part I am calculating size then iterating it means the method size is being called only once but on the other hand in second part whenever it iterates it calculates the size first then then check for size in less than or not.Isn't it long process ?I have seen in many examples in many places (which calculate size on every iteration).
My questions:
Isn't it long process? (talking about second part)
what is best practice first or second?
which is efficient way to perform iteration?
myArrayList.size() how this size method works or calculates the size?
EDITION:
For testing the same thing I wrote programs and calculated the time the code is
ArrayList<Integer> myArrayList = new ArrayList<>();
for (int a =0; a<1000; a++) {
myArrayList.add(a);
}
long startTime = System.nanoTime();
for (int a =0; a< myArrayList.size(); a++) {
//any calculation
}
long lastTime = System.nanoTime();
long result = lastTime - startTime;
and the result is = 34490 nano seconds
on the other hand
ArrayList<Integer> myArrayList = new ArrayList<>();
for (int a =0; a<1000; a++) {
myArrayList.add(a);
}
long startTIme = System.nanoTime();
int count = myArrayList.size();
for (int a =0; a< count; a++) {
}
long endTime = System.nanoTime();
long result = endTime - startTIme;
and the result is = 11394 nano seconds
here when calling size() method in every iteration taking much time then without calling it every call.Is this the right way to check the time calculation?
No. The call is not a "long running" process, the JVM can make function calls quickly.
Either is acceptable. Prefer the one that's easier to read. Adding a local reference with a meaningful name can make something easier to read.
You might prefer the for-each loop, but for readability1. There is no appreciable efficiency difference in your options (or with the for-each).
The ArrayList implementation keeps an internal count (in the OpenJDK implementation, and probably others, that is size) and manages the internal array that backs the List.
1See also The Developer Insight Series, Part 1: Write Dumb Code

getting execution time using getCurrentThreadUserTime()

I'm trying to measure the execution time of a loop, which is a simple Add Matrices.
here's my code:
//get integers m and n from user before this.
long start,end,time;
int[][] a = new int[m][n];
int[][] b = new int[m][n];
int[][] c= new int[m][n];
start = getUserTime();
for(int i = 0;i < m;i++)
{
for(int j = 0;j < n;j++)
{
c[i][j] = a[i][j]+b[i][j];
}
}
end = getUserTime();
time = end - start;
/** Get user time in nanoseconds. */
public long getUserTime() {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
bean.getCurrentThreadUserTime() : 0L;
}
the problem is, sometimes it returns 0, for example when I input 1000 as m and n. which means I have two 1000x1000 matrices being added. sometimes it returns 0 and sometimes 15ms (both keep getting repeated).
I don't know whether to believe 15ms or 0. and there is a big difference between them.
I know the accuracy is OS dependent and not really nanoseconds accurate but 15miliseconds is way off to be an accuracy problem.
EDIT: the very goal of this code was to measure CPU performance on the loop. so if possible I want the effect of Compiler optimization and OS context switching etc to be minimal.
many thanks.
You should use System.nanoTime(). (API Here)
From the documentation:
This method can only be used to measure elapsed time and is not
related to any other notion of system or wall-clock time. The value
returned represents nanoseconds since some fixed but arbitrary origin
time (perhaps in the future, so values may be negative). The same
origin is used by all invocations of this method in an instance of a
Java virtual machine; other virtual machine instances are likely to
use a different origin.
So the nanoTime() is fine for use to measure your execution time because the measurement will always be the same and it will use nanoseconds.
Set the start time to the current nano time.
start = System.nanoTime();
At the end of the loop set the end time to the current nano time
end = System.nanoTime();
To find the difference, which is the time it took to execute, just subtract like you do.
To make it easy, you can just change getUserTime() to return System.nano()
Example:
//get integers m and n from user before this.
long start,end,time;
int[][] a = new int[m][n];
int[][] b = new int[m][n];
int[][] c= new int[m][n];
start = getUserTime();
for(int i = 0;i < m;i++)
{
for(int j = 0;j < n;j++)
{
c[i][j] = a[i][j]+b[i][j];
}
}
end = getUserTime();
// You could use Math.abs() here to handle the situation where
// the values could be negative
time = end - start;
/** Get user time in nanoseconds. */
public long getUserTime() {
return System.nanoTime()
}

StackOverflowError using Recursion

I'm supposed to be comparing a Recursive and a Non-Recursive function to see which one is quicker for a class project. The professor also wants us to time the iterations in milliseconds when the iterator is equal to 10,100,1000, etc. I got it all to work but was having loads of trouble in C++ getting the timer, so I switched to Java as it's much much easier to get millisecond output.
But now when I try to use any number over 8,000 I get a big fat stack overflow error from the Recursive algorithm. Can anyone give me any insight?
Bonus: I also can't figure out how to do the timer in the Recursive function like I did in the Non-Recursive. How would I approach this?
public class comparingTimes {
public static void main(String[] args) {
double num = 10000;
double result;
nonRec(num);
result = rec(num);
System.out.printf("Rec %.0f",(result));
}
public static void nonRec(double num)
{
double resultNum = 1;
double total = 0;
long startTime = System.currentTimeMillis();
long endTime;
for (double i = 1; i < num; i++)
{
total += i * (i+1);
if (i == resultNum)
{
endTime = System.currentTimeMillis();
System.out.printf("Total execution time: %f seconds - num = %.0f%n", (endTime - startTime)/1000.0, i);
resultNum *= 10;
}
}
System.out.printf("NonRec: %.0f%n", total);
}
public static double rec(double num)
{
if (num == 0)
return 0;
else
return num * (num-1) + rec(num-1);
}
}
The ideal use case for recursion is when you reduce the "search space" massively on each recursion level. For example, consider a binary search where each recursion level halves the remaining search space.
Your particular problem is that you're trying to do 8000 levels of recursion since each level simply decrements the value. That's going to require a fairly large chunk of stack space.
You can look into increasing the stack size for your JVM with the -ss or -oss options (depending on implementation, of course). But that will only buy you so much.
In terms of timing the whole recursive operation, I would simply store the time before the top-level call in main(), then compare that to the time after that top-level call returns, something like:
long startTime = System.currentTimeMillis();
result = rec(num);
long endTime = System.currentTimeMillis();
// Now calculate the elapsed time.
There's no need to try and do it within the recursive call itself.
If you want to do it at certain points within the recursive call, you can initialise a "global" counter variable (one outside the recursion itself, such as a class-level static variable) to 0 and have the recursive function increment it for every recursion level.
Then have it output the time deltas at the points you're interested in, such as when the variable is set to 10, 100, 1000 and so on.
Try increasing the stack size.
As for measuring time
public static void main(String[] args) {
double num = 10000;
double result;
long start = System.currentTimeMillis();
nonRec(num);
long finish = System.currentTimeMillis();
System.out.println("Time taken (non-recursive): " + (finish -start));
start = System.currentTimeMillis();
result = rec(num);
finish = System.currentTimeMillis();
System.out.println("Time taken (recursive): " + (finish -start));
System.out.printf("Rec %.0f",(result));
}

Strange code timing behavior in Java

In the following code:
long startingTime = System.nanoTime();
int max = (int) Math.pow(2, 19);
for(int i = 0; i < max; ){
i++;
}
long timePass = System.nanoTime() - startingTime;
System.out.println("Time pass " + timePass / 1000000F);
I am trying to calculate how much time it take to perform simple actions on my machine.
All the calculations up to the power of 19 increase the time it takes to run this code, but when I went above 19(up to max int value 31) I was amazed to discover that it have no effect on the time it takes.
It always shows 5 milliseconds on my machine!!!
How can this be?
You have just witnessed HotSpot optimizing your entire loop to oblivion. It's smart. You need to do some real action inside the loop. I recommend introducing an int accumulator var and doing some bitwise operations on it, and finally printing the result to ensure it's needed after the loop.
On the HotSpot JVM, -XX:CompileThreshold=10000 by default. This means a loop which iterates 10K times can trigger the whole method to be optimised. In your case you are timing how long it take to detect and compile (in the background) your method.
use another System.nanoTime() in the loop. no one can optimize this.
for(int i = 0; i < max; ){
i++;
dummy+=System.nanoTime();
}
dont forget to do:
System.out.println(dummy);
after the loop. ensures non-optimization

adding run time on my java program

what is the correct code to calculating time in Java with
public static int getGcd( int a, int b, int temp) format?
A simple solution:
First, Grab and store the time before you start the piece of code you want the run time for:
long start =System.currentTimeMillis();
After the code that you are tracking grab the current time and subtract it from your starting point to get the total time elapsed:
System.out.println(System.currentTimeMillis() - start);
If it runs relatively fast and you're trying to get an average time by running it on a bunch of random inputs, use:
long totalTime = 0;
long start = System.nanoTime();
for(int i=0;i<n;i++){
//Generate a and b
getGcd(a, b);
}
long end = System.nanoTime();
totalTime = end - start;
start = System.nanoTime();
for (int i=0;i<n;i++){
//Generate a and b
}
end = System.nanoTime();
totalTime -= end - start;
return totalTime / n;
This gives you your average time in nanoseconds.
Finding the average running time of GCD is a very interesting and complex problem. In the worst case, the inputs have a ratio which is close to the golden mean (such as consecutive Fibonacci numbers) and then the running time is O(log n). But it's still possible to have extremely large inputs and end up with essentially constant time. I'd be curious to know your results.

Categories