Performance notes on Room Extensions

Attaching an Extension at Room level is a convenient way to provide each game Room with its own logic. Different Rooms can use different code and manage their own game rules very conveniently.

There are however some important performance aspects that need to be taken into account. SmartFoxServer 2X isolates each Room Extension in its own class loader to facilitate live re-deploy of Extension code. This means that once you have deployed your Game.class each Room running the same Extension will load a copy of it in its own class loader.

cloadersAs shown in this picture, every game Room has a different copy of all classes in the Extension jar file. This means that as the number of Rooms grows so will the amount of memory required to keep all these class copies in memory.

» Why multiple copies?

The advantage of this approach is that developers can, at any time, deploy  a new version of their Extension while the server is running. Once the code is uploaded all newly created game Rooms will run the new code, while the old Rooms will still run the previous Extension.

Without this option the only way to deploy new Room Extensions would be to upload the new jar file and restart the server. Not very convenient if thousands of players are currently playing online.

» How to prevent memory issues?

The Java Virtual Machine (JVM) uses a specialized memory area called PermGen (permanent generation, renamed “metaspace” in Java 8) to store the class definitions. This is the area that could be subject to an overflow if you plan to run tens of thousands of Rooms Extension at once.

Depending on the number and complexity of the loaded classes you may eventually get the dreaded “java.lang.OutOfMemoryError: PermGen space” error, notifying that the class space is fully used and no more data can be loaded.

The default size of the PermGen memory is usually not very big, typically 64MB. We can adjust this size to a larger value via this JVM setting:

-XX:MaxPermSize=512m

JVM settings can be made permanent by adding them to the server startup. See the last section of this documentation page for more details.

» Dependency check

Another important aspect of optimizing an Extension for Room deployment is making absolutely sure that all dependency classes are not deployed with the Extension jar, but instead are copied to the top extension/__lib__/ folder so that they are shared among all instances.

This is particularly true with IDEs that package all dependencies inside your final .jar file (Netbeans for example), which is a bad idea at least for SmartFoxServer deployment.

You can imagine that if you embed the MySQL DB driver in your Extension .jar file, each class loader will potentially end up loading more copies of the same classes which have no potential to ever change and thus should not be deployed with the main code.

The rule of thumb here is: only the game code should be deployed in your Extension jar. Everything else goes into the shared extension/__lib__/ folder.

For more details about deployment follow the documentation here.

» Alternative deployment method

If you don’t need to redeploy your code very often and you want to avoid all of the possible memory issues altogether, there is an alternative. Simply copy your Extension jar directly in the  extension/__lib__/ folder.

This will in turn use only the top class loader for all game Rooms, thus avoiding the problem entirely, i.e. only one copy of your classes will be used throughout the entire life-cycle of the server.

The downside of this approach is that you won’t be able to redeploy the game code without restarting the server itself.

To learn all the details about SmartFoxServer 2X and class loading please refer to the documentation.