/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.communication.management.internal; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.communication.api.CommunicationService; import de.rcenvironment.core.communication.common.InstanceNodeSessionId; import de.rcenvironment.core.communication.management.BenchmarkSetup; import de.rcenvironment.core.communication.management.RemoteBenchmarkService; import de.rcenvironment.core.toolkitbridge.transitional.ConcurrencyUtils; import de.rcenvironment.core.utils.common.rpc.RemoteOperationException; import de.rcenvironment.core.utils.common.textstream.TextOutputReceiver; import de.rcenvironment.toolkit.modules.concurrency.api.TaskDescription; /** * A {@link Runnable} that performs a communication layer benchmark. * * @author Robert Mischke */ public class BenchmarkProcess implements Runnable { // private static final int STATUS_OUTPUT_INTERVAL_MSEC = 5000; private final Log log = LogFactory.getLog(getClass()); /** * A {@link Runnable} that acts as a single-threaded sender within a benchmark. * * @author Robert Mischke */ private final class SenderTask implements Runnable { private InstanceNodeSessionId targetNode; private AtomicInteger messageCounter; private BenchmarkSubtaskImpl subtask; private RemoteBenchmarkService remoteService; SenderTask(BenchmarkSubtaskImpl subtask, InstanceNodeSessionId nodeId, AtomicInteger messageCounter) { this.targetNode = nodeId; this.messageCounter = messageCounter; this.subtask = subtask; this.remoteService = communicationService.getRemotableService(RemoteBenchmarkService.class, targetNode); } @Override @TaskDescription("Communication Layer: benchmark sender task") public void run() { // this ensures that all threads perform the predefined number of requests while (messageCounter.decrementAndGet() >= 0) { long startTime = System.nanoTime(); RemoteOperationException error = null; try { performRequest(); } catch (RemoteOperationException e) { // optional logging of connection errors is left to the calling code error = e; } long duration = System.nanoTime() - startTime; subtask.recordSingleResult(targetNode, duration, error); } } private void performRequest() throws RemoteOperationException { Serializable response = remoteService.respond(new byte[subtask.getRequestSize()], subtask.getResponseSize(), subtask.getResponseDelay()); // basic verification of response: is the payload a byte array of expected size? byte[] responseBytes = (byte[]) response; if (responseBytes == null || responseBytes.length != subtask.getResponseSize()) { throw new IllegalStateException("Unexpected benchmark response payload"); } } } private List<BenchmarkSubtaskImpl> subtasks; private TextOutputReceiver outputReceiver; private CommunicationService communicationService; @SuppressWarnings("unchecked") public BenchmarkProcess(BenchmarkSetup setup, TextOutputReceiver outputReceiver, CommunicationService communicationService) { this.subtasks = new ArrayList<BenchmarkSubtaskImpl>(); // cast to expected BenchmarkSubtask implementation; rework if necessary subtasks.addAll((Collection<? extends BenchmarkSubtaskImpl>) setup.getSubtasks()); this.communicationService = communicationService; this.outputReceiver = outputReceiver; } @Override @TaskDescription("Communication Layer: benchmark main task") public void run() { outputReceiver.onStart(); // initialize and start printOutput("Starting " + subtasks.size() + " benchmark task(s)"); int index = 1; for (BenchmarkSubtaskImpl subtask : subtasks) { printOutput(" Task " + (index++) + ": " + subtask.formatDescription()); subtask.recordStartTime(); for (InstanceNodeSessionId nodeId : subtask.getTargetNodes()) { AtomicInteger messageCounter = new AtomicInteger(subtask.getNumMessages()); for (int senderIndex = 0; senderIndex < subtask.getThreadsPerTarget(); senderIndex++) { SenderTask sender = new SenderTask(subtask, nodeId, messageCounter); ConcurrencyUtils.getAsyncTaskService().execute(sender); } } } // TODO spawn progress watcher thread // await completion printOutput("Awaiting benchmark results..."); for (BenchmarkSubtaskImpl subtask : subtasks) { try { subtask.awaitTermination(); } catch (InterruptedException e) { log.warn("Benchmark subtask interrupted", e); outputReceiver.onFatalError(e); } } // print results printOutput("Benchmark results:"); index = 1; for (BenchmarkSubtaskImpl subtask : subtasks) { printOutput(" Task " + (index++) + ": " + subtask.formatDescription()); for (String line : subtask.formatResults()) { printOutput(" " + line); } } outputReceiver.onFinished(); } /** * Sends a line of output to the configured receiver. * * @param line the output line */ private void printOutput(String line) { outputReceiver.addOutput(line); } }