ENT-2198 Add more benchmarks to the overnight performance run (#1313)

This commit is contained in:
Rick Parker 2018-08-02 09:57:30 +01:00 committed by GitHub
parent 30aad25841
commit 2acd89850a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 150 additions and 33 deletions

View File

@ -0,0 +1,65 @@
package com.r3.corda.enterprise.perftestcordapp.flows
import co.paralleluniverse.fibers.Suspendable
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.Cash
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.OnLedgerAsset
import com.r3.corda.enterprise.perftestcordapp.contracts.asset.PartyAndAmount
import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.contracts.Amount
import net.corda.core.contracts.Issued
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionState
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import java.util.*
@StartableByRPC
class CashPaymentFromKnownStatesFlow(
val inputs: Set<StateRef>,
val numberOfStates: Int,
val amountPerState: Amount<Currency>,
val recipient: Party,
val anonymous: Boolean,
progressTracker: ProgressTracker) : AbstractCashFlow<AbstractCashFlow.Result>(progressTracker) {
constructor(inputs: Set<StateRef>,
numberOfStates: Int,
amountPerState: Amount<Currency>,
recipient: Party,
anonymous: Boolean) : this(inputs, numberOfStates, amountPerState, recipient, anonymous, tracker())
@Suspendable
override fun call(): AbstractCashFlow.Result {
fun deriveState(txState: TransactionState<Cash.State>, amt: Amount<Issued<Currency>>, owner: AbstractParty) = txState.copy(data = txState.data.copy(amount = amt, owner = owner))
progressTracker.currentStep = AbstractCashFlow.Companion.GENERATING_ID
val txIdentities = if (anonymous) {
subFlow(SwapIdentitiesFlow(recipient))
} else {
emptyMap<Party, AnonymousParty>()
}
val anonymousRecipient = txIdentities[recipient] ?: recipient
progressTracker.currentStep = AbstractCashFlow.Companion.GENERATING_TX
val builder = TransactionBuilder(notary = null)
val cashStateAndRef = inputs.map { serviceHub.toStateAndRef<Cash.State>(it) }
val amounts = ArrayList(Collections.nCopies(numberOfStates, PartyAndAmount(anonymousRecipient, amountPerState)))
val changeIdentity = serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, false)
val (spendTx, keysForSigning) = OnLedgerAsset.generateSpend(builder, amounts, cashStateAndRef,
changeIdentity.party.anonymise(),
{ state, quantity, owner -> deriveState(state, quantity, owner) },
{ Cash().generateMoveCommand() })
progressTracker.currentStep = AbstractCashFlow.Companion.SIGNING_TX
val tx = serviceHub.signInitialTransaction(spendTx, keysForSigning)
progressTracker.currentStep = AbstractCashFlow.Companion.FINALISING_TX
val notarised = finaliseTx(tx, setOf(recipient), "Unable to notarise spend")
return AbstractCashFlow.Result(notarised.id, anonymousRecipient)
}
}

View File

