The MicroProfiler is an optimization tool available in Roblox Studio and the Roblox Client that provides detailed timing information for
articles/Task Scheduler processes. This information is very useful when debugging performance issues in games. To open the MicroProfiler interface, pressing Ctrl+Alt+F6 in Studio or the Client.
Using the MicroProfiler
When open, a menu bar is visible at the top of the game view. Under it, there is a moving bar graph which reflects the time used on each frame of the Task Scheduler as they pass – the most recent frames appear on the right, and flow to the left.
The orange bars indicate the processing time each frame is taking. They should generally be around the middle of the graph, but while the game is running you may see the bars spike or increase in value. This indicates that more time was taken to perform some Task Scheduler process, usually because of an increased workload. For instance, creating a lot of moving parts puts more work on the physics simulation, and therefore more time is used to process motion and part contacts. The following image shows an example of a spike:
To pause the recording of frames, press Ctrl+P. While paused, a timeline appears over the game view, and you can navigate through frames by clicking on the graph, or dragging on the interface. Scrolling will zoom on the timeline. You’ll see colorful labels describing different tasks being performed; labels that appear directly underneath another label indicate that a task is performed during another task.
Right-click a label to zoom the timeline to exactly the duration of the label. Left-click it to add the label to a line graph at the bottom right of the game view. The graph will show the time the task is taking each frame. Using this graph, you can test the performance of only certain labels in your game. Multiple labels can be added, and you can hide the graph by right-clicking it.
Like many programs, Roblox uses multiple threads to perform several sequences of tasks at the same time. In the MicroProfiler timeline, you can see labels for these on the left. There are three types of threads:
- Main: Processes input, Humanoids, animations/tweening, physics ownership, sound, waiting script resumes, updates Studio interfaces (Explorer, Properties), and coordinates the other threads.
- Worker (“TSMk2 worker”): Helps main thread with networking, physics and pathfinding.
Multiple are used depending on the number of processor cores.
- Render (“GPU”): Follows a prepare, perform, present logic. Communicates with the graphics processing unit (GPU) of the device.
- Prepare: Information from the main thread is used to update rendering models.
- Perform: Issue rendering commands, including 2D interfaces.
- Present: Synchronizes with the GPU.
If your scripts are doing complicated tasks, then you’ll want to profile critical points to ensure a reasonable amount of time is being used. You can do this by calling
debug.profilebegin followed by
debug.profileend, which times everything done between these two function calls. This creates a label on the MicroProfiler timeline.
debug.profilebegin("Hard Work") -- Here is where the code to be profiled should be debug.profileend()
Be aware that there is a limited amount of memory available to MicroProfiler labels, so sometimes custom profiler labels may not appear as a meaningful name if this memory runs out. Using less labels will avoid this. If you no longer need to profile a section of your code, you should comment out or remove calls to these functions as they provide no other benefit except during debugging.
The code sample below connects a dummy function to the
RunService/Stepped event, which runs every frame. Anything done this often should run as efficiently as possible, so calls to
debug.profileend have been added around the code to be profiled.
local RunService = game:GetService("RunService") local function onStepped() debug.profilebegin("Hard work") -- Start profiling here with this label -- Example hard work: swap two variables 200,000 times local a, b = 0, 1 for i = 1, 200000 do a, b = b, a end debug.profileend() -- Stop profiling here end RunService.Stepped:Connect(onStepped)
Running the game and pausing the profiler (Ctrl+P), the custom profiler label is visible under the Stepped label:
It’s clear that this function is using a lot of performance needlessly: if this were real code, looking here for optimization opportunities would be a good start. However, this is a contrived example that does meaningless work to emphasize the label.
Profiling on Mobile Devices
You can enable the MicroProfiler via the Settings menu. Using a mobile device connected to the same network as your development machine, you can access a browser-based MicroProfiler. Once enabled, the network IP address of the device is displayed along with a port number.
For example, in the screenshot above, the address is
192.168.1.166 and the port is
1338. In the web browser of a computer connected to the same network, you would navigate to
http://192.168.1.166:1338. A similar interface as the one seen on non-mobile devices is shown: