I am writing a word count program (very basic) and try to find its
execution time . What is strange is that sometime it shows
0 milliseconds after execution of same input for which earlier it gave
15 milliseconds.
Moreover sometime it shows 16 milliseconds and sometime 15
milliseconds for same input.Why is that variance? What could be the
possible reason for it?
Here is the program:
import java.util.*;
public class WordCount{
public static void main(String [] args){
Scanner scan=new Scanner(System.in);
System.out.println("Enetr the Line of String");
String words=scan.nextLine();
long startTime = System.currentTimeMillis();
wordCount(words);
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("\n TotalTime = "+totalTime + " mills");
}//main
public static void wordCount(String words){
Integer c=0;
String wor[]=words.split(" ");
//System.out.println(""+Arrays.toString(wor));
HashMap<String,Integer> hm=new HashMap<String,Integer>();
for(String word: wor){
// c=(Integer)hm.get(word);
c=hm.get(word);
c=(c==null)?1:c+1; //no c++
hm.put(word,c);
}
Set keySet=hm.keySet();
Iterator it=keySet.iterator();
while(it.hasNext()){
String key=(String)it.next();
System.out.println(""+key+" = " + hm.get(key));
}
}//wordCount
}//class
Output screen :
H:\Computer Science\Java>java WordCount
Enetr the Line of String
the is an the is an a is an the
the = 3
a = 1
is = 3
an = 3
TotalTime = 15 mills
H:\Computer Science\Java>java WordCount
Enetr the Line of String
the is an the is an a is an the
the = 3
a = 1
is = 3
an = 3
TotalTime = 16 mills
H:\Computer Science\Java>java WordCount
Enetr the Line of String
the is an the is an a is an the
the = 3
a = 1
is = 3
an = 3
TotalTime = 0 mills
H:\Computer Science\Java>java WordCount
Enetr the Line of String
the is an the is an a is an the
the = 3
a = 1
is = 3
an = 3
TotalTime = 0 mills
In the System.currentTimeMillis() JavaDoc we read that the method:
Returns the current time in milliseconds. Note that while the unit of
time of the return value is a millisecond, the granularity of the
value depends on the underlying operating system and may be larger.
For example, many operating systems measure time in units of tens of
milliseconds.
For Windows the resolution time for this method is longer than 1ms (in your case around 16ms) and this is a minimum time needed to update the timer. What this mean is that when you call System.currentTimeMillis() twice you get either two exactly same results (that explains 0) or two results which differ by amount of time needed to resolute time on your operating system.
Consider using System.nanoTime() instead System.currentTimeMillis(). It produces more precise results. You can read more about time measurement at the Oracle blog which concludes with the following paragraph:
If you are interested in measuring/calculating elapsed time, then
always use System.nanoTime(). On most systems it will give a
resolution on the order of microseconds. Be aware though, this call
can also take microseconds to execute on some platforms.
Execution time of your program is computationally 0. Counting words in a small sentence does not take time in milliseconds range. You are sometimes getting 15ms or 16ms most probably because of I/O (System.out), operating systems scheduling delays, other programs working on your system, or limitations of System.currentTimeInMillis() implementation. Actual working time of your word count program should be 0, take out the I/O.
Related
I am doing a project where I need to implement bubblesort, shellsort and quicksort algorithms in an array of 999 random doubles.
I need to measure the time it takes every algorithm to run.
I am using System.nanoTime() to measure this execution time for each algorithm. I have 3 buttons, one for each algorithm. Upon clicking a button, the timer starts, the function is called, the end timer is then called and the duration is calculated by having endtime-starttime. The duration is then printed on a label on top of the button.
public double[] randomArray = SortAlg.getArray();
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
long startTimeBubble = System.nanoTime();
SortAlg.bubble(randomArray);
long endTimeBubble = System.nanoTime();
long durationBubble = (endTimeBubble - startTimeBubble) / 1000000;
bubbleTiempo.setText("bubble took " + durationBubble + " ms");
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
long startTimeShellSort = System.nanoTime();
SortAlg.shellSort(randomArray);
long endTimeShellSort = System.nanoTime();
long durationShellSort = (endTimeShellSort - startTimeShellSort) / 1000000;
shellSortTime.setText("ShellSort took " + durationShellSort + " ms");
}
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
long startTimeQuickSort = System.nanoTime();
SortAlg.quickSort(randomArray, 0, randomArray.length - 1);
long endTimeQuickSort = System.nanoTime();
long durationQuickSort = (endTimeQuickSort - startTimeQuickSort) / 1000000;
quickSortTime.setText("Quicksort took " + durationQuickSort + " ms");
}
General clarifications:
1-getArray() generates a random array of 999 real (double) numbers between 0 and 2000.
2-None of the algorithm methods return an array, so this randomArray is NOT being saved as sorted, therefore, every time the button is clicked, the random array that is passed into the function is unsorted.
3-Every button has a unique label to display the results.
4-What you're seeing there is from the GUI class I created with Netbeans GUI editor, the buttons portion. Main simply creates a new GUI frame and sets it as visible, and the SortAlg contains the logic for the algorithms, which I already tested to be working.
But I have 2 issues here: If I click the button more than 1 time, the time decreases further for every click, until it's eventually 0, which makes no sense.
Also, I initially had a calculation error and I was dividing the time taken by 100000 rather than 1000000, but oddly enough, this was never giving me any errors. When I divide it by 1000000 though (which should be the correct operation for converting ns to ms) I sometimes get 0 MS execution time, which again makes no sense.
Lastly, and I know that this might be difficult to determine, but I was under the impression that quickSort had to be the fastest algorithm? But their execution times greatly vary within builds. Sometimes each one is 5 ms, other times its 30, other times its 68. I am concerned because it seems that, the first clicked is always the fastest one and the other ones end up being slower. I am not confident about these results at all.
When I divide it by 1000000 though (which should be the correct operation for converting ns to ms) I sometimes get 0 MS execution time, which again makes no sense.
Because you are using integer division:
long durationBubble = (endTimeBubble - startTimeBubble) / 1000000;
^^^^^^^
Just replace it with double to include the fraction:
double durationBubble = (endTimeBubble - startTimeBubble) / 1_000_000.0;
See:
Int division: Why is the result of 1/3 == 0?
I have a generator which generates events for Flink CEP, code for which is given below. Basically, I am using Thread.sleep() and I have read somewhere that java can't sleep less than 1 millisecond even we use System.nanoTime(). Code for the generator is
public class RR_interval_Gen extends RichParallelSourceFunction<RRIntervalStreamEvent> {
Integer InputRate ; // events/second
Integer Sleeptime ;
Integer NumberOfEvents;
public RR_interval_Gen(Integer inputRate, Integer numberOfEvents ) {
this.InputRate = inputRate;
Sleeptime = 1000 / InputRate;
NumberOfEvents = numberOfEvents;
}
#Override
public void run(SourceContext<RRIntervalStreamEvent> sourceContext) throws Exception {
long currentTime;
Random random = new Random();
int RRInterval;
int Sensor_id;
for(int i = 1 ; i <= NumberOfEvents ; i++) {
Sensor_id = 2;
currentTime = System.currentTimeMillis();
// int randomNum = rand.nextInt((max - min) + 1) + min;
RRInterval = 10 + random.nextInt((20-10)+ 1);
RRIntervalStreamEvent stream = new RRIntervalStreamEvent(Sensor_id,currentTime,RRInterval);
synchronized (sourceContext.getCheckpointLock())
{
sourceContext.collect(stream);
}
Thread.sleep(Sleeptime);
}
}
#Override
public void cancel() {
}
}
I will specify my requirement here in simple words.
I want generator class to generate events, let's say an ECG stream at 1200 Hz. This generator will accept parameters like input rate and total time for which we have to generate the stream.
So far so good, the issue is that I need to send more than 1000 events / second. How can I do this by using generator function which is generating values U[10,20]?
Also please let me know if I am using wrong way to generate x number of events / second in the above below.
Sleeptime = 1000 / InputRate;
Thanks in advance
The least sleep time in Windows systems is ~ 10 ms and in Linux and Macintosh is 1 millisecond as mentioned here.
The granularity of sleep is generally bound by the thread scheduler's
interrupt period. In Linux, this interrupt period is generally 1ms in
recent kernels. In Windows, the scheduler's interrupt period is
normally around 10 or 15 milliseconds
Through my research, I learned that using the nano time sleep in java will not help as the issue in at OS level. If you want to send data at arrival rate > 1000 in a controlled way, then it can be done using Real-Time Operating Systems (RTOS), as they can sleep for less then a millisecond. Now, I have come up with another way of doing it, but in this solution, the interarrival times will not be constantly distributed.
Let's say you want arrival rate of 3000 events/ second, then you can create a for loop which iterates 3 times to send data in each iteration and then sleep for 1ms. So for the 3 tuples, the interarrival time will be close to one another, but the issue will be solved. This may be a stupid solution but it works.
Please let me know if there is some better solution to this.
I've tried using timer.scheduledAtfixedRate(myTimerTask,delay,period), it seems that it will run myTimerTask at first and then wait 10s. So it will at last be total >10s.
class MyTimerTask extends TimerTask{
private static long lastTime;
public void run(){
try{
long before = System.currentTimeMillis();
callMethod();
long after = System.currentTimeMillis();
System.out.println("callMethod time:"+(after-before)+"ms");
System.out.println("total used time:"+(after-lastTime)+"ms");
lastTime = before;
}
}
}
callMethod time:
102ms
total used time:
10102ms
How can I make it use exactly 10s?
The output is correct: you are simply not looking at the right number.
Imagine the scenario:
lastTime = 0
// first execution
before = 0
after = 102
after - lastTime = 102
lastTime = before = 0
// second execution
before = 10 000
after = 10 000 + 102 (same execution time)
after - lastTime = (10 000 + 102) - 0 // because lastTime was set to before == 0
What you are interested in is to see if your befores are 10s apart, independently from the call time:
long before = System.currentTimeMillis();
System.out.println("elapsed time since last execution:"+(before-lastTime)+"ms");
This looks like your callMethod takes 102ms.The code execution, JIT etc may take a bit longer in the first runs. It has nothing to do woth when your task starts, relatively it takes 10s. If you expect scheduler to predict execution time then no- that's impossible.
You can use your TimerTask, but not directly start the program (or call your function) but start a new Thread that does the job. Then the TimerTask will finish his job of starting the new Thread (almost) immediately and will schedule a new run after 10 seconds (caution: even if your last run has not been finished yet!).
Still, the comments on your question apply - as you're probably not running on a real time operating system, those 10 seconds are not guaranteed. You can just try to get closer.
I am having a problem with Guava RateLimiter. I create the RateLimiter with RateLimiter.create(1.0) ("1 permit per second") and calls rateLimiter.acquire() on every cycle, but when I test run I get the following result:
Average: 1232.0 Diff since last: 2540
Average: 1180.0 Diff since last: 258
Average: 1159.0 Diff since last: 746
Average: 1151.0 Diff since last: 997
Average: 1144.0 Diff since last: 1004
Average is the number of milliseconds it sleeps on average and diff is the number of milliseconds passed since last print. On average it's okay, it does not permit my code to run more than once per second. But sometimes (as you can see) it runs more than once per second.
Do you have any idea why? Am I missing something?
The code that generates the above output:
private int numberOfRequests;
private Date start;
private long last;
private boolean first = true;
private void sleep() {
numberOfRequests++;
if(first) {
first = false;
start = new Date();
}
rateLimiter.acquire();
long current = new Date().getTime();
double num = (current -start.getTime()) / numberOfRequests;
System.out.println("Average: "+ num + " Diff since last: " + (current - last));
last = current;
}
Your benchmark appears to be flawed - when I try to replicate it I see very close to one acquisition per second. Here's my benchmark:
public class RateLimiterDemo {
public static void main(String[] args) {
StatsAccumulator stats = new StatsAccumulator();
RateLimiter rateLimiter = RateLimiter.create(1.0);
rateLimiter.acquire(); // discard initial permit
for (int i = 0; i < 10; i++) {
long start = System.nanoTime();
rateLimiter.acquire();
stats.add((System.nanoTime() - start) / 1_000_000.0);
}
System.out.println(stats.snapshot());
}
}
A sample run prints:
Stats{count=10, mean=998.9071456, populationStandardDeviation=3.25398397901304, min=989.303887, max=1000.971085}
The variance there is almost all attributable to the benchmark overhead (populating the StatsAccumulator and computing the time delta).
Even this benchmark has flaws (though I'll contend it's less-so). Creating an accurate benchmark is very hard, and simple whipped-together benchmarks are often either inaccurate or worse don't reflect the actual performance of the code being tested in a production setting.
This is just a hypothetical question, but could be a way to get around an issue I have been having.
Imagine you want to be able to time a calculation function based not on the answer, but on the time it takes to calculating. So instead of finding out what a + b is, you wish to continue perform some calculation while time < x seconds.
Look at this pseudo code:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int millisStart = System.currentTimeMillis();
// Perform calculation to find the 1000th digit of PI
// Check if the given amount of seconds have passed since millisStart
// If number of seconds have not passed, redo the 1000th PI digit calculation
// At this point the time has passed, return the function.
}
Now I know that I am horrible, despicable person for using precious CPU cycles to simple get time to pass, but what I am wondering is:
A) Is this possible and would JVM start complaining about non-responsiveness?
B) If it is possible, what calculations would be best to try to perform?
Update - Answer:
Based on the answers and comments, the answer seems to be that "Yes, this is possible. But only if it is not done in Android main UI thread, because the user's GUI will be become unresponsive and will throw an ANR after 5 seconds."
A) Is this possible and would JVM start complaining about non-responsiveness?
It is possible, and if you run it in the background, neither JVM nor Dalvik will complain.
B) If it is possible, what calculations would be best to try to perform?
If the objective is to just run any calculation for x seconds, just keep adding 1 to a sum until the required time has reached. Off the top of my head, something like:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int secondsStart = System.currentTimeMillis()/1000;
int requiredEndTime = millisStart + seconds;
float sum = 0;
while(secondsStart != requiredEndTime) {
sum = sum + 0.1;
secondsStart = System.currentTimeMillis()/1000;
}
}
You can and JVM won't complain if your code is not part of some complex system that actually tracks thread execution time.
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < 100000) {
// do something
}
Or even a for loop that checks time only every 1000 cycles.
for (int i = 0; ;i++) {
if (i % 1000 == 0 && System.currentTimeMillis() - startTime < 100000)
break;
// do something
}
As for your second question, the answer is probably calculating some value that can always be improved upon, like your PI digits example.