Java Fib iterative and Fib recursive time comparison - java

Please if you could just check my work and help guide me through the System.currentTimeMillis() function. I understand that it takes a snapshot of my computer time and then when I end it it takes another snap shot and I use the difference of those times to get my run time. Just not sure I'm implementing it properly as my times for my iterative function and my recursive are almost always identical or at most 1 off. I'm confused a little as to if my start time is called again before my iterative starts or if really my time check for iterative time is iterative plus my recursive function. Should I have my total iterative time be endTimeIter - endTimeRecur? Any help is appreciated.
public class FibTest{
public static void main (String[] args){
long startTime = System.currentTimeMillis();
int n = 40;
System.out.println("The 40th Fibonacci number per my recursive function is: " + fibRecur(n));
long endTimeRecur = System.currentTimeMillis();
long totalTimeRecur = endTimeRecur - startTime;
System.out.println("The 40th Fibonacci number per my recursive function is: " + fibIter(n));
long endTimeIter = System.currentTimeMillis();
long totalTimeIter = endTimeIter - startTime;
System.out.println("The time it took to find Fib(40) with my recursive method was: " + totalTimeRecur);
System.out.println("The time it took to find Fib(40) with my iterative method was: " + totalTimeIter);
}
public static int fibRecur(int n){
if (n < 3) return 1;
return fibRecur(n-2) + fibRecur(n-1);
}
public static int fibIter(int n){
int fib1 = 1;
int fib2 = 1;
int i, result = 0;
for (i = 2; i < n; i++ ){
result = fib1 + fib2;
fib1 = fib2;
fib2 = result;
}
return result;
}
}

That's one way of how the time difference must be done
long time = System.currentTimeMillis();
methodA();
System.out.println(System.currentTimeMillis() - time);
time = System.currentTimeMillis();
methodB();
System.out.println(System.currentTimeMillis() - time);

In addition to Amir's answer:
One bug in your program is that you print
System.out.println("The 40th Fibonacci number per my recursive function is: " + fibIter(n));
I think what you want to say is:
System.out.println("The 40th Fibonacci number per my iterative function is: " + fibIter(n));

Related

Timing bubble sorting in different scenarios

I am trying determine the running times of bubble sort algorithm in three different kinds of input:
1) randomly selected numbers
2) already sorted numbers
3) sorted in reverse order numbers
My expectation about their running time was:
Reverse ordered numbers would take longer than other two.
Already sorted numbers would have the fastest running time.
Randomly selected numbers would lie between these two.
I've tested the algorithm with inputs containing more than 100.000 numbers. The results wasn't like I expected. Already sorted numbers had the fastest running time but randomly selected numbers took almost twice as much time to execute compared to reverse ordered numbers. I was wondering why this is happening?
Here is how I test the inputs
int[] random = fillRandom();
int[] sorted = fillSorted();
int[] reverse = fillReverse();
int[] temp;
long time, totalTime = 0;
for (int i = 0; i < 100; i++) {
temp = random.clone();
time = System.currentTimeMillis();
BubbleSort.sort(temp);
time = System.currentTimeMillis() - time;
totalTime += time;
}
System.out.println("random - average time: " + totalTime/100.0 + " ms");
totalTime = 0;
for (int i = 0; i < 100; i++) {
temp = sorted.clone();
time = System.currentTimeMillis();
BubbleSort.sort(temp);
time = System.currentTimeMillis() - time;
totalTime += time;
}
System.out.println("sorted - average time: " + totalTime/100.0 + " ms");
totalTime = 0;
for (int i = 0; i < 100; i++) {
temp = reverse.clone();
time = System.currentTimeMillis();
BubbleSort.sort(temp);
time = System.currentTimeMillis() - time;
totalTime += time;
}
System.out.println("reverse - average time: " + totalTime/100.0 + " ms");
Benchmarks for java code are not easy, as JVM might apply a lot of optimizations to your code at runtime. It can optimize out a loop if computation result is not used, it can inline some code, JIT can compile some code into native and many other things. As a result, benchmark output is very unstable.
There are tools like jmh that simplify benchmarking a lot.
I recommend you to check this article, it has an example of benchmark for sorting algorithm.

In Android, how to measure the execution time overhead programmatically?

