RecursiveTask form Java 7 took greater time than expect - java

I am playing with RecursiveTask of the concurrent package from Java 7. It says this class has an implementation of forkJoin approach and can split my tasks in different threads. So I used a fibonacci example from the Java doc and compared the execution time with a normal recursive fibonacci. And for my surprise the normal recursive took less time! Why? Am I doing anything wrong?
import java.util.concurrent.RecursiveTask;
public class FibonacciJava extends RecursiveTask<Long> {
private static final long serialVersionUID = -2495228492435217747L;
private long n;
protected long valor;
public FibonacciJava(long n) {
this.n = n;
}
#Override
protected Long compute() {
if (n <= 1) {
return n;
}
FibonacciJava f1 = new FibonacciJava(n - 1);
f1.fork();
FibonacciJava f2 = new FibonacciJava(n - 2);
return f2.compute() + f1.join();
}
public long fibonacci(long valor) {
if (valor <= 1)
return valor;
else {
return fibonacci(valor - 1) + fibonacci(valor - 2);
}
}
public static void main(String[] args) {
long value = 40;
FibonacciJava fibonacciJava = new FibonacciJava(value);
long startTimeMillis = System.currentTimeMillis();
System.out.println("RecursiveTask FibonacciJava: "
+ fibonacciJava.compute() + " in "
+ (System.currentTimeMillis() - startTimeMillis)
+ " miliseconds.");
startTimeMillis = System.currentTimeMillis();
System.out.println("Recursive FibonacciJava: "
+ fibonacciJava.fibonacci(value) + " in "
+ (System.currentTimeMillis() - startTimeMillis)
+ " miliseconds.");
}
}
time:
RecursiveTask FibonacciJava: 102334155 in 3681 miliseconds.
Recursive FibonacciJava: 102334155 in 573 miliseconds.

Related

Java long object array assignment time difference

I have a piece of the source code in java8:
public class Test {
public static void main(String[] args) {
testObject(1.3);
testObject(1.4);
}
private static void testObject(double num) {
System.out.println("test:" + num);
long sta = System.currentTimeMillis();
int size = 10000000;
Object[] o = new Object[(int) (size * num)];
for (int i = 0; i < size; i++) {
o[i] = "" + i;
}
System.out.println("object[]: " + (System.currentTimeMillis() - sta) + " ms");
}
}
execution Result:
test:1.3
object[]: 7694 ms
test:1.4
object[]: 3826 ms
Why is the running time so different when my quantity is 1.4 * size?
I wanted to see how Java array assignment works, but I couldn't find anything on google.
In addition you have to keep in mind that System.currentTimeMillis returns a "Wall-Clock-Time". If your OS does a reschedule during the for-loop and a different process gets the cpu, the Wall-Clock-Time increases but your program won't execute.

Fastest way to search in milliseconds

I have to find what is the fastest way to search the max random number from my array within a range
So I create one method that search normal "using one thread" and another one that use threads
I have Class:MaxThread
import java.util.stream.IntStream;
public class MaxThread extends Thread {
private final int from;
private final int to;
public MaxThread(int[] tab, int from, int to) {
this.from = from;
this.to = to;
}
#Override
public void run() {
long start = System.currentTimeMillis();
int max = IntStream.of(from, to)
.max()
.getAsInt();
long end = System.currentTimeMillis() - start;
System.out.println("Max number from threads is : " + max);
System.out.println("Founded in: " + end + " [ms] ");
}
}
Class: Main2
public class Main2{
public static void main(String[] args) {
int[] tab = new int[200000000];
for (int i = 0; i < tab.length; i++) {
tab[i] = random(0, 200000000);
}
int max = searchMax(0, 50000000);
System.out.println("Max number without using threads " + max);
MaxThread maxThread = new MaxThread(tab, 25000000, 150000000);
maxThread.start();
}
public static int random(int start, int end) {
Random rnd = new Random();
return rnd.nextInt(end - start + 1) + start;
}
public static int searchMax(int from, int to) {
long start = System.currentTimeMillis();
int max = IntStream.of(from, to)
.parallel()
.max()
.getAsInt();
long end = System.currentTimeMillis() - start;
System.out.println("Founded in: " + end + " [ms] ");
return max;
}
}
I count the time in ms inside the method but I want to see witch one was the fastest to find the number , but here is where I cannot find out the way to do it.
Can someone give me and hint please?

