0

I'm struggling to what code I should present here, because it is very complicated and it is working at the same time.

The thing is that I build a relatively complicated JavaFX sceengraph and update the content of a VBox with it from a Scala application.

Now, when I run the application using sbt run, with the console window, the sceneragph loads quickly. When I run it from the packaged .jar ( I use sbt-one-jar for this ) the sceenraph takes ages to load.

So everything is working, everything works the same way, except that running from the .jar magically slows it down.

Anyway I paste some code, even if it is not very enlightening:

def SetVboxSceneGraph(
    id:String,
    blob:String,
    handler:(MyEvent)=>Unit
)
{
    val comp=MyComponent.FromBlob(blob,handler)

    comp.CreateNode

    val box=GetMyBox(id)

    val vbox=box.GetNode.asInstanceOf[VBox]

    vbox.getChildren().clear()

    vbox.getChildren().add(comp.GetParent)
}

Edit:

According to sillyfly's suggestion I measured the times each step takes in updating the scenegraph. The steps that slows down is:

        comp.CreateNode

This is the part responsible for building the JavaFX scenegraph from an XML markup ( passed as "blob" ) which I developed to describe so called "MyComponent"s which are classes that build custom widgets from existing JavaFX widgets. Once the scenegraph is built the updating takes the same amount of time.

sbtpr
  • 541
  • 5
  • 18
  • 1
    Does this happen with any scene graph, or does the content matter? Could you try to narrow down which step takes more time, with something like `System.nanoTime` (see [this answer](http://stackoverflow.com/questions/9458234/measuring-time-in-java/9458267#9458267) for example)? – Itai Feb 06 '17 at 12:24
  • It also occured to me that it would be useful to know which step exactly slows down. I have a Timer class in the app which uses System.nanoTime and can report the elapsed time in different units. If I get a clue which step is responsible I will update the question. – sbtpr Feb 06 '17 at 13:41
  • Question updated. – sbtpr Feb 06 '17 at 14:28
  • Well, since you know which method is slow it would probably help if you could include it in the question (or narrow it down to an [MCVE](http://stackoverflow.com/help/mcve) that you can post). – Itai Feb 06 '17 at 17:32
  • The method is fine, otherwise it would not run quickly under sbt run. If there was any systematic problem with it, it would run slow under sbt run as well. The code is too complex to narrow it down, here is the full source: https://github.com/scalasbtguiapps/test/blob/master/src/main/scala/guisystem/mycomponent.scala. It basically transaltes every MyComponent into the respective JavaFX sceengraphs ( MyComponents may consist of more than one widget ). It does this recursively so building the Parent component of a graph builds the whole graph. – sbtpr Feb 06 '17 at 17:58

1 Answers1

1

There are likely two things slowing down your startup: Loading classes, and growing the JVM heap. It's also possible you're allocating less memory for your application, which can slow things down overall.

Unless you have fork := true set in your build.sbt, you'll be running your application in the same java process as your build. This means all of your startup taxes (class loading, heap growing) have already been paid.

Unfortunately, there isn't a way to speed up class loading. However, you can substantially speed up your heap-growing by setting both the Xms and Xmx flags to your java command:

# This is 2 GB. Pick an appropriate value for your app. 
java -Xms2g -Xmx2g -jar my.jar
jkinkead
  • 4,101
  • 21
  • 33
  • First a technical observation: the colon before the memory size causes an error, so it is just -Xms2g and -Xmx2g. Unfortunately no matter how big I choose the heap parameters the execution does not speed up ( also if I choose a barely enough heap size, it does not slow down ). It is still faster with sbt run no matter what I do. – sbtpr Feb 08 '17 at 08:58
  • Sorry, the colons are an error. If you're still having slowdown, it's likely just class loading. You could always try splitting into multiple jars with a more optimal classpath, but that's not likely to help all that much. – jkinkead Feb 08 '17 at 20:36
  • The lesson I have to learn is that rather than building scenegraphs whenever the content changes, it it much faster to build the scenegraph only once and then upon content change update each component to show the actual content. Instead of a scrollable list of content show only a page of content with fixed format. This is less elegant both in terms of programming and looks but at least it works. I have to accept the reality that building large screengraphs is costly in JavaFX. – sbtpr Feb 08 '17 at 21:09