We have released a new Developer Console tool to help you debug and solve issues with memory usage and memory leaks both in client and on the server.
The main focus of the tool is to provide insights into memory used by the Luau VM, but it can also give hints on where unparented engine instances are being held by scripts.
This tool is only visible if you are a developer of the experience.
To use the new tool, open the Developer Console using the F9 key or the Developer Console button in the Settings and select LuauHeap from the drop-down list.
To explore the current memory allocation, create snapshots using the Create Snapshot button on the right.
When multiple snapshots are created, you can compare differences in memory use by clicking on a snapshot in the list on the left and clicking Compare on a different snapshot in the same list.
Be careful when making snapshots on the Server. We recommend first trying it out in Studio and then testing it live in a private instance.
Taking a server snapshot in a live experience is possible, but it can take a considerable amount of time that will be seen as a high ping by the players.
During the preview we received reports of server snapshots crashing the server because of a timeout. We are working to improve the performance of the capture to avoid such a failure case.
There are tabs for the information that is gathered in a snapshot, so let’s go through them.
This is a simple view showing how much memory is used by each Luau VM type.
Using the snapshot comparison function, this view can be used to quickly glance at what kind of objects are being used the most.
This view shows memory usage grouped by memory category.
A memory category is assigned to an object at allocation time, taken from the value assigned to the running Luau thread.
By default, the memory category name is the name of the script. Custom memory category names can be assigned using the
debug.setmemorycategory function. Multiple scripts often share the same memory category slot as their number is limited.
This view shows how many instances of each Roblox engine class are being stored in scripts.
Note that the Size field represents only the memory that Luau VM needs to represent the target object, it doesn’t include any memory that the Roblox engine itself uses.
For example, a ‘Player’ instance only needs 32 bytes of memory inside Luau, but links to an engine class that uses multiple kilobytes of memory and can contain hundreds of other instances inside. Similar to ‘Object Tags’ view, by using the snapshot compare feature, it can provide a quick way to find issues with how specific instances are being created.
This is the most detailed and complex view into the Luau memory. It shows an aggregated memory use tree where each element represents an allocated object and tree structure is derived from the shortest path between object references.
All memory starts at Luau VM ‘registry’ - this is where all references from Roblox engine to Luau are stored, such as functions connected to signals or the task library, ModuleScript return tables, global functions, tables and classes.
The tree shows how objects are linked to each other inside the VM.
Here are some entries you might see:
‘Module @Path.To.Module’ is the table returned by the specified ModuleScript.
‘name:123 =Path.To.Module’ is a function inside the specified Script. Functions often don’t have an associated name in which case the ‘name’ part will be missing. Line 1 often refers to the global script function.
‘env’ refers to the environment of a function. Most commonly, this is a table representing the global scope of a Script. Check out Lua 5.1 Reference Manual for more information.
‘globals’ refers to the environment of a thread.
‘[key]’ is for objects used as table keys.
‘array’ represents the table array part.
‘stack’ refers to the array where all function locals are stored. It is owned by a thread object.
‘constants’ is an array that a function uses for constant value lookups.
Each element has a ‘Size’ and ‘Self’ columns.
- ‘Self’ means the memory used by the element itself, for example, an array of 1000 elements might use 16000 bytes just for the memory block where elements are stored
- ‘Size’ will also include the memory used by each element of the array (when it’s a complex object like a table).
Elements smaller than 2KB are replaced with a single ‘…’ node.
This view shows instances that are unparented from the DataModel and are only reachable from scripts. We attempt to display one or more paths that pin the instance object.
Keep in mind that in some cases it’s ok for the script to be the only owner of an instance, but if you see large amounts of instances that you did not expect, check out the paths which keep holding them.
Often, this is caused by signal connections not being disconnected.
There are some known issues and limitations, some of which we plan to address soon:
Parallel Luau VM heaps are not included in the memory size reports
If an instance is held by a Parallel Luau VM, it will not show up in the ‘Unique References’ view
Server snapshots can timeout a live RCC server with a large Luau heap
We want to provide more info about the root of an unparented instance
Entries smaller than 2KB are replaced with ‘…’, we want to make this limit configurable
Please try it out and tell us what you think!