Skip to content

Commit

Permalink
initial commit of test application
Browse files Browse the repository at this point in the history
  • Loading branch information
epickrram committed Jun 1, 2015
1 parent 22c867e commit b2d3f94
Show file tree
Hide file tree
Showing 26 changed files with 1,717 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
@@ -0,0 +1,7 @@
perf-workshop.iws
perf-workshop.ipr
perf-workshop.iml

out/
build/
gradle/
5 changes: 5 additions & 0 deletions README.md
@@ -0,0 +1,5 @@
System Jitter Utility
=====================

A test program for determining causes of jitter.

116 changes: 116 additions & 0 deletions build.gradle
@@ -0,0 +1,116 @@
/*
* Copyright 2015 LMAX Ltd
*
* 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.
*/
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'eclipse'
apply plugin: 'checkstyle'

defaultTasks 'checkstyleMain', 'checkstyleTest', 'build'

version = new Version(major: 0, revision: 1)

ext {
fullName = 'Perf Workshop'
fullDescription = 'Perf Workshop example code'
teamName = ''
siteUrl = 'http://lmax.com'
sourceUrl = ''

javaCompilerExecutable = System.env['JAVA_HOME'] ? System.env['JAVA_HOME'] + '/bin/javac' : 'javac'
}

sourceSets {
main {
java {
srcDir 'src/main/java'
}
}

test {
java {
srcDir 'src/test/java'
}
resources {
srcDir 'src/test/resources'
}
}
}

repositories {
mavenCentral()
}

dependencies {
compile 'com.lmax:disruptor:3.3.2', 'org.hdrhistogram:HdrHistogram:2.1.4', 'com.google.code.gson:gson:2.3.1', 'com.beust:jcommander:1.48', 'com.higherfrequencytrading:affinity:1.7'

}

sourceCompatibility = 1.8
targetCompatibility = 1.8

jar {
baseName = project.name

manifest.attributes('Built-By': System.properties['user.name'],
'Bundle-Name': fullName,
'Bundle-Vendor': teamName,
'Bundle-Description': fullDescription,
'Bundle-DocURL': siteUrl)
}

task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}


artifacts {
archives sourcesJar, javadocJar
}

checkstyle {
toolVersion = "6.3"
}

task wrapper(type: Wrapper) {
gradleVersion = '2.2'
}

class Version {
int major, minor = 0, revision = 0
boolean snapshot
String stage

String toString() {
"$major.$minor.$revision${stage ? '.' + stage : ''}${snapshot ? '-SNAPSHOT' : ''}"
}
}

164 changes: 164 additions & 0 deletions gradlew
@@ -0,0 +1,164 @@
#!/usr/bin/env bash

##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
echo "$*"
}

die ( ) {
echo
echo "$*"
echo
exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option

if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
1 change: 1 addition & 0 deletions settings.gradle
@@ -0,0 +1 @@
rootProject.name = 'perf-workshop'
91 changes: 91 additions & 0 deletions src/main/java/com/epickrram/workshop/perf/app/AppMain.java
@@ -0,0 +1,91 @@
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.config.CommandLineArgs;
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.Overrides;
import com.epickrram.workshop.perf.support.Threads;
import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.TimeoutException;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.HdrHistogram.Histogram;

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 BusySpinWaitStrategy());

final Histogram[] histograms = new Histogram[commandLineArgs.getNumberOfIterations()];
setAll(histograms, HISTOGRAMS::createHistogramForArray);
final Journaller journaller = new Journaller(SYSTEM_NANO_TIMER, commandLineArgs);
journaller.init();

final Overrides overrides = new Overrides(commandLineArgs);
overrides.init();

packetDisruptor.handleEventsWith(
runOnCpus(wrap(new Accumulator(histograms, SYSTEM_NANO_TIMER, commandLineArgs)::process),
overrides.getAccumulatorThreadAffinity()),
runOnCpus(wrap(journaller::process), overrides.getJournallerThreadAffinity()));

packetDisruptor.start();

final InputReader inputReader = new InputReader(packetDisruptor.getRingBuffer(), SYSTEM_NANO_TIMER, commandLineArgs);

final Thread thread = DAEMON_THREAD_FACTORY.newThread(THREADS.runOnCpu(inputReader::processFiles,
overrides.getProducerThreadAffinity()));
thread.start();

try
{
thread.join();
packetDisruptor.shutdown(1, TimeUnit.MINUTES);
}
catch (TimeoutException e)
{
throw new RuntimeException("Consumers did not process remaining events within timeout", e);
}
finally
{
packetDisruptor.halt();
}
}
}

0 comments on commit b2d3f94

Please sign in to comment.