/* * Copyright 2014, The Sporting Exchange Limited * * Licensed 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 com.betfair.cougar.perf.socket; import com.betfair.cougar.api.ExecutionContext; import com.betfair.cougar.api.ExecutionContextImpl; import com.betfair.cougar.api.geolocation.GeoLocationDetails; import com.betfair.cougar.core.api.ev.ConnectedResponse; import com.betfair.cougar.core.impl.CougarSpringCtxFactoryImpl; import com.betfair.platform.virtualheap.Heap; import com.betfair.platform.virtualheap.HeapListener; import com.betfair.platform.virtualheap.updates.UpdateBlock; import com.betfair.cougar.perf.socket.v1_0.SocketPerfTestingSyncClient; import com.betfair.cougar.perf.socket.v1_0.co.RpcControlCO; import com.betfair.cougar.perf.socket.v1_0.co.client.RpcControlClientCO; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicLong; /** */ public class RpcMain { private static List<TestRunner> runners; private static long startMillis; private static String name; public static void main(String[] args) throws InterruptedException { if (args.length < 2) { System.err.println("Usage: RpcMain <client-name> <target host:port> [<clientExecutorPoolSize>]"); System.exit(1); } name = args[0]; String targetAddress = args[1]; if (args.length > 2) { System.setProperty("cougar.client.socket.clientExecutor.maximumPoolSize", args[2]); } System.setProperty("server.address", targetAddress); CougarSpringCtxFactoryImpl cougarSpringCtxFactory = new CougarSpringCtxFactoryImpl(); ClassPathXmlApplicationContext context = cougarSpringCtxFactory.create(); final SocketPerfTestingSyncClient client = (SocketPerfTestingSyncClient) context.getBean("perfTestClient"); final ExecutionContextImpl ctx = new ExecutionContextImpl(); ctx.setGeoLocationDetails(new GeoLocationDetails() { @Override public String getRemoteAddr() { return "127.0.0.1"; } @Override public List<String> getResolvedAddresses() { return Collections.singletonList("127.0.0.1"); } @Override public String getCountry() { return "GB"; } @Override public boolean isLowConfidenceGeoLocation() { return false; } @Override public String getLocation() { return "Somewhere over the rainbow"; } @Override public String getInferredCountry() { return "GB"; } }); ConnectedResponse rpcControlResponse = client.getRpcControl(ctx); Heap rpcControlHeap = rpcControlResponse.getHeap(); final RpcControlCO rpcControl = RpcControlClientCO.rootFrom(rpcControlHeap); rpcControlHeap.addListener(new HeapListener() { @Override public void applyUpdate(UpdateBlock update) { if (rpcControl.getRunning()) { startTest(rpcControl.getNumThreads(), client, ctx); } else { stopTest(); } } }, true); System.out.println("["+name+"]: READY"); } private static void startTest(Integer integer, SocketPerfTestingSyncClient client, ExecutionContextImpl ctx) { startMillis = System.currentTimeMillis(); runners = new ArrayList<TestRunner>(); for (int i=0; i<integer; i++) { TestRunner tr = new TestRunner(client, ctx); runners.add(tr); Thread t = new Thread(tr); t.start(); } System.out.println("["+name+"]: STARTED AT "+startMillis); } private static void stopTest() { // if it's null then we haven't started yet.. if (runners != null) { long totalCalls = 0; for (TestRunner runner : runners) { totalCalls += runner.stop(); } long endMillis = System.currentTimeMillis(); long totalMillis = endMillis-startMillis; double meanCallsPerSecPerThread = ((double) (totalCalls/(totalMillis/1000))) / runners.size(); double meanLatency = 1000 / meanCallsPerSecPerThread; System.out.println("["+name+"]: COMPLETED AT "+endMillis+" TOOK "+totalMillis+"ms @ "+(totalCalls/(totalMillis/1000))+" tps and "+meanLatency+" ms/call"); } } private static class TestRunner implements Runnable { private SocketPerfTestingSyncClient client; private boolean running = true; private ExecutionContext context; private AtomicLong counter = new AtomicLong(); public TestRunner(SocketPerfTestingSyncClient client, ExecutionContext context) { this.client = client; this.context = context; } @Override public void run() { while (running) { client.noop(context); counter.incrementAndGet(); } } public long stop() { running = false; return counter.get(); } } }