Browse Source

OfficeFloor thread affinity (#4095)

* Plain text test implemented

* Providing a test class per Tech Empower test

* Providing abstract class for generic testing

* Adding JSON serialise test

* Initial work on Single Database Query test

* Single Database Query test written.

* Multiple Database Queries Test

* Added Fortunes test

* All tests 1-6 written

* Json Serialisation requires JsonResponseWriter to specify the
Content-Type header.

* Single Query passing tests

* Multiple database queries passing

* Initial work on Fortunes test

* Fortunes test passing

* Passing unit tests

* Providing connection pooling and not logging.

* Providing threading configuration for database interaction

* Fixing issues with Database Update Test

* Tests are passing

* Setup of OfficeFloor to run in TechEmpire environment.

* Including production data source file

* Tests passing

* Tests now running in Vagrant VM

* Cleaning up start now that working.

* Should not have empty directory

* Plain text test implemented

* Providing a test class per Tech Empower test

* Providing abstract class for generic testing

* Adding JSON serialise test

* Initial work on Single Database Query test

* Single Database Query test written.

* Multiple Database Queries Test

* Added Fortunes test

* All tests 1-6 written

* Json Serialisation requires JsonResponseWriter to specify the
Content-Type header.

* Single Query passing tests

* Multiple database queries passing

* Initial work on Fortunes test

* Fortunes test passing

* Passing unit tests

* Providing connection pooling and not logging.

* Providing threading configuration for database interaction

* Fixing issues with Database Update Test

* Tests are passing

* Setup of OfficeFloor to run in TechEmpire environment.

* Including production data source file

* Tests passing

* Tests now running in Vagrant VM

* Cleaning up start now that working.

* Should not have empty directory

* Passing latest rebase of FrameworkBenchmarks.

* Migrating to version 3.0.0

* Run own comparison with just top level frameworks

* Fix file name spelling

* Providing readme placeholder for OfficeFloor

* Fixing for TTY not available in Jenkins

* Removing OfficeFloor to run setup script

* Initial setup

* Initial project setup

* OfficeFloor implementation passing tests

* Building OfficeFloor

* Fixing path

* Raw OfficeFloor

* Specifying SourceForge repository for sourcing

* Passing build - new SQL fix

* Able to be called for verify for officefloor-raw

* Adding Server / Date headers

* Configuring Postgresql

* Threading access to multiple queries on database

* Running all tests

* Fixing tests to pass verification

* re-useable tests for different implementations

* Pooling Connections

* Adding micro tests

* Providing micro, netty and rapidoid implementations

* Providing throttle active request count value

* Fixing spelling causing failed run

* Initial work to attempt to cache for local runs

* Fixing to start postgres for micro

* Improving Updates and Fortunes performance

* Reducing possible contention in database for updates

* Providing raw with DB functionality

* Including additional raw tests

* Including database for raw

* Fixing logic

* Ready for submission

* Ready for submission

* Cleaning up based on Tech Empower feedback:

 - Removing tests
 - Removing source_files
 - Also bumping up to use Java 10

* Removing test resources

* Fixing netty / rapidoid builds

Simplified build process to only build the project.  However, netty and
rapidoid depend on the benchmark default project for the implementation
(and just change the HTTP server).  Therefore, installing benchmark
first to allow the dependency to be resolved.

* Fixing for not finding parent pom

* Reverting back to Java 8

Issue with running with Java 10.  Will run in Java 8 for time being and
work on resolving this issue when more time.

* Increasing time for checking server up

Travis seems to run many builds at the same time, and concerned that may
be starving for thread to check causing timeout...  and subsequently
causing false positives.

* Working with Java 10

* Allowing to run on different port

CI server running on 8080 (so unable to start in unit tests)

* Updating to 3.1.0

Also, avoiding memory resizing issues reducing performance.

* Register Afterburner

* Configuring for entity manager to use connection

* thread-per-request example

* Run in quiet mode so can see errors in travis logs

This should avoid filling build logs with download progress

* Using batch to show build

* Fix connection string

* quiet build

* Reducing connection pool sizes for improved performance

* Raw able to use async from pgsql2

* officefloor-raw passing fortunes test

* Raw using ADBA for PostgreSql

* Fixing to handle bounds check

* Providing error handling to not hold up query

* Providing Thread Affinity for Raw

* Specifying the team sizes

* Providing Thread Affinity server for comparison

* Upgrading driver version for PostgreSQL

Also, tidying up Java params for optimising

* Fixing docker build of thread affinity
Daniel 6 years ago
parent
commit
6e156f1298

+ 23 - 2
frameworks/Java/officefloor/benchmark_config.json

@@ -34,11 +34,9 @@
 				"framework": "OfficeFloor",
 				"framework": "OfficeFloor",
 				"language": "Java",
 				"language": "Java",
 				"flavor": "None",
 				"flavor": "None",
-				"orm": "raw",
 				"platform": "OfficeFloor",
 				"platform": "OfficeFloor",
 				"webserver": "WoOF",
 				"webserver": "WoOF",
 				"os": "Linux",
 				"os": "Linux",
-				"database_os": "Linux",
 				"display_name": "OfficeFloor-raw",
 				"display_name": "OfficeFloor-raw",
 				"notes": ""
 				"notes": ""
 			},
 			},