@ -50,6 +50,8 @@ abstract class BaseFlowSampler : AbstractJavaSamplerClient() {
private var labelValue: String? = null
protected open var flowResult: Any? = null
override fun getDefaultParameters(): Arguments {
// Add copies of all args, since they seem to be mutable.
return Arguments().apply {
@ -96,13 +98,14 @@ abstract class BaseFlowSampler : AbstractJavaSamplerClient() {
result.sampleLabel = labelValue ?: flowInvoke.flowLogicClass.simpleName
result.latencyEnd()
try {
val flowResult = handle.returnValue.get()
flowResult = handle.returnValue.get()
result.sampleEnd()
result.apply {
isSuccessful = true
additionalFlowResponseProcessing(context, this, flowResult)
}
} catch (e: Exception) {
flowResult = null
result.sampleEnd()
e.printStackTrace()
result.apply {

View File

@ -13,10 +13,12 @@ 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.*
import net.corda.core.contracts.StateRef
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import org.apache.jmeter.config.Argument
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext
import org.apache.jmeter.samplers.SampleResult
@ -90,8 +92,8 @@ class CashIssueSampler : AbstractSampler() {
class CashIssueAndPaySampler : AbstractSampler() {
companion object JMeterProperties {
val otherParty = Argument("otherPartyName", "", "<meta>", "The X500 name of the payee.")
val coinSelection = Argument("useCoinSelection", "true", "<meta>", "True to use coin selection and false (or anything else) to avoid coin selection.")
val anonymousIdentities = Argument("anonymousIdentities", "true", "<meta>", "True to use anonymous identities and false (or anything else) to use well known identities.")
val coinSelection = Argument("useCoinSelection", "false", "<meta>", "True to use coin selection and false (or anything else) to avoid coin selection.")
val anonymousIdentities = Argument("anonymousIdentities", "false", "<meta>", "True to use anonymous identities and false (or anything else) to use well known identities.")
}
lateinit var counterParty: Party
@ -233,3 +235,50 @@ class LinearStateBatchNotariseSampler : AbstractSampler() {
return result
}
}
/**
* A sampler that issues cash once per sampler, and then generates a transaction to pay 1 dollar "numberOfStatesPerTx" times
* to a specified party per sample, thus invoking the notary and the payee via P2P.
*
* This allows us to test performance with different numbers of states per transaction, and to eliminate issuance from
* each sample (unlike CashIssueAndPaySampler).
*/
class CashPaySampler : AbstractSampler() {
companion object JMeterProperties {
val otherParty = Argument("otherPartyName", "", "<meta>", "The X500 name of the payee.")
val numberOfStatesPerTx = Argument("numberOfStatesPerTx", "1", "<meta>", "The number of payment states per transaction.")
val anonymousIdentities = Argument("anonymousIdentities", "false", "<meta>", "True to use anonymous identities and false (or anything else) to use well known identities.")
}
lateinit var counterParty: Party
var numberOfStatesPerTxCount: Int = 1
var useAnonymousIdentities: Boolean = true
private var inputIndex = 0
override fun setupTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
getNotaryIdentity(rpcProxy, testContext)
counterParty = getIdentity(rpcProxy, testContext, otherParty)
numberOfStatesPerTxCount = testContext.getParameter(numberOfStatesPerTx.name, numberOfStatesPerTx.value).toInt()
useAnonymousIdentities = testContext.getParameter(anonymousIdentities.name, anonymousIdentities.value).toBoolean()
// Now issue lots of USD
val amount = 1_000_000_000.DOLLARS
val flowInvoke = FlowInvoke<CashIssueFlow>(CashIssueFlow::class.java, arrayOf(amount, OpaqueBytes.of(1), notaryIdentity))
val handle = rpcProxy.startFlowDynamic(flowInvoke.flowLogicClass, *(flowInvoke.args))
flowResult = handle.returnValue.getOrThrow()
}
override fun createFlowInvoke(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext): FlowInvoke<*> {
// Change is always Nth output
val input = StateRef((flowResult as AbstractCashFlow.Result).id, inputIndex)
val amount = 1.DOLLARS
inputIndex = numberOfStatesPerTxCount
return FlowInvoke<CashPaymentFromKnownStatesFlow>(CashPaymentFromKnownStatesFlow::class.java, arrayOf(setOf(input), numberOfStatesPerTxCount, amount, counterParty, useAnonymousIdentities))
}
override fun teardownTest(rpcProxy: CordaRPCOps, testContext: JavaSamplerContext) {
}
override val additionalArgs: Set<Argument>
get() = setOf(notary, otherParty, numberOfStatesPerTx, anonymousIdentities)
}

View File

@ -61,7 +61,7 @@
</collectionProp>
</Arguments>
<hashTree/>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Empty Flow 200 Thread Group ${__machineName}" enabled="false">
<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>
@ -542,7 +542,7 @@
</JavaSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Cash Issue 200 Thread Group ${__machineName}" enabled="false">
<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>
@ -649,9 +649,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -661,7 +661,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
@ -718,9 +718,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -730,7 +730,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
@ -787,9 +787,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -799,7 +799,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
@ -856,9 +856,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -868,7 +868,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
@ -925,9 +925,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -937,7 +937,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
@ -994,9 +994,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -1006,7 +1006,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>
@ -1063,9 +1063,9 @@
<stringProp name="Argument.value">${otherPartyName}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="useCoinSelection" elementType="Argument">
<stringProp name="Argument.name">useCoinSelection</stringProp>
<stringProp name="Argument.value">false</stringProp>
<elementProp name="numberOfStatesPerTx" elementType="Argument">
<stringProp name="Argument.name">numberOfStatesPerTx</stringProp>
<stringProp name="Argument.value">1</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="anonymousIdentities" elementType="Argument">
@ -1075,7 +1075,7 @@
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">com.r3.corda.jmeter.CashIssueAndPaySampler</stringProp>
<stringProp name="classname">com.r3.corda.jmeter.CashPaySampler</stringProp>
</JavaSampler>
<hashTree/>
</hashTree>