Although there might be similar questions (such as A), their answers do not solve my problem.
I am using Android Studio 1.5.1 targeting Android API 18 (before Android KitKat 4.4, so I’m dealing with Dalvik, not ART runtime).
I have a modified Android that adds memory space overhead (specifically designed by the author and it is outside the scope of this question) with any used variables. For example, if we declare an integer variable, the variable will be stored in 8 bytes (64-bit) instead of 4 bytes (32-bit). This modification is completely transparent to apps which can run on the modified Android without any problem.
I need to measure that overhead in execution time, for example, when I use variables.
Here is what I did so far but it does not seems to work because the overhead variable (at the end of //Method #1 in the code below) is inconsistent, sometime it is negative, positive, or zero. In the ideal solution, it should be always (or at least most of the time) positive.
long start, end, time1, time2, overhead;
//Baseline
start = System.nanoTime();
total=0; total+=1; total+=2; total+=3; total+=4; total+=5; total+=6;
total+=7; total+=8; total+=9;
end = System.nanoTime();
System.out.println("********************* The sum is " + total);
time1 = end - start;
System.out.println("********************* start=" + start + " end=" + end + " time=" + time1);
//Method #1
start = System.nanoTime();
total = (a0() + a1() + a2() + a3() + a4() + a5() + a6() + a7() + a8() + a9());
end = System.nanoTime();
System.out.println("********************* The sum is " + total);
time2 = end - start;
System.out.println("********************* start=" + start + " end=" + end + " time=" + time2);
overhead = time2 - time1;
System.out.println("********************* overhead=" + overhead );
}
private int a0()
{
return 0;
}
private int a1()
{
return 1;
}
private int a2()
{
return 2;
}
private int a3()
{
return 3;
}
private int a4()
{
return 4;
}
private int a5()
{
return 5;
}
private int a6()
{
return 6;
}
private int a7()
{
return 7;
}
private int a8()
{
return 8;
}
private int a9()
{
return 9;
}
My question is:
In Android, how to measure that execution time overhead programmatically?
What you are describing is simply experimental error.
the overhead variable is inconsistent, sometime it is negative,
positive, or zero. In the ideal solution, it should be always (or at
least most of the time) positive.
I don't have an exact solution for you problem on Android, but when I have done experimental testing in other contexts, I typically run multiple iterations and then divide by the number of iterations to get an average.
Here is some pseudocode:
int N = 10000;
startTimer();
for (int i = 0; i < N; i++) {
runExperiment();
}
stopTimer();
double averageRuntime = timer / N;
The problem is that the code that you are trying to time is executing faster than the resolution of System.nanotime(). Try doing your additions in a loop, for e.g.
for (int i = 0; i < 1000; i++) {
total += i;
}
Increase the loop count (1000) until you start getting reasonable elapsed times.

How to determine if a number is a prime in a faster fashion using additional threads?

