Configure Capsule/Driver to give Corda a relatively poxy 200mb heap by default: we don't seem to need more for development purposes. Switch to G1GC by default as well.

This commit is contained in:
Mike Hearn 2017-01-11 18:43:45 +01:00
parent d2d25c9954
commit d26c44d08c
5 changed files with 47 additions and 10 deletions

View File

@ -56,9 +56,28 @@ Here are a few ways to build dashboards and extract monitoring data for a node:
* *Java Mission Control* is a desktop app that can connect to a target JVM that has the right command line flags set * *Java Mission Control* is a desktop app that can connect to a target JVM that has the right command line flags set
(or always, if running locally). You can explore what data is available, create graphs of those metrics, and invoke (or always, if running locally). You can explore what data is available, create graphs of those metrics, and invoke
management operations like forcing a garbage collection. management operations like forcing a garbage collection.
* *VisualVM* is another desktop app that can do fine grained JVM monitoring and sampling. Very useful during development.
* Cloud metrics services like New Relic also understand JMX, typically, by providing their own agent that uploads the * Cloud metrics services like New Relic also understand JMX, typically, by providing their own agent that uploads the
data to their service on a regular schedule. data to their service on a regular schedule.
Memory usage and tuning
-----------------------
All garbage collected programs can run faster if you give them more memory, as they need to collect less
frequently. As a default JVM will happily consume all the memory on your system if you let it, Corda is
configured with a relatively small 200mb Java heap by default. When other overheads are added, this yields
a total memory usage of about 500mb for a node (the overheads come from things like compiled code, metadata,
off-heap buffers, thread stacks, etc).
If you want to make your node go faster and profiling suggests excessive GC overhead is the cause, or if your
node is running out of memory, you can give it more by running the node like this:
``java -Xmx1024m -jar corda.jar``
The example command above would give a 1 gigabyte Java heap.
.. note:: Unfortunately the JVM does not let you limit the total memory usage of Java program, just the heap size.
Uploading and downloading attachments Uploading and downloading attachments
------------------------------------- -------------------------------------

View File

@ -49,15 +49,25 @@ dependencies {
} }
task buildCordaJAR(type: FatCapsule, dependsOn: ['buildCertSigningRequestUtilityJAR']) { task buildCordaJAR(type: FatCapsule, dependsOn: ['buildCertSigningRequestUtilityJAR']) {
applicationClass 'net.corda.node.MainKt' applicationClass 'net.corda.node.Corda'
archiveName "corda-${corda_version}.jar" archiveName "corda-${corda_version}.jar"
applicationSource = files(project.tasks.findByName('jar'), '../build/classes/main/CordaCaplet.class', 'config/dev/log4j2.xml') applicationSource = files(project.tasks.findByName('jar'), '../build/classes/main/CordaCaplet.class', 'config/dev/log4j2.xml')
capsuleManifest { capsuleManifest {
appClassPath = ["jolokia-agent-war-${project.rootProject.ext.jolokia_version}.war"] appClassPath = ["jolokia-agent-war-${project.rootProject.ext.jolokia_version}.war"]
javaAgents = ["quasar-core-${quasar_version}-jdk8.jar"] javaAgents = ["quasar-core-${quasar_version}-jdk8.jar"]
systemProperties['visualvm.display.name'] = 'Corda'
minJavaVersion = '1.8.0' minJavaVersion = '1.8.0'
// This version is known to work and avoids earlier 8u versions that have bugs.
minUpdateVersion['1.8'] = '102'
caplets = ['CordaCaplet'] caplets = ['CordaCaplet']
// JVM configuration:
// - Constrain to small heap sizes to ease development on low end devices.
// - Switch to the G1 GC which is going to be the default in Java 9 and gives low pause times/string dedup.
//
// If you change these flags, please also update Driver.kt
jvmArgs = ['-Xmx200m', '-XX:+UseG1GC']
} }
} }

View File

@ -1,3 +1,4 @@
@file:JvmName("Corda")
package net.corda.node package net.corda.node
import com.typesafe.config.ConfigException import com.typesafe.config.ConfigException

View File

@ -441,7 +441,6 @@ open class DriverDSL(
} }
companion object { companion object {
val name = arrayOf( val name = arrayOf(
"Alice", "Alice",
"Bob", "Bob",
@ -459,20 +458,28 @@ open class DriverDSL(
// Write node.conf // Write node.conf
writeConfig(nodeConf.baseDirectory, "node.conf", nodeConf.config) writeConfig(nodeConf.baseDirectory, "node.conf", nodeConf.config)
val className = "net.corda.node.MainKt" // cannot directly get class for this, so just use string val className = "net.corda.node.Corda" // cannot directly get class for this, so just use string
val separator = System.getProperty("file.separator") val separator = System.getProperty("file.separator")
val classpath = System.getProperty("java.class.path") val classpath = System.getProperty("java.class.path")
val path = System.getProperty("java.home") + separator + "bin" + separator + "java" val path = System.getProperty("java.home") + separator + "bin" + separator + "java"
val debugPortArg = if (debugPort != null) val debugPortArg = if (debugPort != null)
listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort") "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort"
else else
emptyList() ""
val javaArgs = listOf(path) + val javaArgs = listOf(
listOf("-Dname=${nodeConf.myLegalName}", "-javaagent:$quasarJarPath") + debugPortArg + path,
listOf("-cp", classpath, className) + "-Dname=${nodeConf.myLegalName}",
"-javaagent:$quasarJarPath",
debugPortArg,
"-Dvisualvm.display.name=Corda",
"-Xmx200m",
"-XX:+UseG1GC",
"-cp", classpath,
className,
"--base-directory=${nodeConf.baseDirectory}" "--base-directory=${nodeConf.baseDirectory}"
).filter(String::isNotEmpty)
val builder = ProcessBuilder(javaArgs) val builder = ProcessBuilder(javaArgs)
builder.redirectError(Paths.get("error.$className.log").toFile()) builder.redirectError(Paths.get("error.$className.log").toFile())
builder.inheritIO() builder.inheritIO()

View File

@ -12,7 +12,7 @@ import org.junit.Test
class TraderDemoTest { class TraderDemoTest {
@Test fun `runs trader demo`() { @Test fun `runs trader demo`() {
driver(dsl = { driver(isDebug = true) {
val user = User("user1", "test", permissions = setOf(startFlowPermission<IssuerFlow.IssuanceRequester>())) val user = User("user1", "test", permissions = setOf(startFlowPermission<IssuerFlow.IssuanceRequester>()))
val (nodeA, nodeB) = Futures.allAsList( val (nodeA, nodeB) = Futures.allAsList(
startNode("Bank A"), startNode("Bank A"),
@ -23,6 +23,6 @@ class TraderDemoTest {
assert(TraderDemoClientApi(nodeA.configuration.webAddress).runBuyer()) assert(TraderDemoClientApi(nodeA.configuration.webAddress).runBuyer())
assert(TraderDemoClientApi(nodeB.configuration.webAddress).runSeller(counterparty = nodeA.nodeInfo.legalIdentity.name)) assert(TraderDemoClientApi(nodeB.configuration.webAddress).runSeller(counterparty = nodeA.nodeInfo.legalIdentity.name))
}, isDebug = true) }
} }
} }