/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.processor; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.concurrent.Future; import org.apache.camel.ContextTestSupport; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.processor.aggregate.AggregationStrategy; import org.apache.camel.util.StopWatch; public class SplitterParallelAggregateTest extends ContextTestSupport { // run this test manually as it takes some time to process, but shows that parallel aggregate can // be faster when enabled. private boolean enabled; @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { from("direct:splitSynchronizedAggregation") .split(method(new MySplitter(), "rowIterator"), new MyAggregationStrategy()) .to("log:someSplitProcessing?groupSize=500"); from("direct:splitUnsynchronizedAggregation") .split(method(new MySplitter(), "rowIterator"), new MyAggregationStrategy()).parallelAggregate() .to("log:someSplitProcessing?groupSize=500"); } }; } public void test1() throws Exception { if (!enabled) { return; } int numberOfRequests = 1; timeSplitRoutes(numberOfRequests); } public void test2() throws Exception { if (!enabled) { return; } int numberOfRequests = 2; timeSplitRoutes(numberOfRequests); } public void test4() throws Exception { if (!enabled) { return; } int numberOfRequests = 4; timeSplitRoutes(numberOfRequests); } protected void timeSplitRoutes(int numberOfRequests) throws Exception { String[] endpoints = new String[]{"direct:splitSynchronizedAggregation", "direct:splitUnsynchronizedAggregation"}; List<Future<File>> futures = new ArrayList<Future<File>>(); StopWatch stopWatch = new StopWatch(false); for (String endpoint : endpoints) { stopWatch.restart(); for (int requestIndex = 0; requestIndex < numberOfRequests; requestIndex++) { futures.add(template.asyncRequestBody(endpoint, null, File.class)); } for (int i = 0; i < futures.size(); i++) { Future<File> future = futures.get(i); future.get(); } stopWatch.stop(); log.info(String.format("test%d.%s=%d\n", numberOfRequests, endpoint, stopWatch.taken())); } } public static class MySplitter { public Iterator<String[]> rowIterator() { // we would normally be reading a large file but for this test, // we'll just manufacture a bunch of string // arrays LinkedList<String[]> rows = new LinkedList<String[]>(); String[] row; for (int i = 0; i < 10000; i++) { row = new String[10]; for (int j = 0; j < row.length; j++) { row[j] = String.valueOf(System.nanoTime()); } rows.add(row); } return rows.iterator(); } } public static class MyAggregationStrategy implements AggregationStrategy { @Override public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { // emulate some processing Random random = new Random(System.currentTimeMillis()); for (int i = 0; i < 10000; i++) { random.nextGaussian(); } return newExchange; } } }