Following piece of code is take different timing with long and double, not able to understand why there is the difference in the timing?
public static void main(String[] args) {
long j = 1000000000;
double k = 1000000000;
long t1 = System.currentTimeMillis();
for (int index = 0; index < j; index++) {
}
long t2 = System.currentTimeMillis();
for (int index = 0; index < k; index++) {
}
long t3 = System.currentTimeMillis();
long longTime = t2 - t1;
long doubleTime = t3 - t2;
System.out.println("Time to loop long :: " + longTime);
System.out.println("Time to loop double :: " + doubleTime);
}
Output:
Time to loop long :: 2322
Time to loop double :: 1510
long is taking longer time than double, I have 64 bit window operating system and 64 bit Java.
When I modified my code and add casting long and double to int like
public static void main(String[] args) {
long j = 1000000000;
double k = 1000000000;
long t1 = System.currentTimeMillis();
for (int index = 0; index < (int)j; index++) {
}
long t2 = System.currentTimeMillis();
for (int index = 0; index < (int)k; index++) {
}
long t3 = System.currentTimeMillis();
long longTime = t2 - t1;
long doubleTime = t3 - t2;
System.out.println("Time to loop long :: " + longTime);
System.out.println("Time to loop double :: " + doubleTime);
}
The time got reduced but still there is the difference in the timing, but this time double is taking more time than long(opposite of first case)
Output:
Time to loop long :: 760
Time to loop double :: 1030
Firstly, a long is a 64-bit integer and a double is a 64-bit floating point number. The timing difference will likely be due to the difference in optimisation between integer arithmetic and floating point arithmetic in your CPU's ALU.
Secondly, the second time you run your application, in each for loop, the loop evaluates the stop condition every time, so you're casting from a long and double to an integer respectively on every iteration. If you precast the value to an integer value before the loop's condition then you should get more consistent times:
int j_int = (int) j;
for(int index = 0; index < j_int; index++) { /* Body */ }
int k_int = (int) k;
for(int index = 0; index < k_int; index++) { /* Body */ }
In general, casting from long to int is simpler than from double to int.
The reason is that long and int are both whole numbers and represented in memory simply by their binary representation (and possibly one bit for the sign).
Casting from one to another is quite straightforward by just "cropping" or "extending" the memory area (and handling signs correctly).
However, double are floating point numbers and their binary representation a bit more complicated, using sign, mantissa and exponent.
Casting from here to whole numbers thus is more complicated, as it requires conversion from one binary format to the other first.
Related
It is well known that integer division is slow operation (typically several times slower than integer multiplication). But, if one need to perform many divide operations with a fixed divisor, it is possible to do some preconditioning on the divisor and replace "/" with multiplication and bit operations (Chapter 10 in Hacker's Delight).
As I've tested, if the divisor is a compilation-time constant, (e.g. static final long DIVISOR = 12345L;) JVM will do the trick and replace all divisions by DIVISOR with multiplication and bit operations. I'm interesting in the same kind of trick but when the divisor is known only at runtime.
For example, the following (slow) method:
void reduceArraySlow(long[] data, long denominator){
for(int i = 0; i < data.length; ++i)
data[i] = data[i] / denominator;
}
can be replaced with something:
void reduceArrayFast(long[] data, long denominator){
SomeMagicStructure magic = computeMagic(denominator);
for(int i = 0; i < data.length; ++i)
// computes data[i] / denominator
data[i] = doFastDivision(data[i], magic);
}
which must do the job much faster, since all / operations are replaced with faster operations (and also because division is not pipelined in CPUs).
There is well known C/C++ libdivide library for fast integer division, and there is my adaptation of this library for Java libdivide4j.
Fast division with libdivide4j looks as follows:
void reduceArrayFast(long[] data, long denominator){
FastDivision.Magic magic = FastDivision.magicSigned(denominator);
for(int i = 0; i < data.length; ++i)
// computes data[i] / denominator
data[i] = FastDivision.divideSignedFast(data[i], magic);
}
A simple benchmark
public void benchmark() throws Exception {
Random rnd = new Random();
int nIterations = 10000;
//let the JIT to optimize something
for (int att = 0; att < nIterations; att++) {
long[] data = new long[1000];
for (int i = 0; i < data.length; i++)
data[i] = rnd.nextLong();
long denominator = rnd.nextLong();
long[] slow = data.clone();
long start = System.nanoTime();
reduceArraySlow(slow, denominator);
long slowTime = System.nanoTime() - start;
long[] fast = data.clone();
start = System.nanoTime();
reduceArrayFast(fast, denominator);
long fastTime = System.nanoTime() - start;
Assert.assertArrayEquals(slow, fast);
// print last 100 timings (JVM already warmed up)
if (att > nIterations - 100) {
System.out.println("\"/\" operation: " + slowTime);
System.out.println("Fast division: " + fastTime);
System.out.println("");
}
}
}
shows the following timings (nanoseconds) for ordinary / and fast division (Core i7, jdk8 64-bit) :
"/" operation: 13233
Fast division: 5957
"/" operation: 13148
Fast division: 5103
"/" operation: 13587
Fast division: 6188
"/" operation: 14173
Fast division: 6773
...
I was creating a simple 'benchmark' program checking how many calculations a PC can do in 1 second, three times, then averaging and printing the result.
package benchmark;
public class Benchmark {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 1000;
long index = 0;
long index2 = 0;
long index3 = 0;
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime) {
break;
}
index++;
}
while (true) {
double y = Math.sqrt(index2);
long now2 = System.currentTimeMillis();
if (now2 > endTime) {
break;
}
while (true) {
double z = Math.sqrt(index3);
long now3 = System.currentTimeMillis();
if (now3 > endTime) {
break;
}
}
long total = (index + index2 + index3) / 3;
}
System.out.print(index + " loops per second on average.");
}
}
x, y and z variables are used here to store the result of Math.sqrt(index), and indexes 2 and 3.
However at no point in this program are the x, y and z variables called upon at all. Is there a way to remove them from the program?
A variabile uses space on the stack, and the relative push operation to write to the stack.
The compiler and/or the JIT (Just in time compiler) might (and usually will) remove those variables automatically, so having them or not having them will not make a difference if not in the first loops.
If you're mico-benchmarking you should always run the loop a few times (standard seems to be 10000 times) to warmup the code, and then re-run it again to measure real performance.
Are you looking for this solution?
package benchmark;
public class Benchmark {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 1000;
long index = 0;
long index2 = 0;
long index3 = 0;
while (true) {
Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime) {
break;
}
index++;
}
while (true) {
Math.sqrt(index2);
long now2 = System.currentTimeMillis();
if (now2 > endTime) {
break;
}
while (true) {
Math.sqrt(index3);
long now3 = System.currentTimeMillis();
if (now3 > endTime) {
break;
}
}
}
long total = (index + index2 + index3) / 3;
System.out.print(total + " loops per second on average.");
}
}
Also note, that index2 and index3 are never incremented and endTime is never recompouted, so the second and third while loop are only executed once anyway.
Yes, you can remove them, just call the method without storing the result, replace:
double x = Math.sqrt(index);
by
Math.sqrt(index);
// Hideously slow program! Can you spot the object creation?
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
end = System.currentTimeMillis();
System.out.println("Long sum took: " + (end - start) + " milliseconds");
long sum2 = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum2 += i;
}
end = System.currentTimeMillis();
System.out.println("long sum took: " + (end - start) + " milliseconds");
Hi, I am reading Effective Java and in Item 6:Avoid creating unnecessary objects, there is an example suggesting primitives to boxed primitives to avoid unnecessary object creation.
The author says, "Changing the declaration of sum from Long to long reduces the runtime from 43 seconds to 6.8 seconds on my machine." and continues, "The lesson is clear: prefer primitives to boxed primitives, and watch out for unintentional autoboxing".
But when I run it on my machine, the primitive version is slower than the boxed one.
The output of the program above:
Long sum took: 5905 milliseconds
long sum took: 7013 milliseconds
The results are not as expected as the author says, "The variable sum is declared as a Long instead of a long, which means that the program constructs about 2^31 unnecessary Long instances (roughly one for each time the long i is added to the Long sum)".
Why is using primitive slower than using object?
You didn't reset the starting point for the second measurement. The primitive performance is actually the time difference of your two values (which is obviously better than the wrapper's). Try this:
// Hideously slow program! Can you spot the object creation?
Long sum = 0L;
start = System.currentTimeMillis();
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
end = System.currentTimeMillis();
System.out.println("Long sum took: " + (end - start) + " milliseconds");
long sum2 = 0L;
// reset start!!
start = System.currentTimeMillis();
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum2 += i;
}
end = System.currentTimeMillis();
System.out.println("long sum took: " + (end - start) + " milliseconds");
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 '.' .
I'm writing a method to compute the running time for an algorithm. The algorithm is run a specified number of trials and then I compute the running time using System.currentTimeMillis(). However whenever I call the method the value always ends up being zero. Any direction towards fixing this problem is appreciated.
public long runTime(algorithm alg, int[] array, int trials)
{
long initialTime = System.currentTimeMillis();
for(int i = 0; i < trials; i++)
{
alg.runAlgorithm(array);
}
return ((System.currentTimeMillis() - initialTime) / (long) trials);
}
((System.currentTimeMillis() - initialTime) / (long) trials);
It seems the Algorithm is taking less than a 1 ms to complete its loop, and so you need to break it even to smaller unit... Using nanoTime() may do the work for u...
Eg:
public long runTime(algorithm alg, int[] array, int trials)
{
long initialTime = System.nanoTime();
for(int i = 0; i < trials; i++)
{
alg.runAlgorithm(array);
}
return ((System.nanoTime() - initialTime) / (long) trials);
}
If your return value is less then one. Use return type double. In your example, you should use double instance of long.