I have a program which is PrimeNumbers class. It displays if the x is a prime or not. The x is the number being analyzed in the program.
There is a time on how long will the program take to know the answer. x is so big it takes 9 seconds to know the answer. How could the program run faster using more threads? I am having a hard time on getting how to implement thread in this situation.
public class PrimeNumbers {
private static int x = 2147483647;
public static boolean prime= true;
public static void main(String[]args){
long start, end, elapsetime;
start= System.currentTimeMillis();
for(int y=2; y<x; y++){
if(x % y == 0){
prime=false;
System.out.println(y);
break;
}
}
end = System.currentTimeMillis();
elapsetime = end - start;
System.out.println("Prime: " + prime);
System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000
+ " seconds."));
}
}
I'm going to ignore whether you've got the most efficient approach and focus on how your current code could be faster with more threads.
You currently iterate through all the numbers from 2 -> x and perform a simple test. A way to improve performance might be to split this task into Z chunks and start Z threads to perform the tests in parallel.
E.g. if you had two threads, you would have one thread examine 2 -> x/2 and the other examine x/2 + 1 -> x. Each thread should break from its testing if a global (and probably volatile) flag is set to true, which would indicate the other thread has disproved the prime.
Your primality test is very inefficient, you're looping over each number less than x. How can you improve it? This link should be helpful.
A good algorithm would be the AKS test, or Sieve of Eratosthenes. The code below implements one of the algorithms from the wiki article, which is much more efficient than the test you posted.
public static boolean isPrime(long n) {
// http://en.wikipedia.org/wiki/Primality test
if (n <= 3) return n > 1;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i*i <=n; i+=6) {
if (n % i == 0 || n % (i+2) == 0) return false;
}
return true;
}
}
If you intersted for a better algorithm Munyari has already suggested one.
Ignoring this following example can help you how you can make parallely execute an algorithm (even if it is a stupid algorithm)
We need a class which implements Callable interface (similar one to Runnable). It should get the part of the job and calculate it.
public class PrimeChecker implements Callable<Boolean> {
private final long numberToCheck;
private final long start;
private final long end;
public PrimeChecker(long numberToCheck, long start, long end) {
this.numberToCheck = numberToCheck;
this.start = start;
if (end >= numberToCheck) {
this.end = numberToCheck - 1;
}else{
this.end = end;
}
System.out.println("A PrimeChecker with start " + start + " and end " + end + " values to check number "
+ numberToCheck);
}
#Override
public Boolean call() throws Exception {
boolean prime = true;
long current = start;
if (current != 2 && (current % 2 == 0)) {
current = current + 1;
}
for (; current < end; current = current + 2) {
if (numberToCheck % current == 0) {
prime = false;
System.out.println("The number " + numberToCheck + " is divisable with " + current);
return prime;
}
}
return prime;
}
}
It simply start from a number and check if the given number numberToCheck is divisable and continues until it reaches the number end.
In the Main class we have to create multiple PrimeChecker jobs and execute them parallely. For this purpose we use Java's ExecutorService. It creates for us a thread pool. And then we can divide the job on multiple PrimeCheckers. Finally we execute them invokeAll method of ExecutorService. This gives us a Future list, which contains results of each jobs that we executed parallely.
public class Main {
public static boolean prime= true;
public static void main(String[] args) throws InterruptedException, ExecutionException {
long startTime = System.currentTimeMillis();
long numberToCheck = 5333334345L;
int numberOfThreads = 10;
System.out.println("Checking if the number " + numberToCheck + " ...");
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
List<PrimeChecker> primeCheckers = new ArrayList<PrimeChecker>();
long partOfNumber = (long) Math.ceil((double)numberToCheck/ numberOfThreads);
long start = 2 ;
long end = 0;
for(int i = 0; i < numberOfThreads; i++){
end = end + partOfNumber;
primeCheckers.add(new PrimeChecker(numberToCheck, start, end));
start = end+1;
}
List<Future<Boolean>> futures = executor.invokeAll(primeCheckers);
for(Future<Boolean> future : futures){
prime = future.get();
if(prime == false){
break;
}
}
System.out.println("The number " + numberToCheck + " is " + (prime ? "a prime" :"NOT !!!!!!!!!!!!!!!!!!!! a prime") + " number");
long endTime = System.currentTimeMillis();
long elapsetime = endTime - startTime;
System.out.println(elapsetime + " milliseconds");
System.exit(0);
}
}
You can try it with different numbers of threads (see numberOfThreads variable) to see the difference.
I hope it is a useful example for you, to understand multi threading better. (Be careful: It is only a tiny tiny part part of the whole threading theme)
If you do not need to implement the prime check yourself, I would propose to use the API. You can control the certainty, depending on your needs. In the example it is: 1-(1/2)100
public static void main(String[] args) {
BigInteger mersenne = new BigInteger("2").pow(521).add(BigInteger.ONE.negate());
System.out.println("digits of the number: " + mersenne.toString().length());
long start = System.currentTimeMillis();
final int certainty = 100;
boolean isPrime = mersenne.isProbablePrime(certainty);
System.out.println("elapsed millis: " + (System.currentTimeMillis() - start));
System.out.println("isPrime : " + isPrime);
}
edit
Here is an optimised version of the proposed example.
public class PrimeNumbers {
private static int x = 2147483647;
public static boolean prime= true;
public static void main(String[]args){
long start, end, elapsetime;
int divisor = 1;
start= System.currentTimeMillis();
if (x % 2 == 0) {
prime = false;
divisor = 2;
} else {
// - you can use an increment of two
// because you don't need to check
// for a divisor which is a multiple
// of two
// - you don't need to check for any divisor
// which is greater than x/2
for(int y=3; y < x/2; y += 2){
if(x % y == 0){
prime=false;
divisor = y;
break;
}
}
}
end = System.currentTimeMillis();
System.out.println("Prime: " + prime);
if (!prime) {
System.out.println("divisible by: " + divisor);
}
elapsetime = end - start;
System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000
+ " seconds."));
}
}

how to get more signficant digits to print from a long value?

