20 min

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 top bar rendered by the MicroProfiler

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:

A spike in the MicroProfiler frames graph

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.

The MicroProfiler timeline, zoomed in on the main thread

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.

The MicroProfiler graph, created by clicking on a label (in this example, a physics label was clicked


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.

Custom Profiling

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

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.profilebegin and 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
	debug.profileend() -- Stop profiling here

Running the game and pausing the profiler (Ctrl+P), the custom profiler label is visible under the Stepped label:

A custom MicroProfiler label "Hard work", created by the code above

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.

The mobile settings menu, showing the MicroProfiler switch set to on. The device's network IP address is shown at the bottom.

For example, in the screenshot above, the address is and the port is 1338. In the web browser of a computer connected to the same network, you would navigate to A similar interface as the one seen on non-mobile devices is shown:

The browser-based MicroProfiler used with mobile devices

  • performance