-
Notifications
You must be signed in to change notification settings - Fork 25
Optimizing LML
This section contains a few tips on how you can make your GUI building slightly faster. LML is already rather quick and you mostly won't need these informations, but there are situations where you need LML to be blazing-fast (like on GWT, which has a rather slow reflection implementation), so this article might still be useful.
ActorConsumer
is a functional interface that consumes a single Actor
(or other object, depending on its purpose) , does something (according to its implementation) and returns a single result. They might seem like an alternative to more convenient ActionContainers
, which are scanned using reflection, but actually its the other way around: ActionContainer
's methods are wrapped with ActorConsumer
interface at runtime to unify the LML methods API.
By registering ActorConsumers
directly, you omit the whole reflection scanning and invoking process. As you can guess, reflection-based actions are completely optional and were added on top of the regular, plain-old-Java mechanism. There's a drawback to this approach, though: unless using Java 8 lambdas or another JVM language, the syntax for creating new ActorConsumers
is rather verbose. At least comparing to ActionConsumer
, which is basically a class where every method can be invoked in LML.
Explicitly registered ActorConsumers
are always preferred over ActionContainer
methods in case of any name clashes, so you don't have to worry about the methods priority.
If you still want to use reflection-based methods, you might want to make sure that method look-up is as fast as possible. When faced with a method reference (for example, action
), LML parser will search through all ActionConsumers
until it finds matching method with the selected name. By using a single ActionContainer
or explicitly referencing a specific container (for example, global.action
), you limit the time that LML parser spends scanning through ActionContainers
with reflection.
Being able to extract field values from ActionContainers
in LML is very convenient, but this functionality prolongs the time needed to scan through an ActionContainer
(see previous point) and is very error-prone on GWT.
Importing external templates requires LML parser to load an additional file each time it is referenced. Files are not cached to limit meta-data kept by the parser at runtime. On contrary, custom macros need to be parsed once and then they are kept by the parser: you can use custom macros defined with <:macro>
tag in any template, not only the one it was created in.
As a rule of thumb: if you wrap a single actor with a macro, consider if a set of the default attributes would be enough to set it up. If yes, do not use macros. Style sheets page explains why default attributes are usually more convenient. Due to how macro mechanism works, using macros can basically double the amount of text that has to be processed by the parser.
If this setting is true
, component actors cannot have additional attributes. For example, normally you can use Label
attributes (like labelAlign
) in a Window
- they will modify Label
instance used as its title. However, if this settings is change to true
, component actors will no longer be processed and cannot have their specific attributes - so, for example, using Label
attributes in a Window
tag would cause an exception. While it limits customization of some actors in LML, this speeds up attribute parsing of widgets that actually have component actors. A rule of thumb: if you set this value to true
, try using a strict parser and see if your application is still running just fine; if it is, you should keep it that way.
This one is pretty obvious, but not always possible or convenient. If you created all views and you're 100% sure you're not going to use LML to parse any more actors, you can delete all references to LML parser. This will most likely schedule it to be garbage-collected. Note that usually the memory footprint isn't nearly big enough to care.
This will clear user objects (see Actor#setUserObject
) recursively. LML exploits user object mechanism to store various meta-data, including Table
's Cells
, Tree
's Nodes
, and additional settings that are unavailable in vanilla Scene2D
. Again, memory footprint shouldn't be that big - and some meta-data is useful even at runtime, like stage attachers - but if you invoke these methods on your actors after adding them to Stage
and nothing crashes, you can just leave it that way and enjoy having less objects at runtime. Just don't come running with new bug issues, because you have been warned.
When this setting is turned on (the default), LML will go through all methods of your registered ActionContainer
instances, even if they are not annotated with @LmlAction
. This can significantly influence action lookup time.
MJ 2016