Skip to content

Example : Selecting the fastest algorithm result

johnmcclean-aol edited this page Jan 27, 2015 · 6 revisions

If we wanted to test the relative performance of algorithms that solve the same problem, we can setup multiple reactive dataflows, one for each algorithm and select the fastest.

E.g. To test relative retrieval of ArrayLists and LinkedLists

Step 1 - populate the Lists

   @Test
public void testFastest() throws InterruptedException, ExecutionException {

	ArrayList<Integer> arrayList = new ArrayList<>();
	LinkedList<Integer> linkedList = new LinkedList<>();
	for(int i=0;i<1001;i++){
		arrayList.add(i);
		linkedList.add(i);
	}
    }

Step 2 create a simple result class

We use Lombok for this type of thing, as it makes creating Immutable classes very straightforward and greatly cuts down boilerplate code.

@Wither        //adds 'withXXXX' methods that create a new instance with property XXXX changed
@Getter    //adds Java Bean getXXXX methods
@AllArgsConstructor   //adds a Constructor which accepts all fields
@Builder    //adds a builder class for this class
static class Result{
	private final String name;
	private final int result;
	private final long time;
	
}

The equivalent Java for this class is at the bottom of this example doc.

Step 3 Define a simple retrieval method that looks up the 1000th entry in a list

private int retrieval(List<Integer> list) {
	return list.get(1000);
}

Step 4 Setup a reactive flow with two suppliers - one for an ArrayList and one for the LinkedList

@Test
public void testFastest() throws InterruptedException, ExecutionException {

	ArrayList<Integer> arrayList = new ArrayList<>();
	LinkedList<Integer> linkedList = new LinkedList<>();
	for(int i=0;i<1001;i++){
		arrayList.add(i);
		linkedList.add(i);
	}
	
	
	Result result = new SimpleReact()
	.<Result> react( () -> Result.builder().name("approach1").result(retrieval(arrayList)).build(), 
			() -> Result.builder().name("approach2").result(retrieval(linkedList)).build())

}

Step 5 capture the time taken for each approach

 @Test
public void testFastest() throws InterruptedException, ExecutionException {

	ArrayList<Integer> arrayList = new ArrayList<>();
	LinkedList<Integer> linkedList = new LinkedList<>();
	for(int i=0;i<1001;i++){
		arrayList.add(i);
		linkedList.add(i);
	}
	SimpleTimer timer = new SimpleTimer();
	
	Result result = new SimpleReact()
	.<Result> react( () -> Result.builder().name("approach1").result(retrieval(arrayList)).build(), 
			() -> Result.builder().name("approach2").result(retrieval(linkedList)).build())
	.then(it -> it.withTime(timer.getElapsedNanoseconds()))

}

Step 6 ensure both answers are correct

 @Test
public void testFastest() throws InterruptedException, ExecutionException {

	ArrayList<Integer> arrayList = new ArrayList<>();
	LinkedList<Integer> linkedList = new LinkedList<>();
	for(int i=0;i<1001;i++){
		arrayList.add(i);
		linkedList.add(i);
	}
	SimpleTimer timer = new SimpleTimer();
	
	Result result = new SimpleReact()
	.<Result> react( () -> Result.builder().name("approach1").result(retrieval(arrayList)).build(), 
			() -> Result.builder().name("approach2").result(retrieval(linkedList)).build())
	.then(it -> it.withTime(timer.getElapsedNanoseconds()))
	.filter(it -> it.getResult()==1000

}

Step 7 select the first result returned and check the approach name

  @Test
public void testFastest() throws InterruptedException, ExecutionException {

	ArrayList<Integer> arrayList = new ArrayList<>();
	LinkedList<Integer> linkedList = new LinkedList<>();
	for(int i=0;i<1001;i++){
		arrayList.add(i);
		linkedList.add(i);
	}
	SimpleTimer timer = new SimpleTimer();
	
	Result result = new SimpleReact()
	.<Result> react( () -> Result.builder().name("approach1").result(retrieval(arrayList)).build(), 
			() -> Result.builder().name("approach2").result(retrieval(linkedList)).build())
	.then(it -> it.withTime(timer.getElapsedNanoseconds()))
	.filter(it -> it.getResult()==1000)
	.blockAndExtract(Extractors.first());

	
	assertThat(result.getName(),is("approach1"));
}		



private int retrieval(List<Integer> list) {
	return list.get(1000);
}



@Wither
@Getter
@AllArgsConstructor
@Builder
static class Result{
	private final String name;
	private final int result;
	private final long time;
	
}

Equivalent Raw Java and Lombok Java Results classes

Lombok Java

@Wither
@Getter
@AllArgsConstructor
@Builder
static class Result{
	private final String name;
	private final int result;
	private final long time;
	
}

Raw Java

  @Wither
@Getter
@AllArgsConstructor
@Builder
static class Result{
	private final String name;
	private final int result;
	private final long time;
	
}

static class JavaResult {

	private final String name;
	private final int result;
	private final long time;
	
	
	
	public JavaResult(String name, int result, long time) {
		super();
		this.name = name;
		this.result = result;
		this.time = time;
	}
	
	static class Builder{
		private String name;
		private int result;
		private long time;
		
		public Builder name(String name){
			this.name = name;
			return this;
		}
		
		public Builder time(long time){
			this.time = time;
			return this;
		}
		
		public Builder result(int result){
			this.result = result;
			return this;
		}
		
		public JavaResult build(){
			return new JavaResult(name,result,time);
		}
	}
	
	public String getName() {
		return name;
	}
	public int getResult() {
		return result;
	}
	public long getTime() {
		return time;
	}
	public JavaResult withName(String name) {
		return new JavaResult.Builder().name(name).result(result).time(time).build();
	}
	public JavaResult withResult(int result) {
		return new JavaResult.Builder().name(name).result(result).time(time).build();
	}
	public JavaResult getTime(long time) {
		return new JavaResult.Builder().name(name).result(result).time(time).build();
	}
	
	
	
}
Clone this wiki locally