Externalize string from generated java classes

Lucee has a hidden feature to force the compiler to externalise strings from class files, this can reduce the size of class files a lot and because of that the memory footprint of a running application.

Please have in mind that the removal of the PermGen space in Java 8 not really has influence on this, moving in java 8 from permgenspace to meta memory is just change how the memory is handled, but it does not free memory in any way.

Below you can find a detailed description of this feature with installation and configuration instructions.

Question is, should we enable this feature with Lucee 5 by default and make it visible in the admin?

Explanation

When a CFML template is executed, Lucee generated a java class file of that template, this class files includes everything of the CFML template including all texts.

Class files in Java are loaded to the PermGenSpace (short: PGS) memory portion. So having a lot of CFML files executed can mean that the PGS is filled up and runs out of memory. To avoid this, Lucee comes with a hidden feature to externalize string of a certain size to an external file, that files then only get loaded into the memory when needed and it is removed from memory afterwards (with some caching mechanism).

This feature reduces the footprint of classes, but slows down execution a little bit, because it has to load this external resources. Impact on performance normally is less than 1% of the overall execution time depending on the actual value of the setting (see “Configuration” for details).

Installation

  • stop Lucee
  • add the (or extend) the following tag in the body of the root tag of the xml file {lucee-server}/lib/ext/context/luee-server.xml
    <compiler externalize-string-gte="100"/>
  • delete all “cfclasses folder” (I will make sure that this step is no longer necessary in future versions)
  • start Lucee

Configuration

In the example above, all text that are bigger or equal than 100 character are moved to an extrernal file.
Having the text in a external file slows down the execution of a template a little bit, but it does not matter if only one portion is externalized or multiple, then the file is only loaded once when executed and holds all portions of the externalized texts of one class.

So what the right value is for this setting is hard to say, bigger number, less text is externalized but the code run faster. So best is to start with 100 and then see what the effect is, means check how big the .txt files in the cfclasses folder are in comparison to the .class files.

Every change on this value makes it necessary to delete all cfclasses folders.

1 Like

Does that include all of the literal text/html in a CFML template?

I’m for exposing that feature in the Admin, but keeping it off by default, allowing the user to turn it on if he experiences memory issues.

yes all literal string of a certain size.

ATM this is a very static setting, Lucee does what the setting defines without “thinking” about it, i was thinking if we could made this setting smarter in the future. Lucee could log somewhere the code/text ratio of every class and if it runs out of memory, it could update this classes by removing the text from memory and move to an extrernal file starting with the classes that have the biggest portion of text. So in other words Lucee only use this feature when necessary and aplies it to the classes with the biggest benefit first.
Of course i’m talking about a version 2 here.

Looks like Discourse ate your XML?

With my TAG hat on, I have no input on whether or not you should do this. It’s an implementation detail at most and should be the decision of the core developer team alone, in my opinion.

With my CFML developer hat on, I would not want any change to the default behavior of the engine that reduced performance but I certainly would appreciate the option to trade off speed for memory in a case like this. [We run Lucee with a 10GB heap on machines with 64GB RAM so we don’t have memory problems – we want speed first and foremost]

I fixed the eaten XML

1 Like

This is a WIP attribute, right? I think it should be changed a bit. maybe extern-strings-length or maybe extern-strings-threshold

Is the length per string? or total of all strings in the class?

I think that a power-of-2 number would be better than 100. I recommend using 256 instead of 100 for default to start with.

The name of the attribute not really matter, because most people will use the admin frontend for this.
we talking about the string length here, the string is stored with charset URF-8, so the byte size used in memory and in the external files are not the same as the charset length.