I have written a simple "benchmark" to compare performances in same cases - in Java and C#. In Java the program needs about 2,2s to complete (ran multiple times), in C# it needs 7,4s (ran multiple times).
Software used: Windows, Java (JDK 10), C# (.NET Framework 4.6.1)
Isn't CSharp's runtime jitting, or why is Java that times faster?
The program in Java:
Dummy[] dummies = new Dummy[100000000]; // Dummy = empty class
var timer = new Timer();
timer.start();
for (int i = 0; i < 100000000; i++) {
dummies[i] = new Dummy();
}
timer.stop();
System.out.println(String.format("Elapsed time: %sms", timer.millis(2)));
And in C#:
Dummy[] dummies = new Dummy[100000000]; // Dummy = empty class
var timer = new Timer();
timer.Start();
for (int i = 0; i < 100000000; i++)
{
dummies[i] = new Dummy();
}
timer.Stop();
Console.WriteLine("Elapsed time: {0}ms", timer.Millis(2));
The Timer class in Java:
public class Timer {
private long startTime, stopTime;
public void start() {
startTime = System.nanoTime();
stopTime = startTime;
}
public void stop() {
stopTime = System.nanoTime();
}
public double millis() {
return stopTime / 1e6 - startTime / 1e6;
}
public double millis(int decimals) {
double factor = Math.pow(10.0, decimals);
return Math.round(millis() * factor) / factor;
}
}
And in C#:
public class Timer
{
private double startTime, stopTime;
public void start()
{
startTime = TimeSpan.FromTicks(DateTime.Now.Ticks).TotalMilliseconds;
stopTime = startTime;
}
public void stop()
{
stopTime = TimeSpan.FromTicks(DateTime.Now.Ticks).TotalMilliseconds;
}
public double Millis()
{
return stopTime - startTime;
}
public double Millis(int decimals)
{
return Math.Round(Millis(), decimals);
}
}
Related
I have a Runner class which extends Thread. In main class, I have bunch of objects of Runner class which start race at the same time. I want to print the rank of each runner based on the time taken to finish their thread.
private void raceStart() throws InterruptedException
{
long start = System.currentTimeMillis();
Thread.sleep((long) (reaction * 1000));
int track = 100;
int playerLocation = 0;
Random randomDelay = new Random();
double delay = 90 + randomDelay.nextInt(16);
for(int i = 0; i <= track; i++)
{
if(playerLocation == track)
{
long finish = System.currentTimeMillis();
double totalTime = (double)(finish - start) / 1000;
System.out.format("%d %d %d %-12s %-12s %-25s %.3f %.3f%n" , rank, lane, bib, country, lastName, firstName, reaction, totalTime);
}
playerLocation++;
Thread.sleep((long) delay);
}
}
In my main class,
private void run()
{
Runner usainBolt = new Runner(1, 6, 2612, "JAM", "Bolt", "Usain", 0.155);
Runner justinGatlin = new Runner(2, 4, 3069, "USA", "GATLIN", "Justin", 0.152);
Runner andreDeGrasse = new Runner(3, 7, 2196, "CAN", "DE GRASSE", "Andre", 0.141);
Runner yohanBlake = new Runner(4, 9, 2611, "JAM", "BLAKE", "Yohan", 0.145);
Runner akaniSimbine = new Runner(5, 3, 2909, "RSA", "SIMBINE", "Akani", 0.128);
Runner benYoussefMeite = new Runner(6, 8, 2245, "CIV", "MEITE", "Ben Youssef", 0.156);
Runner jimmyVicaut = new Runner(7, 5, 2434, "FRA", "VICAUT", "Jimmy", 0.140);
Runner trayvonBromell = new Runner(8, 2, 3054, "USA", "BROMWELL", "Trayvon", 0.135);
List<Runner> runners = Arrays.asList(usainBolt, justinGatlin, andreDeGrasse,
yohanBlake, akaniSimbine, benYoussefMeite, jimmyVicaut, trayvonBromell);
for (Runner r : runners)
{
r.start();
}
I also want to print the total time taken by the whole program in the end.
I tried
long start = System.currentTimeMillis();
run(0);
long finish = System.currentTimeMillis();
double totalTime = (double)(finish - start) / 1000;
System.out.println("totalTime");
But it always prints 0 or 1 before displaying the results.
Since a lot of this is time recording based, I'd recommend creating a simple StopWatch class that each runner can hold on to and record their individual times.
public class StopWatch {
private long startTime = -1;
private long stopTime = -1;
private long currentTime = 0;
private boolean isRunning = false;
public void start(){
isRunning = true;
startTime = System.nanoTime();
}
public void stop(){
stopTime = System.nanoTime();
}
public long getCurrentTime(){
if (startTime != -1 && stopTime == -1){
currentTime = System.nanoTime() - startTime;
}else if (startTime != -1 && stopTime != -1){
currentTime = stopTime - startTime;
}
return currentTime;
}
public boolean isRunning(){
if(startTime != -1 && stopTime == -1){
isRunning = true;
}
return isRunning;
}
public void reset(){
startTime = -1;
stopTime = -1;
currentTime = 0;
isRunning = false;
}
}
I'm not sure what your Runner class looks like but I've made just a simple one that determines speed randomly and adds a random amount every second to each runner(you can create your own method in Runner to determine how quick each runner is). I would also implement comparable to runner so that you can sort them based on distance traveled and finally overide toString() method in Runner to print the relevant information that will be used for the leaderboard later.
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class Runner extends Thread implements Comparable {
boolean hasFinished = false;
int distanceTraveled = 0;
StopWatch timer = new StopWatch();
Random speed = new Random();
int raceDistanceMeters = 100;
private String nameF;
private String nameL;
public Runner(String nameL, String nameF) {
this.nameF = nameF;
this.nameL = nameL;
}
public void run() {
timer.start();
while(hasFinished == false){
try {
Thread.sleep(1000);
distanceTraveled = distanceTraveled + speed.nextInt(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (distanceTraveled >= raceDistanceMeters){
hasFinished = true;
distanceTraveled = raceDistanceMeters;
timer.stop();
}
}
}
#Override
public int compareTo(Object compareRunner) {
int compareDistanceTraveled = ((Runner)compareRunner).distanceTraveled;
return compareDistanceTraveled-this.distanceTraveled;
}
#Override
public String toString() {
return this.nameF + " " + this.nameL + " " + "Distance: " + distanceTraveled + " Time: " + (Double.valueOf(TimeUnit.NANOSECONDS.toMillis(timer.getCurrentTime())))/1000;
}
}
You can now use ArrayLists of type Runner with Collections.sort and also print each of the runners after sorting.
A Race class makes sense as it will allow some house keeping items related to that specific race such as the runners competing along with printing a leaderboard.
public class Race {
ArrayList<Runner> runners = new ArrayList<>();
public void addRunner(Runner runner){
runners.add(runner);
}
public void start(){
runners.forEach(runner -> runner.start());
}
public void printLeaderboard(){
Collections.sort(runners);
System.out.println();
System.out.println();
System.out.println();
System.out.println();
System.out.println("-------------------------------------------------------------");
runners.forEach(runner -> System.out.println(runner.toString()));
}
public boolean isRaceOver() {
int count = 0;
for (Runner runner : runners) {
if (runner.hasFinished == true){
count++;
}
}
if (count == runners.size()){
return true;
}
return false;
}
}
So an example of what Main() would look like.
public class Main {
public static void main(String[] args) throws InterruptedException {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ArrayList<Runner> runners = new ArrayList<>();
runners.add(new Runner("Bolt", "Usain"));
runners.add(new Runner("GATLIN", "Justin"));
runners.add(new Runner("DE GRASSE", "Andre"));
runners.add(new Runner("BLAKE", "Yohan"));
runners.add(new Runner("SIMBINE", "Akani"));
runners.add(new Runner("MEITE", "Ben Youssef"));
runners.add(new Runner("VICAUT", "Jimmy"));
runners.add(new Runner("BROMWELL", "Trayvon"));
Race race1 = new Race();
runners.forEach(runner -> race1.addRunner(runner));
race1.start();
while (!race1.isRaceOver()){
Thread.sleep(500);
race1.printLeaderboard();
}
System.out.println("Total Run time: " + (Double.valueOf(TimeUnit.NANOSECONDS.toMillis(stopWatch.getCurrentTime())))/1000);
}
}
I am doing this exercise:
Generate 1,000 threads, each of which increments a counter
100,000 times. Compare the performance of using AtomicLong
versus LongAdder.
And the following is my implementation:
import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class AtomicLongVsLongAddr {
// 9. Generate 1,000 threads, each of which increments a counter
// 100,000 times. Compare the performance of using AtomicLong
// versus LongAdder.
AtomicLong al = new AtomicLong(0);
LongAdder la = new LongAdder();
public class AtomicLongThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
al.incrementAndGet();
}
}
}
public class LongAdderThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
la.increment();
}
}
}
public static void main(String[] args) {
AtomicLongVsLongAddr vs = new AtomicLongVsLongAddr();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
(vs.new AtomicLongThread()).start();
}
long endTime = System.currentTimeMillis();
System.out.printf("AtomicLong--Number: %s, Time: %d\n", vs.al, endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
(vs.new LongAdderThread()).start();
}
long res = vs.la.sum();
endTime = System.currentTimeMillis();
System.out.printf("LongAdder--Number: %s, Time: %d\n", res, endTime - startTime);
}
}
I got something like the following as the standard output every time I run this program:
AtomicLong--Number: 100000000, Time: 2330
LongAdder--Number: 99882179, Time: 469
Apparently I've got a wrong value with LongAdder, but I can not figure out where I did wrong.
Can you help me?
updated
Under the help of everybody here and #Ravindra Ranwala, I updated my answer for the exercise above:
import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class AtomicLongVsLongAddr {
// 9. Generate 1,000 threads, each of which increments a counter
// 100,000 times. Compare the performance of using AtomicLong
// versus LongAdder.
AtomicLong al = new AtomicLong(0);
LongAdder la = new LongAdder();
public class AtomicLongThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
al.incrementAndGet();
}
}
}
public class LongAdderThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
la.increment();
}
}
}
public static void main(String[] args) {
try{
long startTime;
long endTime;
AtomicLongVsLongAddr vs = new AtomicLongVsLongAddr();
Thread[] t = new Thread[1000];
for (int i = 0; i < 1000; i ++) {
t[i] = vs.new AtomicLongThread();
}
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
t[i].start();
t[i].join();
}
endTime = System.currentTimeMillis();
System.out.printf("AtomicLong--Number: %s, Time: %d\n", vs.al, endTime - startTime);
for (int i = 0; i < 1000; i ++) {
t[i] = vs.new LongAdderThread();
}
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
t[i].start();
t[i].join();
}
long res = vs.la.sum();
endTime = System.currentTimeMillis();
System.out.printf("LongAdder--Number: %s, Time: %d\n", res, endTime - startTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}
If there still are any wrong, please point it out for me. Thanks everyone.
Call Thread.join on all the threads and wait till all of them are completed. It seems your main thread exits before other threads that increment the two variables completed. What you are getting here is some intermediary result.
Here's the code,
public static void main(String[] args) throws InterruptedException {
final List<Thread> adderThreads = new ArrayList<>();
final List<Thread> atomicThreads = new ArrayList<>();
AtomicLongVsLongAddr vs = new AtomicLongVsLongAddr();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
final AtomicLongThread atomicThread = vs.new AtomicLongThread();
atomicThreads.add(atomicThread);
atomicThread.start();
}
for (Thread thread : atomicThreads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.printf("AtomicLong--Number: %s, Time: %d\n", vs.al, endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
final LongAdderThread adderThread = vs.new LongAdderThread();
adderThreads.add(adderThread);
adderThread.start();
}
for (Thread thread : adderThreads) {
thread.join();
}
long res = vs.la.sum();
endTime = System.currentTimeMillis();
System.out.printf("LongAdder--Number: %s, Time: %d\n", res, endTime - startTime);
}
Your code isn't synchronous - The main thread will exit/proceed before it's finished with the counter threads, thus creating the difference.
I'm trying to record the elapsed time for my method in milliseconds. Could someone tell me what I'm doing wrong?
public static void main(String[] args)
{
double pi = computePi(10000);
System.out.println(pi);
System.out.println(startTime - endTime);
}
long startTime = System.currentTimeMillis();
public static double computePi(int count)
{
double pi = 0;
for(int i = 0; i < count; i++)
{
pi += Math.pow(-1,i)/(2*i+1);
long endTime = System.currentTimeMillis();
}
return pi * 4;
return startTime - endTime;
}
}
The computation should be just before and after the method call. It should be endTime-startTime.
public static void main(String[] args)
{
long startTime = System.currentTimeMillis();
double pi = computePi(10000);
long endTime = System.currentTimeMillis();
System.out.println(pi);
System.out.println(endTime- startTime);
}
This code works fine:
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
long index = 0;
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime) {
break;
}
index++;
}
System.out.println(index + " loops in one minute.");
}
}
But then, I tried rewriting it into a for loop, and it gets stuck in an infinite loop.
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
int i = 0;
for (long now = 0; now < endTime; i++) {
Math.sqrt(i);
now = System.currentTimeMillis();
System.out.println("now" + now);
System.out.println("end" + endTime);
}
}
System.out.println(i+"calculations done in one minute");
}
Your second example is not an infinite loop, just wait 1 minute.
long endTime = startTime + 60000;
set the endTime to 60000 milliseconds in the future, that means 60 seconds, means 1 minute.
The standard output is just printing extremely fast.
Put a Thread.sleep(1000L) in the loop and you will see 61 statements being printed before it ends.
long endTime = 1378140843604L; // for example
for (long now = 0; now < endTime; i++) {
now = System.currentTimeMillis(); // will be 1378140783604, 1378140784604, 1378140785604 and so on
System.out.println("now" + now);
System.out.println("end" + endTime);
Thread.sleep(1000L);
}
This worked for me:
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
int i = 0;
for (long now = 0; now < endTime; i++) {
Math.sqrt(i);
now = System.currentTimeMillis();
System.out.println("now" + now);
System.out.println("end" + endTime);
}
System.out.println(i+"calculations done in one minute");
}
}
The only difference between mine an yours is where I put this: (yours is outside the main method)
System.out.println(i+"calculations done in one minute");
You should also be aware it take just microseconds to run through the loop so you're getting a huge output.
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();
}
}