ENT-2023 Restore rpcThreadPoolSize enterprise config setting (#922)

* Add a sampler for EmptyFlow, and also re-establish wiring to the rpcThreadPoolSize config parameter.

* Remove mutex from multi-threaded SMM startFlow

* Add EmptyFlow to nightly benchmark and also a CashIssue 200
This commit is contained in:
Rick Parker 2018-06-06 11:47:37 +01:00 committed by GitHub
parent 9a4abf92c5
commit d675a17e17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 21 deletions

View File

@ -54,10 +54,11 @@ import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ExecutorService
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.ReentrantReadWriteLock
import javax.annotation.concurrent.ThreadSafe
import kotlin.collections.ArrayList
import kotlin.concurrent.withLock
import kotlin.concurrent.read
import kotlin.concurrent.write
import kotlin.streams.toList
/**
@ -356,7 +357,7 @@ class MultiThreadedStateMachineManager(
// Just flow initiation message
null
}
externalEventMutex.withLock {
externalEventMutex.write {
// Remove any sessions the old flow has.
for (sessionId in getFlowSessionIds(currentState.checkpoint)) {
sessionToFlow.remove(sessionId)
@ -377,9 +378,9 @@ class MultiThreadedStateMachineManager(
}
}
private val externalEventMutex = ReentrantLock()
private val externalEventMutex = ReentrantReadWriteLock()
override fun deliverExternalEvent(event: ExternalEvent) {
externalEventMutex.withLock {
externalEventMutex.read {
when (event) {
is ExternalEvent.ExternalMessageEvent -> onSessionMessage(event)
is ExternalEvent.ExternalStartFlowEvent<*> -> onExternalStartFlow(event)

View File

@ -10,12 +10,10 @@
package com.r3.corda.enterprise.perftestcordapp
import co.paralleluniverse.fibers.Suspendable
import com.google.common.base.Stopwatch
import com.r3.corda.enterprise.perftestcordapp.flows.CashIssueAndPaymentNoSelection
import com.r3.corda.enterprise.perftestcordapp.flows.EmptyFlow
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.messaging.startFlow
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
@ -57,13 +55,6 @@ class NodePerformanceTests : IntegrationTest() {
DUMMY_BANK_A_NAME.toDatabaseSchemaName())
}
@StartableByRPC
class EmptyFlow : FlowLogic<Unit>() {
@Suspendable
override fun call() {
}
}
private data class FlowMeasurementResult(
val flowPerSecond: Double,
val averageMs: Double
@ -84,7 +75,7 @@ class NodePerformanceTests : IntegrationTest() {
queueBound = 50
) {
val timing = Stopwatch.createStarted().apply {
connection.proxy.startFlow(NodePerformanceTests::EmptyFlow).returnValue.getOrThrow()
connection.proxy.startFlow(::EmptyFlow).returnValue.getOrThrow()
}.stop().elapsed(TimeUnit.MICROSECONDS)
timings.add(timing)
}
@ -113,7 +104,7 @@ class NodePerformanceTests : IntegrationTest() {
injectionRate = 2000L / TimeUnit.SECONDS,
workBound = 50
) {
connection.proxy.startFlow(NodePerformanceTests::EmptyFlow).returnValue
connection.proxy.startFlow(::EmptyFlow).returnValue
}
}
}

View File

@ -0,0 +1,22 @@
/*
* R3 Proprietary and Confidential
*
* Copyright (c) 2018 R3 Limited. All rights reserved.
*
* The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law.
*
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
package com.r3.corda.enterprise.perftestcordapp.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
@StartableByRPC
class EmptyFlow : FlowLogic<Unit>() {
@Suspendable
override fun call() {
}
}

View File

@ -12,10 +12,7 @@ package com.r3.corda.jmeter
import com.r3.corda.enterprise.perftestcordapp.DOLLARS
import com.r3.corda.enterprise.perftestcordapp.POUNDS
import com.r3.corda.enterprise.perftestcordapp.flows.CashIssueAndPaymentFlow
import com.r3.corda.enterprise.perftestcordapp.flows.CashIssueAndPaymentNoSelection
import com.r3.corda.enterprise.perftestcordapp.flows.CashIssueFlow
import com.r3.corda.enterprise.perftestcordapp.flows.LinearStateBatchNotariseFlow
import com.r3.corda.enterprise.perftestcordapp.flows.*
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
@ -48,6 +45,23 @@ abstract class AbstractSampler : BaseFlowSampler() {
}
}
/**
* A sampler for calling EmptyFlow.
*/
class EmptyFlowSampler : AbstractSampler() {
override val additionalArgs: Set<Argument> = emptySet()
override fun setupTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
}
override fun teardownTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
}
override fun createFlowInvoke(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext): FlowInvoke<EmptyFlow> {
return FlowInvoke<EmptyFlow>(EmptyFlow::class.java, emptyArray())
}
}
/**
* A sampler for calling CashIssueFlow.
*

View File

@ -61,6 +61,55 @@
</collectionProp>
</Arguments>
<hashTree/>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Empty Flow 200 Thread Group ${__machineName}" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">200</stringProp>
<stringProp name="ThreadGroup.ramp_time"></stringProp>
<longProp name="ThreadGroup.start_time">1509455820000</longProp>
<longProp name="ThreadGroup.end_time">1509455820000</longProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">${duration}</stringProp>
<stringProp name="ThreadGroup.delay">${pause}</stringProp>
</ThreadGroup>
<hashTree>
<JavaSampler guiclass="JavaTestSamplerGui" testclass="JavaSampler" testname="Empty Flow" enabled="true">
<elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="label" elementType="Argument">
<stringProp name="Argument.name">label</stringProp>
<stringProp name="Argument.value">${__samplerName}-${__groovy(ctx.getThreadGroup().getNumThreads() * vars.get(&quot;remoteAgentCount&quot;).toInteger())}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="host" elementType="Argument">
<stringProp name="Argument.name">host</stringProp>
<stringProp name="Argument.value">${host}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="port" elementType="Argument">
<stringProp name="Argument.name">port</stringProp>
<stringProp name="Argument.value">${port}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="username" elementType="Argument">
<stringProp name="Argument.name">username</stringProp>
<stringProp name="Argument.value">${username}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="password" elementType="Argument">
<stringProp name="Argument.name">password</stringProp>
<stringProp name="Argument.value">${password}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.EmptyFlowSampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Cash Issue 1 Thread Group ${__machineName}" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
@ -493,6 +542,60 @@
</JavaSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Cash Issue 200 Thread Group ${__machineName}" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">200</stringProp>
<stringProp name="ThreadGroup.ramp_time"></stringProp>
<longProp name="ThreadGroup.start_time">1509455820000</longProp>
<longProp name="ThreadGroup.end_time">1509455820000</longProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">${duration}</stringProp>
<stringProp name="ThreadGroup.delay">${pause}</stringProp>
</ThreadGroup>
<hashTree>
<JavaSampler guiclass="JavaTestSamplerGui" testclass="JavaSampler" testname="Cash Issue" enabled="true">
<elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="label" elementType="Argument">
<stringProp name="Argument.name">label</stringProp>
<stringProp name="Argument.value">${__samplerName}-${__groovy(ctx.getThreadGroup().getNumThreads() * vars.get(&quot;remoteAgentCount&quot;).toInteger())}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="host" elementType="Argument">
<stringProp name="Argument.name">host</stringProp>
<stringProp name="Argument.value">${host}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="port" elementType="Argument">
<stringProp name="Argument.name">port</stringProp>
<stringProp name="Argument.value">${port}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="username" elementType="Argument">
<stringProp name="Argument.name">username</stringProp>
<stringProp name="Argument.value">${username}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="password" elementType="Argument">
<stringProp name="Argument.name">password</stringProp>
<stringProp name="Argument.value">${password}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="notaryName" elementType="Argument">
<stringProp name="Argument.name">notaryName</stringProp>
<stringProp name="Argument.value">${notaryName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueSampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Cash Issue and Pay 1 Thread Group ${__machineName}" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">