I wrote a test that will run recursion Fibonacci for 40 and run memoization recursion Fibonacci for 40 and compare the time to be at least one order of magnitude different. This is what I get so far:
#Test
void MemoizedMagnitudeDifferentFromRecursion(){
Fibonacci simpleRecursiveFibonacci = new SimpleRecursiveFibonacci();
Fibonacci memoizedRecursiveFibonacci = new MemoizedRecursiveFibonacci();
int n = 40;
long recursionStartTime = System.nanoTime();
simpleRecursiveFibonacci.fibonacci(n);
long recursionTime = System.nanoTime() - recursionStartTime;
//The code below does the same as the code above, how can I remove duplicated code?
long memoizedStartTime = System.nanoTime();
memoizedRecursiveFibonacci.fibonacci(n);
long memoizedTime = System.nanoTime() - memoizedStartTime;
assertTrue(recursionTime/memoizedTime > 1);
}
Extract the logic to a function and pass the logic to be run as a Runnable. Let the function run the piece of logic passed in and return the time it took to run it.
private long execute(Runnable runnable) {
long startTime = System.nanoTime();
runnable.run();
return System.nanoTime() - startTime;
}
Call it as
long recursionTime = execute(() -> simpleRecursiveFibonacci.fibonacci(n));
long memoizedTime = execute(() -> memoizedRecursiveFibonacci.fibonacci(n));
assertTrue(recursionTime/memoizedTime > 1);
One more option (as suggested by SystemGlitch#) is to pass an instance of Fibonacci and an int and call fibonacci inside the method.
private long execute(Fibonacci fibonacciInstance, int n) {
long startTime = System.nanoTime();
fibonacciInstance.fibonacci(n);
return System.nanoTime() - startTime;
}
Call it as
long recursionTime = execute(simpleRecursiveFibonacci, n);
long memoizedTime = execute(memoizedRecursiveFibonacci, n);
assertTrue(recursionTime/memoizedTime > 1);
Related
I know how to get the runtime of a method from here
How do I time a method's execution in Java?
Now I need to get the run time multiple times, so is there a way to make something like
public long exTime(methodToTime())
long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();
long duration = (endTime - startTime);
Thanks for your help
edit: to be more specific, my current code is
long startTime0 = System.nanoTime();
revealStr("1001*00*10");
long endTime0 = System.nanoTime();
long duration0 = (endTime0 - startTime0);
System.out.println("The runtime is " + endTime0);
System.out.println("10**01*1*0");
long startTime1 = System.nanoTime();
revealStr("10**01*1*0");
long endTime1 = System.nanoTime();
long duration1 = (endTime0 - startTime1);
System.out.println("The runtime is " + endTime1);
System.out.println("0*1*0**0**");
long startTime2 = System.nanoTime();
revealStr("0*1*0**0**");
long endTime2 = System.nanoTime();
long duration2 = (endTime2 - startTime2);
System.out.println("The runtime is " + endTime2);
System.out.println("****1*1***");
long startTime3 = System.nanoTime();
revealStr("****1*1***");
long endTime3 = System.nanoTime();
long duration3 = (endTime3 - startTime3);
System.out.println("The runtime is " + endTime3);
System.out.println("**********");
long startTime4 = System.nanoTime();
revealStr("**********");
long endTime4 = System.nanoTime();
long duration4 = (endTime4 - startTime4);
System.out.println("The runtime is " + endTime0);
which is repetitive and redundant
This is a util method I used to compare the performance of two method.
public static void testPerformance(long loopTime, Runnable r1,Runnable r2){
long startTime;
long endTime;
startTime=System.currentTimeMillis();
for (int i = 0; i < loopTime; i++) {
r1.run();
}
endTime=System.currentTimeMillis();
System.out.printf("loop %d times, total spend %d s, each spend %f ms\n",loopTime,(endTime-startTime)/1000,(double)(endTime-startTime)/loopTime);
startTime=System.currentTimeMillis();
for (int i = 0; i < loopTime; i++) {
r2.run();
}
endTime=System.currentTimeMillis();
System.out.printf("loop %d times, total spend %d s, each spend %f ms\n",loopTime,(endTime-startTime)/1000,(double)(endTime-startTime)/loopTime);
}
You can use like this:
PerformanceUtils.testPerformance(loopTime,()->{
//do some thing
},()->{
//do some thing
});
For some reason I can get the start time and the stop time in my program (which is normally a difference of 3 milliseconds) but when I print the result of the getElapsedTime() method it always comes back with 0. Above the listed code is the creation of a StopWatch object named sortTime.
Perhaps there is a problem with rounding?
Perhaps there is a problem with the getElapsedTime() method itself?
System.out.println(sortTime.start()); // Start Timer
java.util.Arrays.sort(numbers); // Sort the array
System.out.println(sortTime.stop());// stop timer
System.out.println("the elapsed time is: " + sortTime.getElapsedTime());
}
} //end of main class (used for testing)
//Define Class
class StopWatch {
long startTime;
long endTime;
//Constructors
public StopWatch () {
}
//Methods
long start() {
long startTime = System.currentTimeMillis();
return startTime;
}
long stop() {
long endTime = System.currentTimeMillis();
return endTime;
}
long getElapsedTime() {
return (endTime - startTime);
}
}
For example, when I run the program the result is:
1442877972466
1442877972469
the elapsed time is: 0
You are creating local variables with the same name as class variables:
long start() {
long startTime = System.currentTimeMillis();
return startTime;
}
The use of long startTime in this function makes a local variable that is different from the class member named startTime. Change this to:
long start() {
startTime = System.currentTimeMillis();
return startTime;
}
startTime and endTime have been redeclared/shadowed as local variables, leaving the instance fields with their default values (of 0)
long start() {
long startTime = System.currentTimeMillis();
return startTime;
}
long stop() {
long endTime = System.currentTimeMillis();
return endTime;
}
Instead, make use of the instance fields...
long start() {
startTime = System.currentTimeMillis();
return startTime;
}
long stop() {
endTime = System.currentTimeMillis();
return endTime;
}
Below is My code:
public class FindTime {
HashSet<String> hashSet = new HashSet<>();
long m1() {
hashSet.add("hai");
hashSet.add("me");
hashSet.add("you ");
hashSet.add("I");
hashSet.add("Us");
Iterator it = hashSet.iterator();
long startTime = System.currentTimeMillis();
while (it.hasNext()) {
System.out.println(it.next());
}
return startTime;
}
public static void main(String[] args) {
FindTime ft = new FindTime();
long startTime = ft.m1();
System.out.println("startTime" + startTime);
long endTime = System.currentTimeMillis();
System.out.println("End time" + endTime);
System.out.println("d/W" + (endTime - startTime));
}
}
I don't know is that one is correct way or not.My requirement is
"I want to calculate time taken to Iterate a HashSet".
To be more precise use System.nanoTime()
public class FindTime {
HashSet<String> hashSet = new HashSet<>();
long m1()
{
hashSet.add("hai");
hashSet.add("me");
hashSet.add("you ");
hashSet.add("I");
hashSet.add("Us");
Iterator it = hashSet.iterator();
long startTime = System.nanoTime();
while (it.hasNext()) {
System.out.println(it.next());
}
return startTime;
}
public static void main(String[] args) {
FindTime ft = new FindTime();
long startTime = ft.m1();
long endTime = System.nanoTime(); //CALCULATE THE END TIME BEFORE PRINTING START TIME
//BECAUSE PRINT OPERATION WILL ALSO TAKE TIME THAT WILL BE ADDED TO DIFFERENCE
System.out.println("Start time in nano seconds" + startTime); //No need because you actually need difference
System.out.println("End time in nano seconds" + endTime);
System.out.println("Difference in Nano Seconds" + (endTime - startTime));
//long microsecondsTime = (end - start) / 1000; //If you need in microseconds
}
}
Your code is correct. You've calculated the time which taken for iterating and printing the output in console. Print may take more time than iteration.
You may have also returned the execution time by
return System.currentTimeMillis()- startTime;
See Also : Do not use System.out.println in server side code
As you telling you need time to take only for iterate not for insertion then you can use it like
long m1() {
hashSet.add("hai");
hashSet.add("me");
hashSet.add("you ");
hashSet.add("I");
hashSet.add("Us");
Iterator it = hashSet.iterator();
long startTime = System.nanoTime();
while (it.hasNext()) {
System.out.println(it.next());
}
long endTime = System.nanoTime();
System.out.println("time taken in nano seconds" + endTime-startTime);
return endTime-startTime;
}
reason is if you take time into your main function then it will also calculate the time for insertion.
Yes I am agree that it will not affect too much but we know that is not right thing to do.Even here I am printing so here also it will add the printing time that is not exactly correct.
This is code which I have written to time how long it takes to perform a selection sort:
static public String [ ] selectionSort(String [ ] wordlist)
{
for (int i = 1; i < wordlist.length; i++)
{
int s = i-1;
for (int j = i; j < wordlist.length; j++)
{
if (wordlist[j].compareTo(wordlist[s]) < 0)
{
s = j;
}
}
String temp = wordlist[i-1];
wordlist[i-1] = wordlist[s];
wordlist[s] = temp;
}
return wordlist;
}
static public String [ ] timedSelectionSort(String [ ] wordlist)
{
long startTime = 0;
long stopTime = 0;
long elapsedMillis = 0;
long elapsedSec = 0;
long elapsedMin = 0;
startTime = System.currentTimeMillis();
wordlist = selectionSort(wordlist);
stopTime = System.currentTimeMillis();
elapsedMillis = stopTime-startTime;
elapsedSec = elapsedMillis/1000;
elapsedMin = elapsedMillis/60000;
System.out.printf("File reading took %d minutes and %s secs and %d milliseconds to execute\n",
elapsedMin,elapsedSec%60, elapsedMillis%1000);
System.out.println("Read " + wordlist.length + " strings.");
return wordlist;
}
I have to also time a how long it takes to make an arraylist object containing all of the strings in an array (my attempt is below)
static public ArrayList<String> makeArrayListClassObject(String [ ] wordlist)
{
long startTime = 0;
long stopTime = 0;
long elapsedMillis = 0;
long elapsedSec = 0;
long elapsedMin = 0;
startTime = System.currentTimeMillis();
ArrayList<String> stringList = new ArrayList<String>(Arrays.asList(wordlist));
stopTime = System.currentTimeMillis();
elapsedMillis = stopTime-startTime;
elapsedSec = elapsedMillis/1000;
elapsedMin = elapsedMillis/60000;
System.out.printf("File reading took %d minutes and %s secs and %d milliseconds to execute\n",
elapsedMin,elapsedSec%60, elapsedMillis%1000);
System.out.println("Read " + wordlist.length + " strings.");
return stringList;
}
as well as time how long it takes to sort the arraylist object using the Collections.sort( ) method. I have made the method (see below) but I don't know how to time it
static public void collectionsClassSort(ArrayList<String> arraylist)
{
Collections.sort(arraylist);
}
I guess my questions are:
1. Is there a way to use the same method to time these two methods the way I timed the first method?
2. If not, how can I time these two methods?
EDIT: the timed collections sort now works, but the timed building of the arraylist still does not. meaning that the timer says that the method took 0 minutes, 0 seconds, and 0 milliseconds to execute
This is the updated code for that:
static public ArrayList<String> makeArrayListClassObject(String [ ] wordlist)
{
long startTime = 0;
long stopTime = 0;
long elapsedMillis = 0;
long elapsedSec = 0;
long elapsedMin = 0;
startTime = System.currentTimeMillis();
ArrayList<String> stringList = new ArrayList<String>(Arrays.asList(wordlist));
stopTime = System.currentTimeMillis();
elapsedMillis = stopTime-startTime;
elapsedSec = elapsedMillis/1000;
elapsedMin = elapsedMillis/60000;
System.out.printf("File reading took %d minutes and %s secs and %d milliseconds to execute\n",
elapsedMin,elapsedSec%60, elapsedMillis%1000);
return stringList;
}
Why can't you just use something like this,
startTime = System.currentTimeMillis();
Collections.sort(arraylist);
stopTime = System.currentTimeMillis();
Its samething that you used above.
You need to distinguish between "doesn't work" and "doesn't produce a meaningful result".
It seems that your wordList string array is not large enough to notice time difference.
Two suggestions:
Test it with a much bigger array: hundreds of thousands of words (see my test code at the bottom)
Use System.nanoTime() that should yield better precision (see the explanation below).
From David Holmes' Weblog:
The absolute "time-of-day" clock is represented by the
System.currentTimeMillis() method, that returns a millisecond
representation of wall-clock time in milliseconds since the epoch. As
such it uses the operating system's "time of day" clock. The update
resolution of this clock is often the same as the timer interrupt (eg.
10ms), but on some systems is fixed, independent of the interrupt
rate.
The relative-time clock is represented by the System.nanoTime() method
that returns a "free-running" time in nanoseconds. This time is useful
only for comparison with other nanoTime values. The nanoTime method
uses the highest resolution clock available on the platform, and while
its return value is in nanoseconds, the update resolution is typically
only microseconds. However, on some systems there is no choice but to
use the same clock source as for currentTimeMillis() - fortunately
this is rare and mostly affects old Linux systems, and Windows 98.
You should always try to use nanoTime to do timing measurement or
calculation (and yes there are JDK API's that don't do this), in the
hope that it will have a better resolution than currentTimeMillis.
The following code produced "2" on my system:
import java.util.*;
public class ArrayTime {
public static void main(String[] args) {
String[] wordList = new String [600000];
for(int i=0; i<wordList.length; ++i)
wordList[i] = "" + i;
long start = System.currentTimeMillis();
ArrayList<String> stringList = new ArrayList<String>(Arrays.asList(wordList));
long elapsedTime = System.currentTimeMillis() - start;
System.out.println(elapsedTime);
}
}
I would like to write a test for a method, that calls observers in a specific intervall, so that they will execute a method. The timer-object runs in its own thread.
Method of timer to be tested
private long waitTime;
public Metronome(int bpm) {
this.bpm = bpm;
this.waitTime = calculateWaitTime();
this.running = false;
}
public void run() {
long startTime = 0, estimatedTime = 0, threadSleepTime = 0;
running = true;
while (running) {
startTime = System.nanoTime();
tick();// notify observers here
estimatedTime = System.nanoTime() - startTime;
threadSleepTime = waitTime -estimatedTime;
threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;
try {
Thread.sleep(threadSleepTime / 1000000l);
} catch (InterruptedException e) {
// sth went wrong
}
}
}
Snippet from my testclass
private int ticks;
private long startTime;
private long stopTime;
#Test
public void tickTest(){
metronome.setBpm(600);
startTime = System.nanoTime();
metronome.run();
long duration = stopTime - startTime;
long lowThreshold = 800000000;
long highThreshold = 900000000;
System.out.println(duration);
assertTrue(lowThreshold < duration);
assertTrue(duration <= highThreshold);
}
#Override
public void update(Observable o, Object arg) {
ticks ++;
if(ticks == 10){
metronome.stop();
stopTime = System.nanoTime();
}
}
Right now, my testclass registers as an observer at the object in question, so that i can count the number of times tick() was executed. The test measures the time before and after the execution, but it feels awkward to me, to test the behaviour this way.
Any suggestions for improving the test?
Sometimes the solution is to use something from a standard library that is sufficiently simple such that it does not need to be tested. I think SchedulerExecuterService will do the trick for replacing the home made Timer being tested here. Note that it is pretty rare to be bit by a bug in library code, but they do exist.
In general though, I think it is okay to create a helper class or use a mocking framework (Mockito) to do something simple like counting "ticks".
P.S. You can replace Thread.sleep(threadSleepTime / 1000000l) with TimeUnit.NANOSECONDS.sleep(threadSleepTime) ... which moves some logic from your code into the standard library.
Based on your comments I changed my code. Instead of implementing the Observer-interface in my testclass, I now created a private class, that implements the interface an registers at my timer.
Thanks for your time and thoughts.
Here is what the code now looks like:
revised testcode
#Test(timeout = 2000)
public void tickTest(){
long lowThreshold = 400000000;
long highThreshold = 600000000;
TickCounter counter = new TickCounter();
metronome.addObserver(counter);
metronome.setBpm(600);
startTime = System.nanoTime();
metronome.run();
long duration = System.nanoTime() - startTime;
assertTrue(lowThreshold <= duration);
assertTrue(duration <= highThreshold);
}
private class TickCounter implements Observer{
private int ticks;
public TickCounter(){
ticks = 0;
}
#Override
public void update(Observable o, Object arg) {
ticks++;
if(ticks == 5){
metronome.stop();
}
}
}
snippet from my revised timer
private long expectedTime; // calculated when bpm of timer is set
#Override
public void run() {
long startTime = 0, elapsedTime = 0, threadSleepTime = 0;
running = true;
while (running) {
startTime = System.nanoTime();
tick();
elapsedTime = System.nanoTime() - startTime;
threadSleepTime = expectedTime - elapsedTime;
threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;
try { TimeUnit.NANOSECONDS.sleep(threadSleepTime); } catch (Exception e) { }
}
}
My biggest issue might have been, that I implemented the observer-interface in my JUnit testcase. So I created a private observer, that specifically counts the number of times, the tick was executed. The counter then stops my timer.
The testmethod measures the timing and asserts, that the needed time is somewhere between my defined limits.
It depends on how accurately you need to measure the time.
If you feel that it's "awkward" is that because you're not sure that the measurement is accurate enough? Do you fear that the OS is getting in the way with overhead?
If so, you may need an external timing board that's synchronized to an accurate source (GPS, atomic standard, etc.) to either test your code, or possibly to provide the trigger for your firing event.
Try this. You also need the time you are expecting. The expected time will be 1000000000/n where n is the number of times your timer needs to tick() per second.
public void run(){
long time = System.nanotime();
long elapsedTime = 0;
// Hope you need to tick 30 times per second
long expectedTime = 1000000000/30;
long waitTime = 0;
while (running){
tick();
elapsedTime = System.nanotime()-time;
waitTime = expectedTime-elapsedTime();
if (waitTime>0){
try { Thread.sleep(waitTime) } catch (Exception e){}
}
time = System.nanotime();
}
}