@@ -88,6 +86,29 @@
 				"notes": "",
 				"notes": "",
 				"versus": "OfficeFloor-raw"
 				"versus": "OfficeFloor-raw"
 			},
 			},
+			"thread_affinity": {
+				"json_url": "/json",
+				"plaintext_url": "/plaintext",
+				"db_url": "/db",
+				"query_url": "/queries?queries=",
+				"fortune_url": "/fortunes",
+				"update_url": "/update?queries=",
+				"port": 8080,
+				"approach": "Realistic",
+				"classification": "Fullstack",
+				"database": "Postgres",
+				"framework": "OfficeFloor",
+				"language": "Java",
+				"flavor": "None",
+				"orm": "raw",
+				"platform": "OfficeFloor",
+				"webserver": "WoOF",
+				"os": "Linux",
+				"database_os": "Linux",
+				"display_name": "OfficeFloor-micro",
+				"notes": "",
+				"versus": "OfficeFloor-raw"
+			},
 			"netty": {
 			"netty": {
 				"json_url": "/json",
 				"json_url": "/json",
 				"plaintext_url": "/plaintext",
 				"plaintext_url": "/plaintext",

+ 1 - 1
frameworks/Java/officefloor/officefloor-micro.dockerfile

@@ -7,4 +7,4 @@ RUN mvn -q clean package
 FROM openjdk:10
 FROM openjdk:10
 WORKDIR /officefloor
 WORKDIR /officefloor
 COPY --from=maven /officefloor/src/woof_micro/target/woof_micro-1.0.0.jar server.jar
 COPY --from=maven /officefloor/src/woof_micro/target/woof_micro-1.0.0.jar server.jar
-CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 1 - 1
frameworks/Java/officefloor/officefloor-netty.dockerfile

@@ -11,4 +11,4 @@ RUN mvn -q clean package
 FROM openjdk:10
 FROM openjdk:10
 WORKDIR /officefloor
 WORKDIR /officefloor
 COPY --from=maven /officefloor/src/woof_netty/target/woof_netty-1.0.0.jar server.jar
 COPY --from=maven /officefloor/src/woof_netty/target/woof_netty-1.0.0.jar server.jar
-CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 1 - 1
frameworks/Java/officefloor/officefloor-rapidoid.dockerfile

@@ -11,4 +11,4 @@ RUN mvn -q clean package
 FROM openjdk:10
 FROM openjdk:10
 WORKDIR /officefloor
 WORKDIR /officefloor
 COPY --from=maven /officefloor/src/woof_rapidoid/target/woof_rapidoid-1.0.0.jar server.jar
 COPY --from=maven /officefloor/src/woof_rapidoid/target/woof_rapidoid-1.0.0.jar server.jar
-CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 2 - 1
frameworks/Java/officefloor/officefloor-raw.dockerfile

@@ -5,6 +5,7 @@ WORKDIR /officefloor/src/woof_raw
 RUN mvn -q clean package
 RUN mvn -q clean package
 
 
 FROM openjdk:10
 FROM openjdk:10
+RUN apt-get update && apt-get install -y libjna-java
 WORKDIR /officefloor
 WORKDIR /officefloor
 COPY --from=maven /officefloor/src/woof_raw/target/woof_raw-1.0.0.jar server.jar
 COPY --from=maven /officefloor/src/woof_raw/target/woof_raw-1.0.0.jar server.jar
-CMD ["java", "-Xms2g", "-Xmx2g", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-jar", "server.jar"]
+CMD ["java", "-Xms2g", "-Xmx2g", "-server", "-XX:+UseNUMA", "-jar", "server.jar"]

+ 15 - 0
frameworks/Java/officefloor/officefloor-thread_affinity.dockerfile

@@ -0,0 +1,15 @@
+FROM maven:3.5.4-jdk-10 as maven
+WORKDIR /officefloor
+COPY src src
+WORKDIR /officefloor/src
+RUN mvn -q -N clean install
+WORKDIR /officefloor/src/woof_micro
+RUN mvn -q clean install
+WORKDIR /officefloor/src/woof_thread_affinity
+RUN mvn -q clean package
+
+FROM openjdk:10
+RUN apt-get update && apt-get install -y libjna-java
+WORKDIR /officefloor
+COPY --from=maven /officefloor/src/woof_thread_affinity/target/woof_thread_affinity-1.0.0.jar server.jar
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 1 - 1
frameworks/Java/officefloor/officefloor-tpr.dockerfile

@@ -7,4 +7,4 @@ RUN mvn -q clean package
 FROM openjdk:10
 FROM openjdk:10
 WORKDIR /officefloor
 WORKDIR /officefloor
 COPY --from=maven /officefloor/src/woof_tpr/target/woof_tpr-1.0.0.jar server.jar
 COPY --from=maven /officefloor/src/woof_tpr/target/woof_tpr-1.0.0.jar server.jar
-CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 1 - 1
frameworks/Java/officefloor/officefloor.dockerfile

@@ -7,4 +7,4 @@ RUN mvn -q clean package
 FROM openjdk:10
 FROM openjdk:10
 WORKDIR /officefloor
 WORKDIR /officefloor
 COPY --from=maven /officefloor/src/woof_benchmark/target/woof_benchmark-1.0.0.jar server.jar
 COPY --from=maven /officefloor/src/woof_benchmark/target/woof_benchmark-1.0.0.jar server.jar
-CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]
+CMD ["java", "-server", "-Xms2g", "-Xmx2g", "-XX:+UseNUMA", "-Dhttp.port=8080", "-Dhttp.server.name=OF", "-Dhttp.date.header=true", "-jar", "server.jar"]

+ 12 - 1
frameworks/Java/officefloor/src/pom.xml

@@ -18,6 +18,7 @@
 		<module>woof_benchmark</module>
 		<module>woof_benchmark</module>
 		<module>woof_tpr</module>
 		<module>woof_tpr</module>
 		<module>woof_micro</module>
 		<module>woof_micro</module>
+		<module>woof_thread_affinity</module>
 		<module>woof_raw</module>
 		<module>woof_raw</module>
 		<module>woof_netty</module>
 		<module>woof_netty</module>
 		<module>woof_rapidoid</module>
 		<module>woof_rapidoid</module>
@@ -46,6 +47,11 @@
 				<artifactId>officeserver_rapidoid</artifactId>
 				<artifactId>officeserver_rapidoid</artifactId>
 				<version>${officefloor.version}</version>
 				<version>${officefloor.version}</version>
 			</dependency>
 			</dependency>
+			<dependency>
+				<groupId>net.officefloor.web</groupId>
+				<artifactId>officeweb_executive</artifactId>
+				<version>${officefloor.version}</version>
+			</dependency>
 			<dependency>
 			<dependency>
 				<groupId>net.officefloor.web</groupId>
 				<groupId>net.officefloor.web</groupId>
 				<artifactId>officejson_jackson</artifactId>
 				<artifactId>officejson_jackson</artifactId>
@@ -114,7 +120,7 @@
 			<dependency>
 			<dependency>
 				<groupId>org.postgresql</groupId>
 				<groupId>org.postgresql</groupId>
 				<artifactId>postgresql</artifactId>
 				<artifactId>postgresql</artifactId>
-				<version>42.2.2</version>
+				<version>42.2.5</version>
 			</dependency>
 			</dependency>
 			<dependency>
 			<dependency>
 				<groupId>com.zaxxer</groupId>
 				<groupId>com.zaxxer</groupId>
@@ -131,6 +137,11 @@
 				<artifactId>woof_benchmark</artifactId>
 				<artifactId>woof_benchmark</artifactId>
 				<version>${project.version}</version>
 				<version>${project.version}</version>
 			</dependency>
 			</dependency>
+			<dependency>
+				<groupId>net.officefloor.benchmarks</groupId>
+				<artifactId>woof_micro</artifactId>
+				<version>${project.version}</version>
+			</dependency>
 		</dependencies>
 		</dependencies>
 	</dependencyManagement>
 	</dependencyManagement>
 	<build>
 	<build>

+ 1 - 1
frameworks/Java/officefloor/src/woof_benchmark/src/main/resources/application.teams

@@ -1,6 +1,6 @@
 <teams>
 <teams>
 
 
-	<team source="net.officefloor.frame.impl.spi.team.ExecutorFixedTeamSource" type="java.sql.Connection">
+	<team size="56" source="net.officefloor.frame.impl.spi.team.ExecutorFixedTeamSource" type="java.sql.Connection">
 		<property name="team.size" value="28" />
 		<property name="team.size" value="28" />
 	</team>
 	</team>
 
 

+ 1 - 1
frameworks/Java/officefloor/src/woof_micro/src/main/resources/application.teams

@@ -1,6 +1,6 @@
 <teams>
 <teams>
 
 
-	<team source="net.officefloor.frame.impl.spi.team.ExecutorFixedTeamSource" type="java.sql.Connection">
+	<team size="56" source="net.officefloor.frame.impl.spi.team.ExecutorFixedTeamSource" type="java.sql.Connection">
 		<property name="team.size" value="28" />
 		<property name="team.size" value="28" />
 	</team>
 	</team>
 
 

+ 6 - 1
frameworks/Java/officefloor/src/woof_raw/pom.xml

@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 	<parent>
@@ -21,6 +22,10 @@
 			<groupId>com.fasterxml.jackson.module</groupId>
 			<groupId>com.fasterxml.jackson.module</groupId>
 			<artifactId>jackson-module-afterburner</artifactId>
 			<artifactId>jackson-module-afterburner</artifactId>
 		</dependency>
 		</dependency>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>officeweb_executive</artifactId>
+		</dependency>
 		<dependency>
 		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>
 			<artifactId>lombok</artifactId>

+ 32 - 12
frameworks/Java/officefloor/src/woof_raw/src/main/java/net/officefloor/benchmark/RawOfficeFloorMain.java

@@ -24,16 +24,17 @@ import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;
 import java.util.Timer;
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.TimerTask;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
 
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
 import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
 
 
 import lombok.Data;
 import lombok.Data;
+import net.officefloor.frame.api.executive.Executive;
 import net.officefloor.frame.api.manage.OfficeFloor;
 import net.officefloor.frame.api.manage.OfficeFloor;
 import net.officefloor.frame.api.managedobject.ProcessAwareContext;
 import net.officefloor.frame.api.managedobject.ProcessAwareContext;
 import net.officefloor.frame.api.managedobject.ProcessSafeOperation;
 import net.officefloor.frame.api.managedobject.ProcessSafeOperation;
+import net.officefloor.frame.util.ExecutiveSourceStandAlone;
 import net.officefloor.server.SocketManager;
 import net.officefloor.server.SocketManager;
 import net.officefloor.server.http.AbstractHttpServicerFactory;
 import net.officefloor.server.http.AbstractHttpServicerFactory;
 import net.officefloor.server.http.HttpHeaderName;
 import net.officefloor.server.http.HttpHeaderName;
@@ -50,6 +51,7 @@ import net.officefloor.server.http.impl.ProcessAwareServerHttpConnectionManagedO
 import net.officefloor.server.http.parse.HttpRequestParser.HttpRequestParserMetaData;
 import net.officefloor.server.http.parse.HttpRequestParser.HttpRequestParserMetaData;
 import net.officefloor.server.stream.StreamBufferPool;
 import net.officefloor.server.stream.StreamBufferPool;
 import net.officefloor.server.stream.impl.ThreadLocalStreamBufferPool;
 import net.officefloor.server.stream.impl.ThreadLocalStreamBufferPool;
+import net.officefloor.web.executive.WebThreadAffinityExecutiveSource;
 
 
 /**
 /**
  * <p>
  * <p>
@@ -80,8 +82,13 @@ public class RawOfficeFloorMain {
 		// Create the server location
 		// Create the server location
 		HttpServerLocation serverLocation = new HttpServerLocationImpl("localhost", port, -1);
 		HttpServerLocation serverLocation = new HttpServerLocationImpl("localhost", port, -1);
 
 
+		// Create the execution strategy
+		ExecutiveSourceStandAlone standalone = new ExecutiveSourceStandAlone();
+		Executive executive = standalone.loadExecutive(WebThreadAffinityExecutiveSource.class);
+		ThreadFactory[] executionStrategy = executive.getExcutionStrategies()[0].getThreadFactories();
+
 		// Create the socket manager
 		// Create the socket manager
-		socketManager = HttpServerSocketManagedObjectSource.createSocketManager();
+		socketManager = HttpServerSocketManagedObjectSource.createSocketManager(executionStrategy);
 
 
 		// Create raw HTTP servicing
 		// Create raw HTTP servicing
 		StreamBufferPool<ByteBuffer> serviceBufferPool = new ThreadLocalStreamBufferPool(
 		StreamBufferPool<ByteBuffer> serviceBufferPool = new ThreadLocalStreamBufferPool(
@@ -94,9 +101,9 @@ public class RawOfficeFloorMain {
 		dateTimer.schedule(serviceFactory.updateDate, 0, 1000);
 		dateTimer.schedule(serviceFactory.updateDate, 0, 1000);
 
 
 		// Start servicing
 		// Start servicing
-		Executor executor = Executors.newCachedThreadPool();
-		for (Runnable runnable : socketManager.getRunnables()) {
-			executor.execute(runnable);
+		Runnable[] runnables = socketManager.getRunnables();
+		for (int i = 0; i < runnables.length; i++) {
+			executionStrategy[i].newThread(runnables[i]).start();
 		}
 		}
 
 
 		// Indicate running
 		// Indicate running
@@ -161,6 +168,20 @@ public class RawOfficeFloorMain {
 			this.objectMapper.registerModule(new AfterburnerModule());
 			this.objectMapper.registerModule(new AfterburnerModule());
 		}
 		}
 
 
+		/**
+		 * Sends the {@link HttpResponse}.
+		 * 
+		 * @param connection {@link ServerHttpConnection}.
+		 * @throws IOException If fails to send.
+		 */
+		protected void send(ProcessAwareServerHttpConnectionManagedObject<ByteBuffer> connection) throws IOException {
+			try {
+				connection.getServiceFlowCallback().run(null);
+			} catch (Throwable ex) {
+				throw new IOException(ex);
+			}
+		}
+
 		/*
 		/*
 		 * ===================== HttpServicer ====================
 		 * ===================== HttpServicer ====================
 		 */
 		 */
@@ -184,26 +205,25 @@ public class RawOfficeFloorMain {
 			// Determine request
 			// Determine request
 			String requestUri = request.getUri();
 			String requestUri = request.getUri();
 			switch (requestUri) {
 			switch (requestUri) {
+
 			case "/plaintext":
 			case "/plaintext":
 				response.setContentType(TEXT_PLAIN, null);
 				response.setContentType(TEXT_PLAIN, null);
 				response.getEntity().write(HELLO_WORLD);
 				response.getEntity().write(HELLO_WORLD);
+				this.send(connection);
 				break;
 				break;
 
 
 			case "/json":
 			case "/json":
 				response.setContentType(APPLICATION_JSON, null);
 				response.setContentType(APPLICATION_JSON, null);
 				this.objectMapper.writeValue(response.getEntityWriter(), new Message("Hello, World!"));
 				this.objectMapper.writeValue(response.getEntityWriter(), new Message("Hello, World!"));
+				this.send(connection);
 				break;
 				break;
 
 
 			default:
 			default:
+				// Unknown request
 				response.setStatus(HttpStatus.NOT_FOUND);
 				response.setStatus(HttpStatus.NOT_FOUND);
+				this.send(connection);
 				break;
 				break;
 			}
 			}
-
-			try {
-				connection.getServiceFlowCallback().run(null);
-			} catch (Throwable ex) {
-				throw new IOException(ex);
-			}
 		}
 		}
 	}
 	}
 
 

+ 46 - 0
frameworks/Java/officefloor/src/woof_thread_affinity/pom.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>net.officefloor.benchmarks</groupId>
+		<artifactId>benchmarks</artifactId>
+		<version>1.0.0</version>
+	</parent>
+	<artifactId>woof_thread_affinity</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>net.officefloor.benchmarks</groupId>
+			<artifactId>woof_micro</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.officefloor.web</groupId>
+			<artifactId>officeweb_executive</artifactId>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-shade-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>shade</goal>
+						</goals>
+						<configuration>
+							<transformers>
+								<transformer
+									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+									<mainClass>net.officefloor.OfficeFloorMain</mainClass>
+								</transformer>
+							</transformers>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 1 - 1
frameworks/Java/officefloor/src/woof_tpr/src/main/resources/datasource.properties

@@ -2,4 +2,4 @@ datasource.class=com.zaxxer.hikari.HikariDataSource
 jdbcUrl=jdbc:postgresql://tfb-database:5432/hello_world
 jdbcUrl=jdbc:postgresql://tfb-database:5432/hello_world
 username=benchmarkdbuser
 username=benchmarkdbuser
 password=benchmarkdbpass
 password=benchmarkdbpass
-maximumPoolSize=28
+maximumPoolSize=56