How to interrupt a method after specific time in Java?

I need to write a simple program that prints prime numbers up to the given number but no longer than 5 seconds.
Is there some kind of timer to use to interrupt a method after a period of time? (but no interruption if printing is shorter than 5 sec).
Thanks in advance.
My code:
public class Primes {
private static boolean checkIfPrime(int x) {
if (x == 2) return true;
if (x % 2 == 0) return false;
int sqrt = (int) Math.sqrt(x) + 1;
for (int i = 3; i < sqrt; i = i + 2) if (x % i == 0) return false;
return true;
}
private static void printPrimesAndOperationTime(int n) {
long start = System.nanoTime();
for (int i = 2; i <= n; i++) if (checkIfPrime(i)) System.out.println(i);
long end = System.nanoTime();
long timeResult = end - start;
System.out.println("Printing time = " + timeResult + " [ns] => "
+ Math.round(timeResult * 100.0 / 1000000) / 100.0 + " [ms]");
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
printPrimesAndOperationTime(n);
}
}
Used Java Concurrency APIs to solve the above problem. please find inline comments for code walk through.
import java.util.Scanner;
import java.util.concurrent.*;
public class TimeoutInterval {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor(); // Start Single thread executor
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
Future future = executor.submit(new Primes(n)); // Find prime no.
try {
future.get(5, TimeUnit.SECONDS); // Set the time out of the prime no. search task
executor.shutdown();
} catch (TimeoutException e) {
executor.shutdown();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Primes implements Runnable {
private final int number;
Primes(int number) {
this.number = number;
}
#Override
public void run() {
System.out.println("Started..");
printPrimesAndOperationTime(number);
System.out.println("Finished!");
}
private static boolean checkIfPrime(int x) {
if (x == 2) return true;
if (x % 2 == 0) return false;
int sqrt = (int) Math.sqrt(x) + 1;
for (int i = 3; i < sqrt; i = i + 2) if (x % i == 0) return false;
return true;
}
private static void printPrimesAndOperationTime(int n) {
long start = System.nanoTime();
for (int i = 2; i <= n && !Thread.interrupted(); i++) if (checkIfPrime(i)) {
System.out.println(i);
}
long end = System.nanoTime();
long timeResult = end - start;
System.out.println("Printing time = " + timeResult + " [ns] => "
+ Math.round(timeResult * 100.0 / 1000000) / 100.0 + " [ms]");
}
}
Using ExecutorService, you can submit a task with a timeout. On Receiving the TimeoutException, you should call cancel(true) method on the task to interrupt the thread.
From the documentation
... If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

How to periodically print to terminal from an if statement that is nested in a while loop (Java)

I am writing a java application that will hash a series of input values repeatedly until a condition is met. I have accomplished this by nesting a series of if/else statements inside a while loop. I want to be able to print the hash rate to the terminal every 3 seconds while the application is actively hashing, and not repeatedly until the condition is met. I have tried using ExecutorService and scheduling a TimerTask but neither worked the way I wanted them to as they both kept on executing after the condition that should have stopped them was met. I know I am missing something but I don't know what ):
I've included a small snippet, feel free to ask for any information you may think is relevant.
Any help would be greatly appreciated!
I tried using a TimerTask like this:
while(iterator) {
if (difficulty == 1) {
if (!hash.startsWith("0")) {
long updatedTime = System.nanoTime();
Nonce++;
long deltaN = updatedTime - startTime;
long deltaS = (deltaN / 1000000000);
long hashRate = (Nonce / deltaS);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
System.out.println("Current hash rate: " + hashRate + " " + "hash/s");
}
}, 0, 3000);
} else {
System.out.println("Valid hash found! " + hash);
iterator = false;
}
}
}
EDIT: What this will be when finished is essentially a cheesy 'block chain' I will be using for illustrative purposes as a teaching tool, with that in mind I have included the rest of the 'miner' method below:
public void miner(long index, long currentTimeMillis, long data, long Nonce, String previousBlockHash, int difficulty) throws InterruptedException {
this.index = index;
this.currentTimeMillis = currentTimeMillis;
this.pszTimeStamp = pszTimeStamp;
this.Nonce = Nonce;
this.previousBlockHash = previousBlockHash;
this.difficulty = difficulty;
this.data = data;
boolean iterator = true;
String blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
String hash = SHA256.generateHash(blockHeader);
long startTime = System.nanoTime();
TimeUnit.SECONDS.sleep(2);
while (iterator) {
blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
hash = SHA256.generateHash(blockHeader);
if (difficulty == 1) {
if (!hash.startsWith("0")) {
long updatedTime = System.nanoTime();
Nonce++;
long deltaN = updatedTime - startTime;
long deltaS = (deltaN / 1000000000);
long hashRate = (Nonce / deltaS);
System.out.println("Current hash rate: " + hashRate
} else {
System.out.println("\n");
System.out.println("Hash found! \n");
System.out.println("Mined block hash: \n" + hash);
}
} else if (difficulty == 2) {
...........
All of the parameters the 'miner' method takes are passed to it by a launching class which includes the main function. My goal is to be able to print the hash rate while it searches for a 'valid' hash every few seconds instead of it printing thousands of times per second.
I have a few suggestions:
I personally would prefer using break inside a while(true) loop instead of of a loop variable. I feel that it makes the code more readable;
You are re declaring the Timer inside the loop, which means that a new timer is created each iteration of the loop. You need to create the timer once, outside the loop.
The Timer variable needs to be final to allow you to call timer.cancel() inside the run function of the TimerTask. If you plan on terminating the timer outside the run function, then the Timer variable need not be final.
import java.util.*;
public class Test{
static double Nonce;
public static void main(String... args) throws Exception{
final Timer timer = new Timer();
timer.schedule(new TimerTask(){
public void run(){
//calcualte hashRate by any formula
double hashRate = Nonce/100.0;
//check if the timer needs to continue, else call timer.cancel()
System.out.println(hashRate);
}
}, 0, 500);
while(true){
Thread.sleep(100);
Nonce++;
if(Nonce == 100){
timer.cancel(); //or terminate the timer outside the loop
break;
}
}
}
}
Please let me know if you need any help.
Edit:
A few things I have noticed:
The class variable Nonce cannot be static, otherwise it will be shared amongst all instances of the class.
The name of the variable cannot be Nonce in the function declaration, otherwise the local copy will be used whenever you use Nonce within the miner function.
If you do not calculate the hashRate directly, then deltaS can be zero, which may lead to a divide by 0 error.
Please let me know if you need any clarification.
public class ChainBuilder extends MainChain {
private long index;
private long currentTimeMillis;
private long data;
private int difficulty;
private String pszTimeStamp;
private String previousBlockHash;
private String currentHash;
private String genesisHash;
public long Nonce; //Nonce cannot be be static, otherwise it will cause issues if more than one object is created.
public static long startTime;
.......
public void miner(long index, long currentTimeMillis, long data, long _Nonce /*You cannot use Nonce here*/, String previousBlockHash, int difficulty) throws InterruptedException {
this.index = index;
this.currentTimeMillis = currentTimeMillis;
this.pszTimeStamp = pszTimeStamp;
this.Nonce = _Nonce; /*In this scope, Nonce refers to the local variable, and this.Nonce refers to the class variable.
If you use Nonce in this scope, then the class variable will not be changed.*/
this.previousBlockHash = previousBlockHash;
this.difficulty = difficulty;
this.data = data;
boolean iterator = true;
String blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
String hash = SHA256.generateHash(blockHeader);
startTime = System.nanoTime();
TimeUnit.SECONDS.sleep(2);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
long endTime = System.nanoTime();
long deltaN = endTime - startTime;
//long deltaS = (deltaN / 1_000_000_000);
long hashRate = (1_000_000_000 * Nonce / deltaN); /*calculate the hashRate directly, because if deltaN < 1_000_000_000,
then deltaS will be 0, giving a divide by zero error.*/
System.out.println("Current hash rate: " + hashRate + " " + "hash/s");
}
}, 0, 3000);
while (iterator) {
blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
hash = SHA256.generateHash(blockHeader);
if (difficulty == 1) {
if (!hash.startsWith("0")) {
Nonce++;
} else {
System.out.println("Hash found!");
timer.cancel();
.......
Okay, so what worked for me was declaring the relevant variables static, putting the start of the timer before loop, and cancelling upon the discovery of a valid hash, like so:
public class ChainBuilder extends MainChain {
private long index;
private long currentTimeMillis;
private long data;
private int difficulty;
private String pszTimeStamp;
private String previousBlockHash;
private String currentHash;
private String genesisHash;
public static long deltaS;
public static long deltaN;
public static long Nonce;
public static long startTime;
public static long endTime;
public static long hashRate;
.......
public void miner(long index, long currentTimeMillis, long data, long Nonce, String previousBlockHash, int difficulty) throws InterruptedException {
this.index = index;
this.currentTimeMillis = currentTimeMillis;
this.pszTimeStamp = pszTimeStamp;
this.Nonce = Nonce;
this.previousBlockHash = previousBlockHash;
this.difficulty = difficulty;
this.data = data;
boolean iterator = true;
String blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
String hash = SHA256.generateHash(blockHeader);
startTime = System.nanoTime();
TimeUnit.SECONDS.sleep(2);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
System.out.println("Current hash rate: " + hashRate + " " + "hash/s");
}
}, 0, 3000);
while (iterator) {
blockHeader = (index + currentTimeMillis + data + Nonce + previousBlockHash + difficulty);
hash = SHA256.generateHash(blockHeader);
if (difficulty == 1) {
if (!hash.startsWith("0")) {
endTime = System.nanoTime();
Nonce++;
deltaN = endTime - startTime;
deltaS = (deltaN / 1000000000);
hashRate = (Nonce / deltaS);
} else {
System.out.println("Hash found!");
timer.cancel();
.......

ExecutorService.submit(<callable>) taking more time?

I am trying to understand the utilities in java.util.concurrent package and learnt that we can submit callable objects to the ExecutorService, which returns Future, which is filled with the value returned by the callable, after successful completion of task within call() method.
I am understanding that all the callables are executed concurrently using multiple threads.
When I wanted to see how much improvement ExecutorService gives over the batch task execution, i thought of capturing time.
Following is the code which i tried to execute -
package concurrency;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorExample {
private static Callable<String> callable = new Callable<String>() {
#Override
public String call() throws Exception {
StringBuilder builder = new StringBuilder();
for(int i=0; i<5; i++) {
builder.append(i);
}
return builder.toString();
}
};
public static void main(String [] args) {
long start = System.currentTimeMillis();
ExecutorService service = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<Future<String>>();
for(int i=0; i<5; i++) {
Future<String> value = service.submit(callable);
futures.add(value);
}
for(Future<String> f : futures) {
try {
System.out.println(f.isDone() + " " + f.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("Executer callable time - " + (end - start));
service.shutdown();
start = System.currentTimeMillis();
for(int i=0; i<5; i++) {
StringBuilder builder = new StringBuilder();
for(int j=0; j<5; j++) {
builder.append(j);
}
System.out.println(builder.toString());
}
end = System.currentTimeMillis();
System.out.println("Normal time - " + (end - start));
}
}
and here is the output of this -
true 01234
true 01234
true 01234
true 01234
true 01234
Executer callable time - 5
01234
01234
01234
01234
01234
Normal time - 0
Please let me know if I am missing something OR understanding something in a wrong way.
Thanks in advance for your time and help for this thread.
If you task in Callable is to small, you won't get benefits from concurrency due task switching and overhead for initialisation. Try to add more heavier loop in callable, say 1000000 iterations, and you can see difference
When you run any code esp for the first time, it takes time. If you pass a task to another thread it can take 1-10 micro-seconds and if your task take less time than this, the overhead can be greater than the benefit. i.e. using multiple threads can be much slower than using a single thread if your overhead is high enough.
I suggest you
increase the cost of the task to 1000 iterations.
make sure the result is not discarded in the single threaded example
run both tests for at least a couple of seconds to ensure the code has warmed up.
Not an answer (but I am not sure the code will fit a comment). To expand a bit on what Peter said, there is usually a sweet spot for the size of your jobs (measured in execution time), to balance pool/queue overhead with fair work distribution among workers. The code example helps find an estimate for that sweet spot. Run on your target hardware.
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class FibonacciFork extends RecursiveTask<Long> {
private static final long serialVersionUID = 1L;
public FibonacciFork( long n) {
super();
this.n = n;
}
static ForkJoinPool fjp = new ForkJoinPool( Runtime.getRuntime().availableProcessors());
static long fibonacci0( long n) {
if ( n < 2) {
return n;
}
return fibonacci0( n - 1) + fibonacci0( n - 2);
}
static int rekLimit = 8;
private static long stealCount;
long n;
private long forkCount;
private static AtomicLong forks = new AtomicLong( 0);
public static void main( String[] args) {
int n = 45;
long times[] = getSingleThreadNanos( n);
System.out.println( "Single Thread Times complete");
for ( int r = 2; r <= n; r++) {
runWithRecursionLimit( r, n, times[ r]);
}
}
private static long[] getSingleThreadNanos( int n) {
final long times[] = new long[ n + 1];
ExecutorService es = Executors.newFixedThreadPool( Math.max( 1, Runtime.getRuntime().availableProcessors() / 2));
for ( int i = 2; i <= n; i++) {
final int arg = i;
Runnable runner = new Runnable() {
#Override
public void run() {
long start = System.nanoTime();
final int minRuntime = 1000000000;
long runUntil = start + minRuntime;
long result = fibonacci0( arg);
long end = System.nanoTime();
int ntimes = Math.max( 1, ( int) ( minRuntime / ( end - start)));
if ( ntimes > 1) {
start = System.nanoTime();
for ( int i = 0; i < ntimes; i++) {
result = fibonacci0( arg);
}
end = System.nanoTime();
}
times[ arg] = ( end - start) / ntimes;
}
};
es.execute( runner);
}
es.shutdown();
try {
es.awaitTermination( 1, TimeUnit.HOURS);
} catch ( InterruptedException e) {
System.out.println( "Single Timeout");
}
return times;
}
private static void runWithRecursionLimit( int r, int arg, long singleThreadNanos) {
rekLimit = r;
long start = System.currentTimeMillis();
long result = fibonacci( arg);
long end = System.currentTimeMillis();
// Steals zählen
long currentSteals = fjp.getStealCount();
long newSteals = currentSteals - stealCount;
stealCount = currentSteals;
long forksCount = forks.getAndSet( 0);
System.out.println( "Fib(" + arg + ")=" + result + " in " + ( end-start) + "ms, recursion limit: " + r +
" at " + ( singleThreadNanos / 1e6) + "ms, steals: " + newSteals + " forks " + forksCount);
}
static long fibonacci( final long arg) {
FibonacciFork task = new FibonacciFork( arg);
long result = fjp.invoke( task);
forks.set( task.forkCount);
return result;
}
#Override
protected Long compute() {
if ( n <= rekLimit) {
return fibonacci0( n);
}
FibonacciFork ff1 = new FibonacciFork( n-1);
FibonacciFork ff2 = new FibonacciFork( n-2);
ff1.fork();
long r2 = ff2.compute();
long r1 = ff1.join();
forkCount = ff2.forkCount + ff1.forkCount + 1;
return r1 + r2;
}
}

Categories