package org.jgroups.tests;
import org.jgroups.util.*;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Bela Ban
*/
public class TimeSchedulerStressTest {
final TimeScheduler timer;
final int num_threads;
final int num_tasks; // to process per thread
final long task_duration; // ms
final CyclicBarrier barrier;
final AtomicInteger total_tasks=new AtomicInteger(0);
final AtomicInteger total_sched=new AtomicInteger(0);
final AtomicInteger total_task_invocations=new AtomicInteger(0);
static final int NUM_THREADS_IN_TIMER=5;
public TimeSchedulerStressTest(TimeScheduler timer, int num_threads, int num_tasks, long task_duration) {
this.timer=timer;
this.num_threads=num_threads;
this.task_duration=task_duration;
this.num_tasks=num_tasks;
barrier=new CyclicBarrier(num_threads +1);
}
public void start() throws Exception {
MyThread[] threads=new MyThread[num_threads];
for(int i=0; i < threads.length; i++) {
threads[i]=new MyThread();
threads[i].setName("thread-" + i);
threads[i].start();
}
Util.sleep(1000);
System.out.println("starting " + threads.length + " threads");
long start=System.currentTimeMillis();
barrier.await();
Reporter reporter=new Reporter();
reporter.setDaemon(true);
reporter.start();
for(MyThread thread: threads)
thread.join();
long diff=System.currentTimeMillis() - start;
timer.stop();
System.out.println("Time: " + diff + " ms for " + total_tasks + " tasks");
System.out.println("running tasks: " + timer.size() + ", total_sched: " + total_sched + ", completed: " + total_tasks +
", total task invocations: " + total_task_invocations);
}
class MyThread extends Thread {
public void run() {
try {
barrier.await();
}
catch(Exception e) {
e.printStackTrace();
}
MyTask[] tasks=new MyTask[num_tasks];
for(int i=0; i < num_tasks; i++) {
tasks[i]=new MyTask();
timer.schedule(tasks[i], task_duration, TimeUnit.MILLISECONDS);
total_sched.incrementAndGet();
}
for(MyTask task: tasks) {
task.get();
total_tasks.incrementAndGet();
}
}
}
class Reporter extends Thread {
public void run() {
while(!timer.isShutdown()) {
System.out.println("running tasks: " + timer.size() + ", total_sched: " + total_sched + ", completed: " + total_tasks +
", total task invocations: " + total_task_invocations);
Util.sleep(2000);
}
}
}
class MyTask implements Runnable {
final Promise<Boolean> result=new Promise<Boolean>();
public void run() {
total_task_invocations.incrementAndGet();
result.setResult(true);
}
Boolean get() {
return result.getResult();
}
}
public static void main(String[] args) throws Exception {
int num_threads=100;
int num_tasks=100; // to process per thread
long task_duration=50; // ms
TimeScheduler timer=null;
for(int i=0; i < args.length; i++) {
if(args[i].equals("-num_threads")) {
num_threads=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-num_tasks")) {
num_tasks=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-task_duration")) {
task_duration=Long.parseLong(args[++i]);
continue;
}
if(args[i].equals("-type")) {
String tmp=args[++i];
if(tmp.equals("default")) {
timer=new DefaultTimeScheduler(NUM_THREADS_IN_TIMER); // ? That's not what we do in real life !
}
else if(tmp.equals("new")) {
timer=new TimeScheduler2(NUM_THREADS_IN_TIMER);
}
else {
help();
return;
}
continue;
}
help();
return;
}
if(timer == null) {
System.out.println("timer is null, using DefaultTimeScheduler with " + NUM_THREADS_IN_TIMER + " threads");
timer=new DefaultTimeScheduler(NUM_THREADS_IN_TIMER);
}
TimeSchedulerStressTest test=new TimeSchedulerStressTest(timer, num_threads, num_tasks, task_duration);
test.start();
}
static void help() {
System.out.println("TimeSchedulerStressTest [-type <\"default\" | \"new\">] [-num_threads <num>] [-num_tasks <num>]" +
" [-task_duration <ms>]");
}
}