New Features in ScriptProfiler


Hello Creators,

Recently we have been working on improving ScriptProfiler. We have made many improvements that are available today, as well as several features coming soon.

Available Now

Display total wall-clock duration of the completed profiling session

The total wall-clock duration of the session is now displayed at the top of the window in hours:minutes:seconds.milliseconds format.

Focus on subtree

Right-clicking on a node in the Callgraph view sets the focus on that node, displaying only itself and its child nodes. Right-clicking the same node again will reset the view, displaying the contents of the <root> node again.

Higher Sampling Frequency

The Freq: N KHz button toggles the profiler between recording samples at 1KHz, or 1000 times per second, and 10KHz. This higher sampling mode enables greater time precision at the cost of some performance.

Functions View

A flat view of functions is now available, listing all functions recorded during the session.

Live Update

The Live checkbox enables polling and refreshing of profiling data continuously, updating the view with new data each second.

Searching

The search bar is now functional, hiding any parts of the callgraph that do not lead to a node containing the name typed in the search field.

Averaging

The Average button toggles displaying timing values on an average of 1 second, 1 minute, 5 minutes, or 10 minutes based on the wall-clock duration of the entire session. Averaging using an option that is longer than the session duration will extrapolate timing values. For example, for a profiling session of 1 minute in length, averaging using the 5-minutes option will display timing values at 5x their recorded values.

Timed Profiling

The Time button enables automatically stopping the profiler after a set duration. A countdown timer, with the remaining time in the session, is displayed during profiling. Clicking Stop at any time will cancel the timer, and stop the profiler as usual.

Coming Soon

Export profiler data

The Export view enables saving the profiling data displayed in DevConsole to the Roblox Logs directory. Profiling data is encoded as a JSON string, the structure of which is described below.

Profiling Data Format

Example JSON Blob
{
  "Version":2,
  "SessionStartTime":1704850750514,
  "SessionEndTime":1704850751198,
  "Categories":
  [
    {"Name":"Parallel Luau","NodeId":4},
    {"Name":"Heartbeat","NodeId":1}
  ],
  "Nodes":
  [
      {"TotalDuration":2530,"FunctionIds":[1],"NodeIds":[2]},
      {"TotalDuration":2530,"FunctionIds":[2,5],"NodeIds":[3,7]},
      {"TotalDuration":1267},
      {"TotalDuration":7746,"FunctionIds":[3],"NodeIds":[5]},
      {"TotalDuration":7746,"FunctionIds":[4],"NodeIds":[6]},
      {"TotalDuration":7746},
      {"TotalDuration":1263,"FunctionIds":[6],"NodeIds":[8]},
      {"TotalDuration":1263,"FunctionIds":[7],"NodeIds":[9]},
      {"TotalDuration":1263,"FunctionIds":[8],"NodeIds":[10]},
      {"TotalDuration":1263}
  ],
  "Functions":
  [
    {"Name":"main","TotalDuration":2530},
    {"Source":"builtin_ManageCollaborators.rbxm.ManageCollaborators.Packages._Index.roblox_rodux-3.0.0.rodux.Store","Line":81,"TotalDuration":1267},
    {"Name":"Script","TotalDuration":7746},
    {"Source":"Workspace.Actor.Script","Line":1,"TotalDuration":7746},
    {"Source":"builtin_DeveloperInspector.rbxm.DeveloperInspector.Packages._Index.DeveloperFramework.DeveloperFramework.UI.Components.Grid","Line":221,"TotalDuration":1263},
    {"Source":"builtin_DeveloperInspector.rbxm.DeveloperInspector.Packages._Index.DeveloperFramework.DeveloperFramework.UI.Components.Grid","Name":"_update","Line":236,"TotalDuration":1263},
    {"Source":"builtin_DeveloperInspector.rbxm.DeveloperInspector.Packages._Index.DeveloperFramework.DeveloperFramework.UI.Components.Grid","Name":"_getRange","Line":277,"TotalDuration":1263},
    {"Source":"[C]","Name":"ScrollingFrame.CanvasPosition","TotalDuration":1263}
  ]
}

The Version field tracks the major version number of the format. This value is currently 2. The format is subject to change with new, optional fields that may be added at any time, but we expect these changes to remain compatible with tooling that adopts this format today.