I am trying to print a long value held by elapsed, can someone help me with the format of how to do it?
This prints 0.0
but i know it has more significant digits (maybe like .0005324 or something)
System.out.println("It took " + (double)elapsed + " milliseconds to complete SELECTION_SORT algorithm.");
'
System.currentTimeMillis();
long start = System.currentTimeMillis();
int sortedArr[] = selectionSort(arr1);
long elapsed = System.currentTimeMillis() - start;
System.out.println("\n///////////SELECTIONSort//////////////");
System.out.println("\nSelection sort implemented below prints a sorted list:");
print(sortedArr);
System.out.printf("It took %.7f ms....", elapsed);
//System.out.println("It took " + (double)elapsed + " milliseconds to complete SELECTION_SORT algorithm.");'
'
private static int[] selectionSort(int[] arr) {
int minIndex, tmp;
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
minIndex = i;
for (int j = i + 1; j < n; j++)
if (arr[j] < arr[minIndex])
minIndex = j;
if (minIndex != i) {
tmp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
}
return arr;
}'
Changing the format won't give you more resolution which is what your real problem is hee if you print 1 ms with 7 digits you just get 1.0000000 every time. This doesn't help you at all.
What you need is a high resolution timer
long start = System.nanoTime();
int sortedArr[] = selectionSort(arr1);
long elapsed = System.nanoTime() - start;
System.out.println("\n///////////SELECTIONSort//////////////");
System.out.println("\nSelection sort implemented below prints a sorted list:");
print(sortedArr);
System.out.printf("It took %.3f ms....", elapsed / 1e6);
However, if you do this once you are fooling yourself because Java compiles code dynamically and gets fast the more you run it. It can get 100x faster or more making the first number you see pretty useless.
Normally I suggest you run loops many times and ignore the first 10,000+ times. This will change the results so much that you will see that the first digit was completely wrong. I suggest you try this
for(int iter = 1; iter<=100000; iter *= 10) {
long start = System.nanoTime();
int[] sortedArr = null
for(int i=0;i<iter;i++)
sortedArr = selectionSort(arr1);
long elapsed = System.nanoTime() - start;
System.out.println("\n///////////SELECTIONSort//////////////");
System.out.println("\nSelection sort implemented below prints a sorted list:");
print(sortedArr);
System.out.printf("It took %.3f ms on average....", elapsed / 1e6 / iter);
}
You will see you results improve 10x maybe even 100x just by running the code for longer.
You can use print formatting. For a double or float, to get 7 places after the decimal place, you would do:
System.out.printf("It took %.7f ms....", elapsed);
EDIT:
You are actually using a long, not a double, so you cannot have significant digits, because long only takes on integer values.
A long is an integer value and does not have decimal places.
To get an approximation of the runtime, run the same sort in a loop, say 1000 times and then divide the measured time by 1000.
For example:
System.out.println("It took " + ((double)elapsed) / NUMBER_OF_ITERATONS);
Try this:
String.format("%.7f",longvalue);
by using above line you can format your long or any floating point numbers. Here 7 is referred how many digits you want after '.' .

How to return the time, which would take for a method to finish it's job?

I have a simple recursive algorithm, which returns Fibonacci numbers:
private static double fib_recursive(int n){
if(n <= 2) return 1;
else return fib_recursive(n-1) + fib_recursive(n-2);
}
Now my task is to return the time, which this method would take to calculate the 400-th fibonacci number on a given computer e.g. fib_recursive(400). "Would" is in bold, because I can't run the function, as it would take to long for this method to give an answer.
How can it be best achieved?
Calculate how much time to do each recursive call, figure out how many recursive calls, and you have an answer.
There are faster ways to do this, using a smarter recursion algorithm, but for your algorithm just put in some timing information.
Timing is done by taking differences of System.currenTimeMillis() or System.nanoTime() before and after what you want to meausre.
I ended up with probably not a best solution, but here is what i've got(may be it will help someone in future):
1) I measured the time, which the recursive method needs to calculate the 42-nd(for example) Fibonacci number.
2) Using the iterative method, I counted how many program rows are executed while calculating the 42-nd Fibonacci number with the recursive method. (Rows = 3*fib_iterative(42)-2)
3) Deviding 2. by 1. I got the average number of rows executed in 1 millisecond.
4) Using the iterative method, I counted how many program rows are executed while calculating the 400-th Fibonacci number with the recursive method. (Rows = 3*fib_iterative(400)-2)
5) Deviding 4. by 3. I got the estimated time spent by fib_recursive(400).
// Recursive algorithm, calculates Fibonacci number (slow)
private static double fib_recursive(int n){
if( n <= 2) return 1;
else return fib_recursive(n-1) + fib_recursive(n-2);
}
// Iterative algorithm, calculates Fibonacci number (fast)
private static double fib_iterative(int n){
double a = 1, b = 1;
for (int i = 2; i <= n; i++){
b = a + b;
a = b - a;
}
return a;
}
// Get time, which fib_recursive(int) needs to calculate the 400th Fibonacci number
private static long testRecursiveFor400(){
int elapsedTime = 0;
int start = (int) System.currentTimeMillis();
fib_recursive(42);
elapsedTime = (int) (System.currentTimeMillis() - start);
return (3 * (long) fib_iterative(400) - 2) / ((3 * (int) fib_iterative(42) - 2) / elapsedTime);
}

Categories