package com.epickrram.workshop.perf.app;
//////////////////////////////////////////////////////////////////////////////////
// Copyright 2015 Mark Price mark at epickrram.com //
// //
// 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. //
//////////////////////////////////////////////////////////////////////////////////
import com.beust.jcommander.JCommander;
import com.epickrram.workshop.perf.app.jitter.Spinners;
import com.epickrram.workshop.perf.app.message.Packet;
import com.epickrram.workshop.perf.app.processors.Accumulator;
import com.epickrram.workshop.perf.app.processors.InputReader;
import com.epickrram.workshop.perf.app.processors.Journaller;
import com.epickrram.workshop.perf.config.CommandLineArgs;
import com.epickrram.workshop.perf.config.Overrides;
import com.epickrram.workshop.perf.support.SpinLoopHintBusySpinWaitStrategy;
import com.lmax.disruptor.TimeoutException;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.HdrHistogram.Histogram;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import static com.epickrram.workshop.perf.app.processors.EventHandlerAdapter.wrap;
import static com.epickrram.workshop.perf.app.processors.ThreadAffinityEventHandler.runOnCpus;
import static com.epickrram.workshop.perf.support.DaemonThreadFactory.DAEMON_THREAD_FACTORY;
import static com.epickrram.workshop.perf.support.Histograms.HISTOGRAMS;
import static com.epickrram.workshop.perf.support.SystemNanoTimer.SYSTEM_NANO_TIMER;
import static com.epickrram.workshop.perf.support.Threads.THREADS;
import static java.util.Arrays.setAll;
import static java.util.concurrent.Executors.newCachedThreadPool;
public final class AppMain
{
public static void main(final String[] args) throws Exception
{
final CommandLineArgs commandLineArgs = new CommandLineArgs();
new JCommander(commandLineArgs).parse(args);
final Disruptor<Packet> packetDisruptor =
new Disruptor<>(new Packet.Factory(commandLineArgs.getRecordLength()), commandLineArgs.getBufferSize(),
newCachedThreadPool(DAEMON_THREAD_FACTORY), ProducerType.SINGLE, new SpinLoopHintBusySpinWaitStrategy());
final Overrides overrides = new Overrides(commandLineArgs);
overrides.init();
final Journaller journaller = new Journaller(SYSTEM_NANO_TIMER, commandLineArgs, overrides.enableJournaller());
journaller.init();
final Histogram[] messageTransitTimeHistograms = new Histogram[commandLineArgs.getNumberOfIterations()];
setAll(messageTransitTimeHistograms, HISTOGRAMS::createHistogramForArray);
final Histogram[] interMessageTimeHistograms = new Histogram[commandLineArgs.getNumberOfIterations()];
setAll(interMessageTimeHistograms, HISTOGRAMS::createHistogramForArray);
packetDisruptor.handleEventsWith(
runOnCpus(wrap(new Accumulator(messageTransitTimeHistograms, interMessageTimeHistograms, SYSTEM_NANO_TIMER, commandLineArgs)::process),
"Accumulator", overrides.getAccumulatorThreadAffinity()),
runOnCpus(wrap(journaller::process), "Journaller", overrides.getJournallerThreadAffinity()));
packetDisruptor.start();
final InputReader inputReader = new InputReader(packetDisruptor.getRingBuffer(), SYSTEM_NANO_TIMER, commandLineArgs);
if(commandLineArgs.runSpinners())
{
System.out.println("Starting spinner threads to perturb the system");
Spinners.SPINNERS.start();
}
System.out.println("Starting replay at " + new Date());
final Thread thread = DAEMON_THREAD_FACTORY.newThread(THREADS.runOnCpu(inputReader::processFiles,
overrides.getProducerThreadAffinity()));
thread.start();
try
{
thread.join();
System.out.println("Finished replay at " + new Date());
packetDisruptor.shutdown(1, TimeUnit.MINUTES);
}
catch (TimeoutException e)
{
throw new RuntimeException("Consumers did not process remaining events within timeout", e);
}
finally
{
Spinners.SPINNERS.stop();
packetDisruptor.halt();
}
System.out.println("Pausing for 10 seconds...");
THREADS.sleep(10L, TimeUnit.SECONDS);
}
}