A NodeId is a unique identifier for a given node. This identifier is a 1-based index into the Nodes array. Thus, to lookup the Node with NodeId 123, one can simply retrieve the 123rd element in Nodes.

Similarly, a FunctionId identifies a given function descriptor in the Functions array by indexing Functions by the FunctionId.

A Duration is an integer representing an amount of time in profiler ticks. Currently, each tick is equivalent to 1 microsecond. Thus, to convert a duration to seconds, it is simply Duration / 1e6.

SessionStartTime and SessionEndTime are timestamps in milliseconds since the Unix epoch.

Each object in the Categories array contains a Name field and a NodeId field. Each category is representative of each of the top-level categories displayed in ScriptProfiler. The associated NodeId maps to a top-level node in the callgraph with child nodes that refer to each of the functions and nodes that executed during that category’s part of the frame.

Each entry in Nodes represents a function executing at a particular point in the callgraph. Nodes will always have a TotalDuration field, describing the total time spent in that node, including time spent in any child nodes. A node may optionally have a FunctionIds array and a NodeIds array. Each entry in these arrays corresponds to a callee of the current node. For any given child of a node, the i-th index of each array corresponds to the function descriptor of the child in Functions, and the node descriptor of the child in Nodes. If one of these arrays are present, then the other is also present; additionally, the number of entries in each array will always match.

Each entry in Functions stores auxiliary information shared amongst nodes that describe source-location, name, line number, and the total aggregate time spent in the function, as well as additional flags. A function entry will always have a TotalDuration field. Source, Name, and Line are optional; they are only present when the profiler has access to the corresponding information.

A function may also have a Flags integer. This is a bitfield with the following potential bits:

0 IsNative; if set, this function was executed via NativeCodeGen
1 IsPlugin; if set, this function (and its descendants) was executed as part of a plugin

Flags uniquely identify a function. There may more than one function entry for the same exact function if one Lua thread had executed that function under NativeCodeGen, and another that had executed the function via the LuauVM interpreter.

Hide GC Overhead and Plugin Scripts

We will additionally have checkboxes that toggle hiding time spent in garbage collection, and time spent in plugin scripts. Timings displayed across the callgraph will adjust accordingly.

Coming Later

We are planning to make available a public API for plugin tools to control the profiler and access profiling data. We will have more details on this API in the near future.

Feedback

We are continuously considering feedback and requests to improve ScriptProfiler. Feel free to suggest improvements and report issues in the thread below.

131 Likes

This topic was automatically opened after 11 minutes.

Wow, these updates look awesome! Kudos to the team, I’m excited to make use of this.

5 Likes

So excited for this

Great job to all teams involved!

6 Likes

When will documentation be updated for the Developer Console page? (Developer Console | Documentation - Roblox Creator Hub) It is severely out-of-date and only includes the Log, Memory, and Network tabs. While documentation may exist for this specific feature, developers who are looking at the console in general will see information that is old, and not very useful.

12 Likes

That’s pretty cool, but I don’t use the Developer Console that much, sorry.
Good job anyways! :smiley:

7 Likes

Loving this update. Can’t wait for occlusion culling :pray:

10 Likes

this is great for our services

4 Likes

Yeah, there needs to be a significant increase in resources for learning these tools.

3 Likes

I’ve been coding on this website for 6+ years and I still have no idea how to use this lol

6 Likes

I would really appreciate if the developer console’s UI was remade. As it stands now, it’s especially hard to read with all the contrasting white lines. It would also be nice if it respected the background opacity user setting!

Another thing, there’s barely any documentation on most of the developer console features. Your left to just figure them out, which can be challenging. Personally, I have no idea what the script profiler does. Infact, all I know how to use is the output, and the rest is just noise.

9 Likes

Ty, would pair up nicely with the micro profiler.

2 Likes

This will make performance issues even easier to solve. Thanks for these recent changes!

1 Like

very nice
hopefully roblox adds more features like this instead of keeping you locked out of “advanced” stuff like buffers

1 Like

Fab changes! This will make debugging laggy scripts a ton easier

Hey I would love to make use of these changes on low-performing phone devices, however the Start button is obscured by various other options. Can this please be fixed?

This issue has now been fixed and we are continuing to work on additional improvements to the UI.