Browse Source

Added Pronghorn server (#2972)

Chris Turner 8 years ago
parent
commit
afd8782678

+ 1 - 0
.travis.yml

@@ -116,6 +116,7 @@ env:
     - "TESTDIR=JavaScript/sailsjs"
     - "TESTDIR=Kotlin/hexagon"
     - "TESTDIR=Kotlin/ktor"
+    - "TESTDIR=Kotlin/pronghorn"
     - "TESTDIR=Lua/lapis"
     - "TESTDIR=Lua/octopus"
     - "TESTDIR=Lua/openresty"

+ 2 - 0
frameworks/Kotlin/pronghorn/.gitignore

@@ -0,0 +1,2 @@
+.gradle
+build/

+ 30 - 0
frameworks/Kotlin/pronghorn/README.md

@@ -0,0 +1,30 @@
+# Pronghorn
+This is the [Pronghorn Http Server](https://www.pronghorn.tech) portion of the [TechEmpower Framework Benchmarks](https://github.com/TechEmpower/FrameworkBenchmarks). 
+
+## About
+The Pronghorn HTTP Server is a low-level, high performance HTTP server written in [Kotlin](https://kotlinlang.org/).
+
+### Version
+v0.1.0 : [https://github.com/pronghorn-tech/server/releases/tag/0.1.0](https://github.com/pronghorn-tech/server/releases/tag/0.1.0)
+
+## Test Types
+Currently only the plaintext and json tests are implemented.
+
+### Plaintext
+url : `http://TFB-server:8080/plaintext` 
+source code : [TestServer.kt](src/main/kotlin/pronghorn/TestServer.kt)
+
+### Json
+url : `http://TFB-server:8080/json`
+source code : [JsonHandler.kt](src/main/kotlin/pronghorn/JsonHandler.kt)
+
+## Additional Dependencies
+Pronghorn is by default a zero dependency library, but for the purpose of benchmarking these tests utilize three Pronghorn plugins for performance and logging :
+* [JCTools Collections Plugin](https://github.com/pronghorn-tech/plugin-collections-jctools) - performance
+* [OpenHFT Hashing Plugin](https://github.com/pronghorn-tech/plugin-hashing-openhft) - performance
+* [SLF4J Logging Plugin](https://github.com/pronghorn-tech/plugin-logging-slf4j) - logging
+
+In addition to the above plugins, the json test utilizes the [jsoniter](http://jsoniter.com/) library for the actual json implementation, as well as the [Javassist](http://jboss-javassist.github.io/javassist/) library for improved performance of jsoniter. 
+
+## Contact
+For additional information, help, or corrections concerning Pronghorn or these tests contact info [at] pronghorn.tech 

+ 25 - 0
frameworks/Kotlin/pronghorn/benchmark_config.json

@@ -0,0 +1,25 @@
+{
+  "framework": "pronghorn",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "None",
+      "language": "Kotlin",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "Pronghorn",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Pronghorn",
+      "notes": "",
+      "versus": ""
+    }
+  }]
+} 

+ 47 - 0
frameworks/Kotlin/pronghorn/build.gradle

@@ -0,0 +1,47 @@
+group 'pronghorn'
+version '0.1.0'
+
+buildscript {
+    ext {
+        pronghornVersion = '0.1.0'
+        kotlinVersion = '1.1.4'
+    }
+
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+    }
+}
+
+apply plugin: 'kotlin'
+apply plugin: 'application'
+
+mainClassName = "pronghorn.TestServerKt"
+
+repositories {
+    mavenCentral()
+}
+
+kotlin {
+    experimental {
+        coroutines 'enable'
+    }
+}
+
+dependencies {
+    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+    compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
+
+    runtime 'ch.qos.logback:logback-classic:1.2.3'
+
+    compile 'com.jsoniter:jsoniter:0.9.15'
+    compile 'org.javassist:javassist:3.21.0-GA'
+
+    compile "tech.pronghorn:server:$pronghornVersion"
+    compile "tech.pronghorn:plugin-collections-jctools:$pronghornVersion"
+    compile "tech.pronghorn:plugin-hashing-openhft:$pronghornVersion"
+    compile "tech.pronghorn:plugin-logging-slf4j:$pronghornVersion"
+}

BIN
frameworks/Kotlin/pronghorn/gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
frameworks/Kotlin/pronghorn/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Sat Sep 16 19:52:18 MDT 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

+ 164 - 0
frameworks/Kotlin/pronghorn/gradlew

@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# 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
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+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" -a "$nonstop" = "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"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # 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 "$@"

+ 90 - 0
frameworks/Kotlin/pronghorn/gradlew.bat

@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
frameworks/Kotlin/pronghorn/settings.gradle

@@ -0,0 +1 @@
+rootProject.name = 'pronghorn'

+ 5 - 0
frameworks/Kotlin/pronghorn/setup.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+fw_depends java
+
+./gradlew --no-daemon clean run

+ 2 - 0
frameworks/Kotlin/pronghorn/source_code

@@ -0,0 +1,2 @@
+./pronghorn/src/main/kotlin/pronghorn/TestServer.kt
+./pronghorn/src/main/kotlin/pronghorn/JsonHandler.kt

+ 33 - 0
frameworks/Kotlin/pronghorn/src/main/kotlin/pronghorn/JsonHandler.kt

@@ -0,0 +1,33 @@
+package pronghorn
+
+import com.jsoniter.output.EncodingMode
+import com.jsoniter.output.JsonStream
+import tech.pronghorn.http.*
+import tech.pronghorn.http.protocol.CommonContentTypes
+import tech.pronghorn.server.handlers.DirectHttpRequestHandler
+import java.io.ByteArrayOutputStream
+
+data class JsonExample(val message: String)
+
+class JsonHandler: DirectHttpRequestHandler() {
+    companion object {
+        init {
+            JsonStream.setMode(EncodingMode.DYNAMIC_MODE)
+        }
+    }
+
+    private val outputStream = ByteArrayOutputStream()
+    private val stream = JsonStream(outputStream, 32)
+
+    fun toJson(any: Any): ByteArray{
+        outputStream.reset()
+        stream.writeVal(any)
+        stream.flush()
+        return outputStream.toByteArray()
+    }
+
+    override fun handleDirect(exchange: HttpExchange): HttpResponse {
+        val example = JsonExample("Hello, World!")
+        return HttpResponses.OK(toJson(example), CommonContentTypes.ApplicationJson)
+    }
+}

+ 16 - 0
frameworks/Kotlin/pronghorn/src/main/kotlin/pronghorn/TestServer.kt

@@ -0,0 +1,16 @@
+package pronghorn
+
+import tech.pronghorn.http.HttpResponses
+import tech.pronghorn.http.protocol.CommonContentTypes
+import tech.pronghorn.server.HttpServer
+import tech.pronghorn.server.handlers.StaticHttpRequestHandler
+
+fun main(args: Array<String>) {
+    val helloWorldResponse = HttpResponses.OK("Hello, World!", CommonContentTypes.TextPlain)
+    val helloWorldHandler = StaticHttpRequestHandler(helloWorldResponse)
+
+    val server = HttpServer("0.0.0.0", 8080)
+    server.registerUrlHandler("/plaintext", helloWorldHandler)
+    server.registerUrlHandlerGenerator("/json", { JsonHandler() })
+    server.start()
+}

+ 10 - 0
frameworks/Kotlin/pronghorn/src/main/resources/logback.xml

@@ -0,0 +1,10 @@
+<configuration>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <root level="INFO">
+        <appender-ref ref="STDOUT"/>
+    </root>
+</configuration>

+ 6 - 0
frameworks/Kotlin/pronghorn/src/main/resources/pronghorn.properties

@@ -0,0 +1,6 @@
+pronghorn.plugins.LoggingPlugin       = tech.pronghorn.plugins.Slf4jLoggingPlugin
+pronghorn.plugins.SpscQueuePlugin     = tech.pronghorn.plugins.JCToolsSpscQueuePlugin
+pronghorn.plugins.MpscQueuePlugin     = tech.pronghorn.plugins.JCToolsMpscQueuePlugin
+pronghorn.plugins.ConcurrentMapPlugin = tech.pronghorn.plugins.JCToolsConcurrentMapPlugin
+pronghorn.plugins.ConcurrentSetPlugin = tech.pronghorn.plugins.JCToolsConcurrentSetPlugin
+pronghorn.plugins.ArrayHasherPlugin   = tech.pronghorn.plugins.OpenHFTArrayHasherPlugin