mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
update rules
This commit is contained in:
parent
4c390fdd37
commit
d5522b2fef
8549 changed files with 11783 additions and 1888 deletions
|
|
@ -0,0 +1,264 @@
|
|||
---
|
||||
title: MicroProfiler
|
||||
description: The MicroProfiler is a Studio and client tool for optimizing your experience.
|
||||
---
|
||||
|
||||
The **MicroProfiler** is a performance optimization and troubleshooting tool in Roblox Studio and the Roblox client. It provides detailed, visual timing information for all the [engine tasks](task-scheduler.md) that run during a frame, like animating characters, updating physics, running scripts, and rendering geometry. You can identify which tasks ran during which frame, how long these tasks took to run, and whether any caused you to miss your frame time goals.<br />
|
||||
|
||||
<Grid container spacing={2} style={{ marginBottom: 24, width: '100%' }}>
|
||||
<Grid item xs={6} style={{ padding: 16 }}>
|
||||
<Grid item container wrap="nowrap" direction="column" style={{ gap: 8, flex: 1 }}>
|
||||
|
||||
<div
|
||||
className="container"
|
||||
style={{ position: "relative", paddingBottom: "56.25%", height: 0, marginBottom: 12 }} >
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/XLCZfGEm9tU?si=d992GKSU7oveIrhd"
|
||||
title="YouTube video player"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowFullScreen
|
||||
style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }} ></iframe>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={6} style={{ padding: 16 }}>
|
||||
<Grid item container wrap="nowrap" direction="column" style={{ gap: 8, flex: 1 }}>
|
||||
|
||||
<div
|
||||
className="container"
|
||||
style={{ position: "relative", paddingBottom: "56.25%", height: 0, marginBottom: 12 }} >
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/eWf-6Sh-9Os?si=GZYvQw6ZvQiZF1uv"
|
||||
title="YouTube video player"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowFullScreen
|
||||
style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }} ></iframe>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
## Frame times
|
||||
|
||||
To use the MicroProfiler, you must understand the relationship between **frame time** and **frame rate**.
|
||||
|
||||
- Frame time is how long a frame took to render on screen, generally measured in milliseconds.
|
||||
- Frame rate is the number of frames rendered on screen, generally measured in frames per second (FPS).
|
||||
|
||||
Lower frame times mean higher frame rate. Divide 1,000 milliseconds (1 second) by frame time to get frame rate.
|
||||
|
||||
Average frame time | Frames per second
|
||||
:--- | :---
|
||||
33.33 ms | 30 FPS
|
||||
16.67 ms | 60 FPS
|
||||
8.33 ms | 120 FPS
|
||||
4.17 ms | 240 FPS
|
||||
|
||||
For smooth gameplay, however, it's not enough to have a high frame rate. You need **consistent frame times**. For example, if 59 frames arrive in 10 milliseconds and one frame in 410 milliseconds, players perceive a huge, jarring stutter, even though the experience is running at 60 FPS. If all frames take roughly the same amount of time to render, your experience will feel perceptibly smoother due to that consistency, especially at lower frame rates.
|
||||
|
||||
The MicroProfiler focuses **entirely on frame time**. Its purpose is to help you identify frame time spikes and what caused them.
|
||||
|
||||
## Open the MicroProfiler
|
||||
|
||||
Opening the MicroProfiler varies by platform:
|
||||
|
||||
- On the mobile client, open the **Settings** menu and change the MicroProfiler to **On**. Then from a development machine **on the same network**, use your web browser to navigate to the provided IP address and port.
|
||||
|
||||
<img alt="The MicroProfiler UI on mobile." src="../../assets/optimization/microprofiler/micro-mobile.png" width="700px" />
|
||||
|
||||
This screenshot shows an IP address of `172.18.56.105` and a port of `1338`, so you navigate to `172.18.56.105:1338`. Depending on your device's network configuration, you might see multiple IP addresses. If one doesn't work, try the next.
|
||||
|
||||
<Alert severity="info">
|
||||
By default, the MicroProfiler web UI shows the 30 most recent frames from your mobile device. For a larger set of frames, add a slash and a number to the URL, such as `172.18.56.105:1338/90`. To get a fresh set of frames, use the **Re-capture** button.
|
||||
</Alert>
|
||||
|
||||
- On the desktop client, press <kbd>Ctrl</kbd><kbd>F6</kbd> (<kbd>⌘</kbd><kbd>F6</kbd>).
|
||||
- In Studio, press <kbd>Ctrl</kbd><kbd>F6</kbd> (<kbd>⌘</kbd><kbd>F6</kbd>).
|
||||
|
||||
Generally, the mobile client is the best place to profile your experience. Most players on Roblox use phones and tablets, and these devices have severe thermal and power constraints that limit their performance. If your experience runs well on a midrange Android tablet, it almost certainly performs much, much better on a gaming desktop.
|
||||
|
||||
<Alert severity="success">
|
||||
Powerful devices like gaming desktops can actually obscure performance problems, especially if you have a frame rate cap in place. For example, if you cap FPS to 60 on the client, you might not notice the difference between a frame time of 4 milliseconds and 16 milliseconds, even though the latter is four times as long, because they all arrive in under 16.67 milliseconds. On a mobile device that is struggling to stay at 30 FPS, a frame that takes four times as long (133 ms) is hard to miss.
|
||||
</Alert>
|
||||
|
||||
## MicroProfiler basics
|
||||
|
||||
The MicroProfiler has two key components: the **frame time bar graph** and the **detailed task timeline**.
|
||||
|
||||
- The frame time graph runs along the top of the interface and shows how long each frame took to render. Taller bars mean longer frame times.
|
||||
- The timeline shows all of the individual tasks that ran during the frame. Wider bars represent tasks that took longer to run.
|
||||
|
||||
A typical workflow in the MicroProfiler is to use the frame time graph to identify a spike (a taller bar) and then use the timeline to identify which tasks caused the spike. Then you can check the [Tag reference](tag-table.md) for information on the task and how to improve its performance.
|
||||
|
||||
<img alt="Example of a frame time spike." src="../../assets/optimization/microprofiler/micro-spike.png" width="600px" />
|
||||
|
||||
### Frame time graph
|
||||
|
||||
The height of each bar indicates the number of milliseconds that it took to complete the frame. More recent frames are on the right. Hover over a frame for some basic information around CPU and GPU usage.
|
||||
|
||||
<img alt="The Microprofiler frame graph, showing blue frames and detailed frame information." src="../../assets/optimization/microprofiler/micro-frames.png" width="500px" />
|
||||
|
||||
- Orange bars are frames where the **Jobs Wall Time** exceeds the **Render Wall Time**. In these frames, at least one of the [worker threads](#threads), which do things like run scripts, calculate physics, and play animations, took longer to run than the [main render thread](#threads).
|
||||
|
||||
If the experience is not reaching your frame time goals and has a large number of orange frames, common causes are scripts, physics, and animations. See [Improve performance](../../performance-optimization/improve.md#script-computation).
|
||||
|
||||
- Blue bars are frames where the **Render Wall Time** exceeds the **Jobs Wall Time**. In these frames, the main render thread took more time than any of the worker threads.
|
||||
|
||||
If the experience is not reaching your frame time goals and has a large number of blue frames, that indicates a rendering bottleneck. Common causes are excessive object density, object movement, and lighting. See [Improve performance](../../performance-optimization/improve.md#rendering).
|
||||
|
||||
- Red bars are frames where two conditions are true:
|
||||
|
||||
- **Render Wall Time** exceeds **Jobs Wall Time**
|
||||
- **GPU Wait Time** is greater than 2.5 milliseconds
|
||||
|
||||
Red bars are less common than orange and blue and often the result of excessive object complexity, texture size, and visual effects. Optimization is similar to blue bars. See [Improve performance](../../performance-optimization/improve.md#rendering).
|
||||
|
||||
Tiny tasks at the end of a frame can sometimes throw off the **Jobs Wall Time** and **Render Wall Time**, which is a good reason to focus more on frame time than frame color. There's no "good" color to strive for. A mixture of orange, blue, and red isn't problematic as long as you're reaching your frame time goals. If you **aren't** reaching your frame time goals, the colors can indicate where to optimize.
|
||||
|
||||
### Timeline
|
||||
|
||||
- Left-click and drag to pan the timeline. On a machine with many CPU cores, you might need to pan up or down quite a bit to find the [thread](#threads) performing a particular task.
|
||||
|
||||
<img alt="The lefthand side of the Microprofiler detailed view, with rows for threads." src="../../assets/optimization/microprofiler/micro-panning.png" width="700px" />
|
||||
|
||||
- Scrolling zooms the timeline in and out. Combined with the millisecond labels at the top of the timeline, you can get a sense of how long a task took in an absolute sense, but also how long it took relative to other tasks.
|
||||
|
||||
<img alt="The Microprofiler detailed view with numerous horizontal labels." src="../../assets/optimization/microprofiler/micro-timeline.png" width="500px" />
|
||||
|
||||
- The green overlay on the bar graph indicates the number of frames currently visible on the timeline—your zoom level. Left-click on a frame bar to jump to that position on the timeline.
|
||||
|
||||
You might have to adjust your zoom level, but hovering over a bar highlights the frame on the timeline. Light grey lines delineate frames.
|
||||
|
||||
<img alt="The MicroProfiler bar graph with green overlay to show zoom level." src="../../assets/optimization/microprofiler/micro-detailed.png" width="600px" />
|
||||
|
||||
- Labels that appear directly below another label indicate tasks that are performed as part of the higher-level task.
|
||||
|
||||
Rather than the parent task, you typically want to troubleshoot the worst-performing child tasks; a parent task can't be shorter than the sum of its child tasks.
|
||||
|
||||
- Right-click a label to zoom the timeline to exactly the duration of that task.
|
||||
|
||||
- If the amount of information is overwhelming, use the **Groups** or **Threads** menu to filter the timeline. For example, you might only want to see **Render** tasks in the main thread.
|
||||
|
||||
<img alt="The on-hover view for a label, with Group highlighted." src="../../assets/optimization/microprofiler/micro-group.png" width="500px" />
|
||||
|
||||
- Use <kbd>Ctrl</kbd><kbd>F</kbd> (<kbd>⌘</kbd><kbd>F</kbd>) to jump to the occurrence of a task that takes up the most time in the dump. For example, `computeLightingPerform` runs in every client frame. If you search for it in a dump with 128 frames, you can jump to the frame where it took the longest to complete.
|
||||
|
||||
## Threads
|
||||
|
||||
Like many programs, Roblox uses multiple threads to perform sequences of tasks at the same time. The MicroProfiler displays the thread name on the lefthand side of the timeline.
|
||||
|
||||
<img alt="The lefthand side of the Microprofiler detailed view, with rows for threads." src="../../assets/optimization/microprofiler/micro-panning.png" width="600px" />
|
||||
|
||||
There are three important thread types:
|
||||
|
||||
- **Main** ("RBX Main"): Handles CPU-based rendering tasks. Processes input, `Class.Humanoid|Humanoids`, animations/tweening, physics ownership, sound, and waiting script resumes. Also updates Studio interfaces and coordinates the other threads.
|
||||
|
||||
- **Worker** ("RBX Worker"): Helps the main thread with networking, physics, and pathfinding. Due to the number of cores in modern CPUs, you likely have many worker threads, most of which are in a sleep state at any given time.
|
||||
|
||||
- **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 script profiles
|
||||
|
||||
If your scripts are running complicated tasks, you can profile critical portions of the code to ensure that they're not taking too long. Wrap code with `Library.debug.profilebegin()` and `Library.debug.profileend()` to time everything done between those function calls and create a label on the MicroProfiler timeline.
|
||||
|
||||
```lua
|
||||
local RunService = game:GetService("RunService")
|
||||
|
||||
local function onPreSimulation()
|
||||
debug.profilebegin("Hard Work")
|
||||
-- Example hard work: swap two variables 200,000 times
|
||||
local a, b = 0, 1
|
||||
for _ = 1, 200000 do
|
||||
a, b = b, a
|
||||
end
|
||||
debug.profileend()
|
||||
end
|
||||
RunService.PreSimulation:Connect(onPreSimulation)
|
||||
```
|
||||
|
||||
<img alt="Many labels on the MicroProfiler, with a custom label taking up the majority of the processing time." src="../../assets/optimization/microprofiler/custom-profile.png" width="500px" />
|
||||
|
||||
From its duration on the timeline, you can tell that the function is using a lot of processing time compared to other tasks.
|
||||
|
||||
## Save frame data
|
||||
|
||||
If you want to save a set of frame data for later review (or to share with someone else), use the **Save to file** button. The MicroProfiler saves frame data to a standalone HTML file named `microprofile-<date>-<time>.html`.
|
||||
|
||||
<img alt="The save to file button in the web UI." src="../../assets/optimization/microprofiler/micro-save-to-file.png" width="700px" />
|
||||
|
||||
On the desktop client or in Studio, use the **Dump** menu. In both cases, the MicroProfiler automatically saves the file to the Roblox logs directory:
|
||||
|
||||
- On Windows, check `%LOCALAPPDATA%\Roblox\logs`.
|
||||
|
||||
If you use the Universal Windows Platform (UWP) app, check `\Users\<username>\AppData\Local\Packages\ROBLOXCORPORATION.ROBLOX_<hash>\LocalState\logs\`.
|
||||
|
||||
- On macOS, check `~/Library/Logs/Roblox`.
|
||||
|
||||
<Alert severity="info">
|
||||
Dumps only contain data for the selected number of frames, **not** the entire duration that the experience has been running. The exception is [counters mode](modes.md#counters-mode), which includes data from when Studio or the client started running to the time of the dump.
|
||||
</Alert>
|
||||
|
||||
## Profile the server
|
||||
|
||||
In addition to profiling the client, you can capture brief dumps of server activity:
|
||||
|
||||
1. On the desktop client, join an experience that you have edit permissions for.
|
||||
1. Open the Developer Console with <kbd>Ctrl</kbd><kbd>F9</kbd> (<kbd>⌘</kbd><kbd>F9</kbd>).
|
||||
1. In the dropdown menu, select **MicroProfiler**.
|
||||
1. In the **Server** tab, specify the number of frames to capture (maximum 60) and the number of seconds to delay before starting the capture (maximum 4).
|
||||
1. Click **Begin server recording**.
|
||||
|
||||
<img alt="The Developer Console MicroProfiler screen." src="../../assets/optimization/microprofiler/micro-server.png" />
|
||||
|
||||
After a few seconds, the Developer Console provides the path to the file, which is the same path as a [standard dump](#save-frame-data).
|
||||
|
||||
## Web-only features
|
||||
|
||||
The MicroProfiler has two user interfaces: the web UI (mobile and dumps) and the desktop UI (client and Studio). We recommend using the web UI whenever possible. In general, the two work similarly, but the web UI has a few extra features:
|
||||
|
||||
- Use the **X-Ray** menu to enable or disable color coding for memory allocation.
|
||||
|
||||
<img alt="The MicroProfiler web view with x-ray enabled." src="../../assets/optimization/microprofiler/micro-xray.png" width="600px" />
|
||||
|
||||
- Lighter frames within the main bar graph indicate higher memory allocation.
|
||||
- Lighter portions of the preview bar and lighter labels on the timeline indicate portions of the frame with higher memory allocation.
|
||||
- In X-ray mode, press <kbd>C</kbd> to show the total size of the memory allocations rather than the number of allocations.
|
||||
|
||||
- Use the **Export** menu to export a CPU or memory flame graph, a specialized visualization that aggregates all of the call stacks included in the dump, maintains the parent-child hierarchy, and sizes them based on duration. Flame graphs are especially useful for identifying tasks that don't cause you to miss your frame time goals (and are therefore hard to notice), but run so often that their processing time becomes significant.
|
||||
|
||||
<img alt="The MicroProfiler flame graph in the web UI." src="../../assets/optimization/microprofiler/micro-flame.png" />
|
||||
|
||||
You can also create flame graphs in Studio, although only for scripts (execution time and memory allocations). Compared to the web-based flame graphs, the ones in Studio are top-down rather than bottom-up and support dramatically longer capture times.
|
||||
|
||||
<img alt="The MicroProfiler flame graph in Studio." src="../../assets/optimization/microprofiler/micro-studio-flame.png" />
|
||||
|
||||
- Drag and drop a second dump file into the web UI to generate a diff flame graph, which can help you identify improvements or regressions to your experience's performance over time. Click **Combine & Compare** to export a new HTML file.
|
||||
|
||||
<img alt="The MicroProfiler diff flame graph builder showing the left and right sides." src="../../assets/optimization/microprofiler/micro-flame-diff.png" />
|
||||
|
||||
<Alert severity="success">
|
||||
You can combine several dump files—for example, four on each side, from before and after a major update—to get a more aggregated comparison. Comparing data between different places can be useful, too, but don't **combine** data from different places!
|
||||
</Alert>
|
||||
|
||||
The diff flame graph highlights the dump (left or right) that consumes more CPU or memory, with brighter colors indicating a larger difference.
|
||||
|
||||
<img alt="The MicroProfiler diff flame graph." src="../../assets/optimization/microprofiler/micro-flame-diff2.png" />
|
||||
|
||||
## Desktop-only features
|
||||
|
||||
On the desktop timeline, left-click a label to add it to a line graph in the bottom-right. The graph shows the time the task takes each frame. Using this graph, you can test the performance of only certain tasks in your experience. When you're done, right-click the graph to hide it.
|
||||
|
||||
<img alt="The graph showing how long tasks take per frame." src="../../assets/optimization/microprofiler/micro-graph.png" width="300px" />
|
||||
|
||||
This graph is synchronized with the main profiler bars. The currently selected frame range is highlighted in green on the graph. You can also click anywhere on this graph to re-center the main profiler view to that specific frame, which is helpful for finding spikes in the detailed view.
|
||||
|
||||
<Alert severity="info">
|
||||
Use the **Options** menu to change the reference line on the graph to a different number of milliseconds.
|
||||
</Alert>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: MicroProfiler modes
|
||||
description: The MicroProfiler includes several different modes, all of which .
|
||||
---
|
||||
|
||||
The MicroProfiler includes several modes, which can help you visualize your experience's performance characteristics in different ways. After opening the MicroProfiler, use the **Modes** menu to switch between them.
|
||||
|
||||
**Frame mode** and **detailed mode** are covered under [MicroProfiler basics](index.md#microprofiler-basics).
|
||||
|
||||
## Timers mode
|
||||
|
||||
**Timers mode** is an alternative way of visualizing the data in the detailed view: as a list of labels with processing times and call counts. Horizontal bar graphs in some columns help you spot the busiest tasks.
|
||||
|
||||
<img alt="Timers mode." src="../../assets/optimization/microprofiler/micro-timers-mode.png" width="600px" />
|
||||
|
||||
Controls are similar to detailed view:
|
||||
|
||||
- Left-click and hold to pan up and down.
|
||||
- Left-click a label to add it to the line graph in the lower-right.
|
||||
- Use the **Groups** menu to filter the list.
|
||||
- Use the **Timers** menu to customize the columns.
|
||||
|
||||
<Alert severity="info">
|
||||
All of the information in this view is visible when you hover over a label in the detailed view.
|
||||
</Alert>
|
||||
|
||||
## Counters mode
|
||||
|
||||
Counters mode is a lengthy list of categories and statistics, including instance count and memory usage (in bytes) for the various tasks.
|
||||
|
||||
<img alt="Counters mode with a single graph." src="../../assets/optimization/microprofiler/micro-counters-mode.png" width="400px" />
|
||||
|
||||
- Just like the detailed view, left-click and hold to pan up and down.
|
||||
- Left-click in the **Graph** column to add a small usage graph with minimum and maximum values. Left-click the graph again to expand it.
|
||||
- Right-click a graph to close it.
|
||||
- You can't filter this view, but you can left-click on a category (for example, `memory`) to collapse it.
|
||||
|
||||
While counters mode can be useful, the [Developer Console](../../studio/optimization/memory-usage.md) is the best way to [identify memory issues](../../performance-optimization/identify.md#client-memory). You might also find the [X-ray view](index.md#web-only-features) helpful for identifying when problematic memory allocation occurs.
|
||||
|
||||
## Groups mode
|
||||
|
||||
Only available in the web UI. Similar to timers mode, groups mode provides average, max, and total task times for each group, broken down by thread, to help you identify how broad categories of tasks are impacting your frame times.
|
||||
|
||||
<img alt="MicroProfiler web UI showing groups mode." src="../../assets/optimization/microprofiler/micro-groups-mode.png" width="600px" />
|
||||
|
||||
## Threads mode
|
||||
|
||||
Only available in the web UI. Similar to timers mode, threads mode provides average and total task times for each thread, broken down by group, to help you identify how your experience is distributing tasks across threads.
|
||||
|
||||
<img alt="MicroProfiler web UI showing threads mode." src="../../assets/optimization/microprofiler/micro-threads-mode.png" width="600px" />
|
||||
|
||||
## Hidden mode
|
||||
|
||||
Only available in the desktop UI. Hidden mode keeps the MicroProfiler menu open, but hides the bar graph. It's useful for reducing visual clutter, [saving frame data](index.md#save-frame-data), and pausing and unpausing while you observe the line graph.
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
title: Network usage
|
||||
description: The MicroProfiler provides detailed information on network usage within your experience.
|
||||
---
|
||||
|
||||
The MicroProfiler also lets you capture and view network traffic, which can help you identify causes of high latency and loading problems in your experiences.
|
||||
|
||||
Network data is available **only in frame dumps from the desktop client or Studio**, not in the real-time overlay. If you encounter lag or other issues that you suspect are network-related, that's a great time to [save MicroProfiler data](index.md#save-frame-data).
|
||||
|
||||
## Capture network data
|
||||
|
||||
1. Open the MicroProfiler with <kbd>Ctrl</kbd><kbd>Alt</kbd><kbd>F6</kbd> or <kbd>⌘</kbd><kbd>⌥</kbd><kbd>F6</kbd>.
|
||||
|
||||
1. In the **Network** menu, choose **High**, **Low**, or **Off**.
|
||||
|
||||
- **High** includes additional information on the items within a batch data packet, the task that deserialized the packet, and the asset ID for any assets in the request or response.
|
||||
|
||||
- **Low** captures less data and is not as computationally intensive. Depending on your computer, selecting it can help your dumps contain a larger number of frames. This is the default level and the one the MicroProfiler uses when you [profile a mobile device](index.md#profile-mobile-devices).
|
||||
|
||||
- **Off** means that network data is not included in frame dumps.
|
||||
|
||||
1. [Save MicroProfiler frame data](index.md#save-frame-data) and open the generated HTML file.
|
||||
|
||||
## Basic navigation
|
||||
|
||||
After you open the MicroProfiler dump in a web browser, select **X-Ray** / **Network**. Two more rows appear below the frame time graph:
|
||||
|
||||
- The top row is received traffic (downloads).
|
||||
- The bottom row is sent traffic (uploads).
|
||||
|
||||
<img alt="Overview of the network graphs." src="../../assets/optimization/microprofiler/micro-network.png" width="750px" />
|
||||
|
||||
Because network traffic can vary dramatically between frames, you might see a couple spikes and seemingly very little else. In this case, select **Options** / **Log Scale Graph** to change the scaling of the bars such that they scale logarithmically rather than linearly, which makes small bars more prominent.
|
||||
|
||||
The stacked bars are colored not by severity, but by type of traffic: physics in blue, data in green, and assets in red. Hover over any bar to get the amount of received or sent traffic for that frame. Right-click to show the **Network events** window, which shows much more detailed information.
|
||||
|
||||
## Network events window
|
||||
|
||||
The **Network events** window shows individual events within the scope of the frame. Click on any event for more detailed information.
|
||||
|
||||
<img alt="Overview of the network graphs." src="../../assets/optimization/microprofiler/micro-network-events.png" width="450px" />
|
||||
|
||||
Available information depends on the type of packet and verbosity level:
|
||||
|
||||
- **Engine network batch data** includes traffic due to streaming, instance property updates, and events. If you chose high verbosity, the batch data expands to show individual items. At low verbosity, you only get the summary.
|
||||
|
||||
- At high verbosity, click an Engine network packet to zoom in on the task that deserialized the packet.
|
||||
- Regardless of verbosity level, click any other Engine network event to show information such as size, direction, and type.
|
||||
|
||||
- Compared to Engine network events, **HTTP asset delivery** shows some additional information, including batch size (if the request was batched) and the number of queued HTTP requests (if applicable). If you chose high verbosity, it also includes asset IDs for any assets in the request.
|
||||
|
||||
- Click the asset ID to zoom in on the task where the next step in fetching that asset took place.
|
||||
- Click the **+** to view the asset on the Creator Store.
|
||||
|
||||
<img alt="Overview of the network graphs." src="../../assets/optimization/microprofiler/micro-network-asset.png" width="450px" />
|
||||
|
||||
## Additional graphs
|
||||
|
||||
Depending on the data included in the frame dump, you can view additional graphs below the standard download and upload graphs:
|
||||
|
||||
- Asset fetching
|
||||
- Data
|
||||
- Large replicator data (async and chunked data)
|
||||
- Physics
|
||||
- Terrain
|
||||
|
||||
Click any category in the legend to add these graphs, which provide dedicated views into each packet type. Each graph defaults to showing received traffic (Rx), but you can use the label in the upper-left of any of the three graphs to swap to sent traffic (Tx).
|
||||
|
||||
<img alt="Overview of the network graphs." src="../../assets/optimization/microprofiler/micro-network-extra.png" width="750px" />
|
||||
|
|
@ -0,0 +1,450 @@
|
|||
---
|
||||
title: Tag reference
|
||||
description: A list of tags for the MicroProfiler.
|
||||
---
|
||||
|
||||
The following is a list of common tags in the [MicroProfiler](./index.md), grouped by category. Tags are also interchangeably called tasks, timers, scopes, processes, and labels. Whatever the name, they represent a unit of work.
|
||||
|
||||
Understanding these tags can help you identify problematic code in your experience. The tables contain tag label, descriptions, and advice for improving performance and optimizing your experience.
|
||||
|
||||
## Sleep
|
||||
|
||||
When threads aren't actively performing tasks, they enter a sleep state, with tags to indicate how long the thread was sleeping. At any given time, it's extremely common for most worker threads to be in a sleep state.
|
||||
|
||||
## Navigation
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>rasterizeTile</td>
|
||||
<td>Updates navigation tiles needed for a pathfinding request, usually followed by **computePath** which requires those tiles be up-to-date. Follows **NavigationJob/preprocess** on the main thread.</td>
|
||||
<td>Reduce the number of pathfinding tile invalidations, as this causes those paths to need recomputing. This is caused by non-navigable parts moving.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>computePath</td>
|
||||
<td>
|
||||
Calculates paths, typically after **rasterizeTile**.
|
||||
</td>
|
||||
<td>Reduce the number and world extents of `Class.Path:ComputeAsync()` calls. Try reusing paths for multiple agents if they are expected to start/end from approximately similar locations.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>preprocess/getPrimitivesOverlapping</td>
|
||||
<td>Collects the world geometry for each pathfinding tile and schedules the rasterization tasks to be executed by the pathfinding thread.</td>
|
||||
<td>Reduce the part count.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Animation and humanoids
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Simulation/gameStepped</td>
|
||||
<td>Processing of experience-specific objects such as `Class.Humanoid|Humanoids`, `Class.Animation|Animations` and heartbeat callbacks.</td>
|
||||
<td>See **gameStepped** labels below.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/gameStepped/stepHumanoid</td>
|
||||
<td>`Class.Humanoid` state changes and movement.</td>
|
||||
<td>Reduce the amount of `Class.Humanoid|Humanoids` or humanoids with `Class.Humanoid.EvaluateStateMachine` enabled. Disable `Class.Humanoid` states on NPCs that don't need them, such as `Enum.HumanoidStateType|Climbing` or `Enum.HumanoidStateType|Swimming`. Reduce callbacks to `Class.Humanoid.StateChanged` or state changes such as `Class.Humanoid.Running|Running` or `Class.Humanoid.Died|Died`.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/gameStepped/stepAnimation</td>
|
||||
<td>`Class.Animator|Animators` will step forward in currently playing animations.</td>
|
||||
<td>Reduce the amount of `Class.Animator|Animators` or animated joints to lower the workload of this step. Reduce number of callbacks to animation events such as `Class.AnimationTrack.KeyframeReached` or `Class.AnimationTrack.Ended`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/gameStepped/RunService.Stepped</td>
|
||||
<td>Runs functions connected to the `Class.RunService.Stepped` event.</td>
|
||||
<td>Reduce the amount or workload of functions connected to this event. Consider delaying or replacing expensive calculations or spreading computation across multiple frames.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Audio
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Sound</td>
|
||||
<td>Processes acoustic simulation and updates sounds in active playback.</td>
|
||||
<td>See **Sound** labels below.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sound/stepInstances</td>
|
||||
<td>Updates the volume of active sounds in the workspace.</td>
|
||||
<td>Reduce the amount of sounds in active playback.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Networking
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Net PacketReceive</td>
|
||||
<td>Receives network packets. If many objects or events are being replicated, this step takes longer. </td>
|
||||
<td>Replicate fewer objects or events.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Replicator/ProcessPackets</td>
|
||||
<td>Processes contents of network packets, such as motion, event invocations and property changes. </td>
|
||||
<td>Reduce the number or size of objects being replicated, or do this in incremental steps. May increase if map size increases, as larger maps tend to have more overall activity.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Allocate Bandwidth and Run Senders/Dispatch Physics Senders and TouchSenders</td>
|
||||
<td>Sends data about activity in the experience.</td>
|
||||
<td>Reduce the amount of moving objects and/or touches. See following sections.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Allocate Bandwidth and Run Senders/Dispatch StreamJob</td>
|
||||
<td>Sends corresponding specific regions to specific clients in the streaming feature.</td>
|
||||
<td>Reduce the minimum and target streaming radii.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Allocate Bandwidth and Run Senders/Dispatch Data Senders</td>
|
||||
<td>Sends property changes, remote event invocations, `Class.Humanoid` state changes, animation state changes, and replication of new instances.</td>
|
||||
<td>Reduce the number of replicated changes to the data model.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Replicator SendCluster</td>
|
||||
<td>Sends [Terrain](../../parts/terrain.md) data to clients.</td>
|
||||
<td>Reduce the amount or size of terrain changes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ModelCompleteness Mega Job</td>
|
||||
<td>Server only: completeness is an internal concept. When models are completely sent, model completeness events are sent.</td>
|
||||
<td>Add or remove fewer instances.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>deserializePacket</td>
|
||||
<td>Low-level network packet processing. Prepares for **Replicator/ProcessPackets**.</td>
|
||||
<td>Send fewer or smaller updates.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Rendering
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Prepare</td>
|
||||
<td>Information is gathered from the main thread and updates various data structures used for rendering.</td>
|
||||
<td>See **Prepare** labels below.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prepare/Pass3dAdorn</td>
|
||||
<td>Handles rendering of various object adorns, such as text labels above objects. For `Class.Humanoid` labels with occlusion, this step includes raycasting to determine if such objects are visible. This includes non-transparent parts to facilitate debug visualizations.</td>
|
||||
<td>Reduce the number of visible adorned objects, such as `Class.BillboardGui|BillboardGuis`, `Class.Humanoid` name/health labels, etc. Reduce the number of visible parts.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prepare/Pass2d</td>
|
||||
<td>Readies 2D UI rendering (both player and Roblox UI).</td>
|
||||
<td>Reduce the amount or complexity of UI elements.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prepare/UpdatePrepare/updateInvalidParts</td>
|
||||
<td>Updates parts that had some property changed or added.</td>
|
||||
<td>Reduce the amount of properties changes on the world. If a script updates a large set of object properties, break it down across frames.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prepare/UpdatePrepare/updateInvalidatedFastClusters</td>
|
||||
<td>Prepares "FastCluster" geometries used to render `Class.Humanoid|Humanoids` and [skinned](../../art/modeling/rigging.md) `Class.MeshPart|MeshParts`. Labels specify the number of parts, vertices, and size of vertices.</td>
|
||||
<td>Reduce visual changes to models with `Class.Humanoid|Humanoids` or skinned `Class.MeshPart|MeshParts`.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prepare/UpdatePrepare/updateDynamicParts</td>
|
||||
<td>Prepares `Class.Beam|Beams`, `Class.ParticleEmitter|ParticleEmitters`, and `Class.Humanoid|Humanoids` for rendering.</td>
|
||||
<td>Reduce the number of visible `Class.Beam|Beams`, `Class.ParticleEmitter|ParticleEmitters`, and `Class.Humanoid|Humanoids`.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prepare/UpdatePrepare/updateInstancedClusters</td>
|
||||
<td>Updates geometry that uses instanced rendering such as parts. Labels **Clusters** and **Instances** indicate the number updated.</td>
|
||||
<td>Reduce work that implicitly updates the bounding box of the part, such as `Class.BasePart.CFrame`, `Class.BasePart.Size`, or `Class.Motor6D.Transform`. Creative property updates such as `Class.Bone.Transform` can help.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform</td>
|
||||
<td>When actual rendering commands are created and issued.</td>
|
||||
<td>See **Perform** labels below.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/fillGuiVertices</td>
|
||||
<td>Fills buffers with UI vertices to prepare for rendering. **gui count** label indicates the amount of `Class.LayerCollector|LayerCollectors` visible in the frame.</td>
|
||||
<td>If the cost is high, reduce the amount, density, and space taken by UI elements. If there are too many **Process GuiEffect** labels, consider reducing the use of `Class.UIGradient` and `Class.UICorner` on text labels.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/queryFrustumOrdered</td>
|
||||
<td>Applies frustum culling so that objects not visible are not rendered.</td>
|
||||
<td>If there is a high cost that means there are a lot of elements. Perhaps use some larger meshes where a single mesh has more details as opposed to many small individual pieces.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/computeLightingPerform</td>
|
||||
<td>Computation of lighting near the camera.</td>
|
||||
<td>Manipulate the number of light sources or move the camera less to reduce the time it takes to recalculate lighting.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/computeLightingPerform/LightGridCPU</td>
|
||||
<td>Updates the voxel lighting, which is used at lower quality levels.</td>
|
||||
<td>If updating chunk occupancy takes too long, consider using lower resolution geometry, reducing the number of parts, or anchoring parts. If the other labels take too long, consider reducing the number of lights and using non-shadow casting geometry for objects that move and invalidate the occupancy.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/computeLightingPerform/ShadowMapSystem</td>
|
||||
<td>Updates shadow maps. Not performed at quality levels below 4.</td>
|
||||
<td>Reduce the number of lights. You can also use `Class.Light.Shadows` and `Class.BasePart.CastShadow` to disable shadow casting on less important instances. See [Improve performance](../../performance-optimization/improve.md#mitigation-4).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/Glow, ColorCorrection, MSAA, SSAO, and SSAOApply</td>
|
||||
<td>Post-processing rendering.</td>
|
||||
<td>Reduce the number of post-processing effects. Usually this is not significant.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/UI</td>
|
||||
<td>UI rendering. In **Id_Screen**, there is a label with the number of batches, materials and triangles used.</td>
|
||||
<td>Reduce the number of visible UI elements. Using `Class.CanvasGroup|CanvasGroups` can help at the expense of increased memory use.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Scene/UpdateView/updateParticles, updateParticleBoundings</td>
|
||||
<td>Update particle position and bounds.</td>
|
||||
<td>Reduce the number of `Class.ParticleEmitter|ParticleEmitters`, emission rates, lifetimes, etc. Limit the movement of emitters.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Scene/Id_Opaque, RenderView/Id_Opaque</td>
|
||||
<td>Parts in the scene with an overall transparency of `0.01` or lower.</td>
|
||||
<td>Reduce the use and density of parts.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Scene/Id_Transparent, RenderView/Id_Transparent</td>
|
||||
<td>Parts in the scene with an overall transparency between `0.01` and `1`.</td>
|
||||
<td>Reduce the use of partial transparency.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Scene/Id_Decals, RenderView/Id_Decals</td>
|
||||
<td>Decals in the scene.</td>
|
||||
<td>Reduce the use of decals on complex meshes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Scene/Shadows</td>
|
||||
<td>Shadow recalculation in the scene, usually performed on dynamic scenes and typical gameplay. Parts regardless of transparency cast shadows under the assumption that they contain decals. Not performed at quality levels below 4.</td>
|
||||
<td>If this step takes too long, consider disabling `Class.BasePart.CastShadow` for complex meshes, parts with high partial transparency, and less important instances. Fully transparent parts that don't have decals or need decal shadows should have `Class.BasePart.CastShadow` disabled. See [Improve performance](../../performance-optimization/improve.md#mitigation-4).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Present</td>
|
||||
<td>Forwards to the GPU thread to perform rendering commands.</td>
|
||||
<td>Reduce scene complexity in general. If this step is taking a long time, you might be limited by the GPU.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Perform/Present/waitUntilCompleted</td>
|
||||
<td>Waits for the GPU to finish rendering the previous frame.</td>
|
||||
<td>If this is generally happening a lot then the amount of things rendered is too high. The Frame Rate Manager helps with balancing this, but if it remains high, try following performance advice from the individual **Scene** tags.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LoadImage</td>
|
||||
<td>Processes images into a format the engine can use.</td>
|
||||
<td>Reduce the use of large images.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Scripts
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Render/PreRender/fireBindToRenderSteppedCallbacks</td>
|
||||
<td>Running functions bound to render step via `Class.RunService:BindToRenderStep()`.</td>
|
||||
<td>Ensure functions connected to this event do as little work as possible.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Render/PreRender/RunService.RenderStepped</td>
|
||||
<td>Runs functions connected to the `Class.RunService.RenderStepped` event.</td>
|
||||
<td>Ensure functions connected to this event do as little work as possible.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WaitingHybridScriptJob</td>
|
||||
<td>Resumes scripts waiting using `Class.Instance:WaitForChild()` or `Globals.Roblox.wait()`. Usually performed 30 times per second. This step has an execution time budget to run waiting scripts.</td>
|
||||
<td>If you have too many waiting scripts or scripts with a long runtime before yielding, this step is throttled and waits longer before it can run again. Reduce the amount of bound functions or long computations in this step.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GC</td>
|
||||
<td>Luau's garbage collection cycle.</td>
|
||||
<td>Pool tables and other collectable objects or try to reduce creating temporary tables.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Heartbeat/RunService.Heartbeat</td>
|
||||
<td>Runs functions connected to the `Class.RunService.Heartbeat` event.</td>
|
||||
<td>Reduce the amount or workload of functions connected to this event. Consider delaying or replacing expensive calculations or spreading computation across multiple frames.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Simulation
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Distributed Physics Ownership</td>
|
||||
<td>Determines whether the server or a client has authority over certain instances such as parts.</td>
|
||||
<td>Reduce the amount of parts that frequently switch network ownership, especially those with common interaction.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/assemble</td>
|
||||
<td>Updates a tree of connected objects (assemblies) used by the physics engine.</td>
|
||||
<td>Reduce the amount of joints being created or destroyed.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/physicsSteppedTotal/physicsStepped</td>
|
||||
<td>Runs the physics simulation.</td>
|
||||
<td>Reduce the amount and complexity of physically simulated bodies.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/physicsSteppedTotal/physicsStepped/SpatialFilter/filterStep</td>
|
||||
<td>Updates simulation islands, arranging parts according to network ownership, local simulation. Islands are non-interacting groups of parts which can be simulated independently.</td>
|
||||
<td>Avoid setting network ownership frequently. Keep groups of parts far enough away from each other so they can be simulated separately.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/physicsSteppedTotal/physicsStepped/worldStep/stepContacts</td>
|
||||
<td>Updates contacts between objects.</td>
|
||||
<td>Reduce the amount of bodies colliding at once, or use simpler collision boxes. Cubes are better than complex meshes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/physicsSteppedTotal/physicsStepped/worldStep/stepWorld **OR** stepWorldThrottled</td>
|
||||
<td>Solves physics equations relating to connectors, buoyancy and `Class.Humanoid|Humanoids`. When the engine is overloaded and unable to simulate everything in real time, some steps may be throttled (**stepWorldThrottled**) and only "real-time assemblies" such as `Class.Humanoid|Humanoids` are simulated.</td>
|
||||
<td>Depends on where the time is going based on the following three phases: **stepContacts**: narrow phase collision detection geometry tests. **Solver step**: integrate time and resolve collisions and other constraints **updateBroadphase**: update positions of assemblies in collision detection system and find possibly colliding narrow phase pairs.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>notifyMovingAssemblies</td>
|
||||
<td>Helps track how long primitives have been sleeping.</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/physicsSteppedTotal/physicsStepped/interpolateNetworkedAssemblies</td>
|
||||
<td>Interpolates assemblies not controlled by the current player.</td>
|
||||
<td>Set the network owner of parts to the current player to reduce this; although this will usually cause more physics work to be done elsewhere.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simulation/handleFallenParts</td>
|
||||
<td>Removes parts that have fallen below `Class.Workspace.FallenPartsDestroyHeight`.</td>
|
||||
<td>Lower the destroy height or reduce the amount of parts that fall to the destroy height.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Heartbeat/heartbeatInternal/workspaceOnHeartbeat/updateVisuallySleeping</td>
|
||||
<td>Second part of **notifyMovingAssemblies**.</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Heartbeat/RunService.Heartbeat</td>
|
||||
<td>Runs functions connected to the `Class.RunService.Heartbeat` event to simulation and scripts contacts. Current description is generic enough to be not wrong.</td>
|
||||
<td>Reduce the amount or workload of functions connected to `Class.RunService.Heartbeat`.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>worldStep/stepContacts</td>
|
||||
<td>Helps physics simulation step many contacts at once.</td>
|
||||
<td>Reduce the number of colliding objects.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SolveBatch</td>
|
||||
<td>Helps the physics simulation solve batches of objects' motion.</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## UI
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Description</th>
|
||||
<th>Performance advice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Render/PreRender/UpdateInput</td>
|
||||
<td>Updates and fires all user input related events if the user has performed input since the last frame.</td>
|
||||
<td>Try and not do too much work directly as you get the input. Consider doing a minimal amount of processing for the input, and larger computations should be pushed off to another thread that happens later.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Render/PreRender/TweenService</td>
|
||||
<td>Updates objects being tweened using `Class.TweenService` and calls completion callbacks, such as those used provided to `Class.GuiObject:TweenSize()` or `Class.GuiObject:TweenPosition()`.</td>
|
||||
<td>Reduce the number of objects being tweened using `Class.TweenService` and ensure callbacks do as little work as possible.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Heartbeat/TweenService</td>
|
||||
<td>In the server, `Class.TweenService` runs in `Class.RunService.Heartbeat` instead of `Class.RunService.PreRender`.</td>
|
||||
<td>Reduce the number of objects being tweened using `Class.TweenService` and ensure callbacks do as little work as possible.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Render/PreRender/UpdateUILayouts</td>
|
||||
<td>Updates position and size for UI elements on all enabled `Class.LayerCollector|LayerCollectors`.</td>
|
||||
<td>See **UpdateUILayouts** labels below.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Render/PreRender/UpdateUILayouts/Rebuild Z-order list</td>
|
||||
<td>Sorts the Z-order of UI elements (internal term not to be confused with `Class.GuiObject.ZIndex`) to prevent tearing of UI elements.</td>
|
||||
<td>Reduce the amount of UI elements with the same `Class.GuiObject.ZIndex`.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Render/PreRender/UpdateUILayouts/Layout</td>
|
||||
<td>
|
||||
Updates position and size for UI elements in an individual `Class.LayerCollector`. Can contain a label with information about the relevant UI, along with the amount of Relayouts, Updates and Resizes.
|
||||
</td>
|
||||
<td>Reduce the amount of UI elements being resized or repositioned, such as those managed by `Class.UILayout` and those tweened with `Class.TweenService`, `Class.GuiObject:TweenSize()`, or `Class.GuiObject:TweenPosition()`. Consider using fixed sizes for `Class.BillboardGui|BillboardGuis`.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
title: Task scheduler
|
||||
description: Task Scheduler coordinates tasks done in each frame as the experience runs.
|
||||
---
|
||||
|
||||
The **task scheduler** coordinates tasks done each frame as the experience runs, even when it is paused. These tasks include detecting player input, animating characters, updating the physics simulation, and resuming scripts in a `Library.task.wait()` state.
|
||||
|
||||
While there may be multiple tasks running, the task scheduler can potentially be overloaded, especially in the following situations:
|
||||
|
||||
- Using a custom character rig or input scheme.
|
||||
- Animating parts yourself (instead of using an `Class.Animator`).
|
||||
- Depending heavily on precise physics.
|
||||
- Replicating objects regularly.
|
||||
|
||||
## RunService
|
||||
|
||||
The most direct way to add frame-by-frame tasks is through the following members of `Class.RunService`:
|
||||
|
||||
- `Class.RunService:BindToRenderStep()`
|
||||
- `Class.RunService.PreAnimation`
|
||||
- `Class.RunService.PreRender`
|
||||
- `Class.RunService.PreSimulation`
|
||||
- `Class.RunService.PostSimulation`
|
||||
- `Class.RunService.Heartbeat`
|
||||
|
||||
## Scheduler priority
|
||||
|
||||
The task scheduler categorizes and completes tasks in the following order. Some tasks may not perform work in a frame, while others may run multiple times.
|
||||
|
||||
<img src="../../assets/optimization/task-scheduler/scheduler-priority.png" />
|
||||
|
||||
## Best practices
|
||||
|
||||
To build performant experiences with efficiency in mind, note the following:
|
||||
|
||||
- **Don't connect/bind functions to the render step unless absolutely necessary.**
|
||||
Only tasks that must be done after input but before rendering should be done in such a way, like camera movement. For strict control over order, use `Class.RunService:BindToRenderStep()|BindToRenderStep()` instead of `Class.RunService.PreRender|PreRender`.
|
||||
|
||||
- **Manage physical states carefully.**
|
||||
`Class.RunService.PreSimulation|PreSimulation` happens **before** physics, while `Class.RunService.PostSimulation|PostSimulation` happens **after** physics. Therefore, gameplay logic that affects the physics state should be done in `Class.RunService.PreSimulation|PreSimulation`, such as setting the `Class.BasePart.Velocity|Velocity` of parts. In contrast, gameplay logic that relies on or reacts to the physics state should be handled in `Class.RunService.PostSimulation|PostSimulation`, such as reading the `Class.BasePart.Position|Position` of parts to detect when they enter defined zones.
|
||||
|
||||
- **Motor6D transform changes should be done on the PreSimulation event.**
|
||||
If you don't, `Class.Animator|Animators` will overwrite changes on the next frame. Even without an `Class.Animator`, `Class.RunService.PreSimulation|PreSimulation` is the last Luau event fired before `Class.Motor6D.Transform` is applied to part positions.
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
---
|
||||
title: MicroProfiler walkthrough
|
||||
description: Explains how using the MicroProfiler can help you optimize portions of your experience.
|
||||
---
|
||||
|
||||
This walkthrough shows how to use the MicroProfiler to find a problematic aspect of an experience and identify the root cause. Download the experience, **Open from File** in Studio, and follow along.
|
||||
|
||||
<a href="../../assets/optimization/microprofiler/RaycastSpam.rbxl">
|
||||
<Button variant="contained">Download the Experience</Button>
|
||||
</a>
|
||||
|
||||
<br />
|
||||
|
||||
## Identify the issue
|
||||
|
||||
1. After you open the experience in Studio, start testing it with <kbd>F5</kbd> or the **Play** button.
|
||||
|
||||
1. The frame rate feels decent, but not as smooth as it should be for an experience of this size and scope. Press <kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>F5</kbd> (<kbd>⌘</kbd><kbd>Shift</kbd><kbd>F5</kbd>) to show the **Performance Summary** overlay.
|
||||
|
||||
<img alt="Performance summary showing 45 FPS." src="../../assets/optimization/microprofiler/micro-tut-framerate.png" width="500px" />
|
||||
|
||||
Note that the frame rate is below 60 frames per second (FPS).
|
||||
|
||||
1. Open the MicroProfiler by pressing <kbd>Ctrl</kbd><kbd>Alt</kbd><kbd>F6</kbd> (<kbd>⌘</kbd><kbd>⌥</kbd><kbd>F6</kbd>).
|
||||
|
||||
<img alt="The MicroProfiler after opening it." src="../../assets/optimization/microprofiler/micro-tut-bar-graph.png" width="500px" />
|
||||
|
||||
Note that the frame times are **consistent**—the bars are roughly the same height—so whatever is causing the low frame rate is running every single frame as opposed to running occasionally and causing frame time spikes.
|
||||
|
||||
1. Pause the MicroProfiler by pressing <kbd>Ctrl</kbd><kbd>P</kbd> (<kbd>⌘</kbd><kbd>P</kbd>). Pausing with the keyboard shortcut opens [detailed mode](./modes.md#detailed-mode).
|
||||
|
||||
1. Click and drag to pan the graph. Note how one particular task in the worker threads seems to be using a lot of processing time compared to the main thread. Hover over `Class.RunService.Stepped` and note how long it's taking to render.
|
||||
|
||||
<img alt="Detailed mode with long labels for processes." src="../../assets/optimization/microprofiler/micro-tut-stepped.png" width="600px" />
|
||||
|
||||
1. Stacked bars in the timeline indicate a hierarchy of code, so keep hovering on lower and lower layers to try and identify the issue.
|
||||
|
||||
<img alt="On-hover details for various processes, with LocalScript highlighted." src="../../assets/optimization/microprofiler/micro-tut-localscript.png" width="600px" />
|
||||
|
||||
<img alt="On-hover details for various processes, with Raycast highlighted." src="../../assets/optimization/microprofiler/micro-tut-raycast-label.png" width="600px" />
|
||||
|
||||
Note the `LocalScript` label, which indicates the name of the script, and the `Raycast` label, which indicates that the problem might be related to raycasting.
|
||||
|
||||
## Create troubleshooting labels
|
||||
|
||||
Now that the MicroProfiler has provided a starting point, you can troubleshoot the problematic code.
|
||||
|
||||
1. Stop the play test and filter the Explorer window for `localscript` to find the file.
|
||||
|
||||
<img alt="A view of filtering in the Explorer window." src="../../assets/optimization/microprofiler/micro-tut-explorer-filter.png" width="400px" />
|
||||
|
||||
A search for `raycast` indicates that this portion of code is probably the culprit for the experience's poor performance:
|
||||
|
||||
```lua
|
||||
local RAYS_PER_SECOND = 1500
|
||||
|
||||
local function onStepped()
|
||||
|
||||
for _ = 1, RAYS_PER_SECOND do
|
||||
local startPosition = getRandomPosition()
|
||||
local endPosition = getRandomPosition()
|
||||
local direction = endPosition - startPosition
|
||||
|
||||
Workspace:Raycast(
|
||||
startPosition,
|
||||
endPosition
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
RunService.Stepped:Connect(onStepped)
|
||||
```
|
||||
|
||||
Specifically, you can see that the code is casting 1,500 rays per second in random directions.
|
||||
|
||||
1. To verify that this portion of code is causing the rendering delay, wrap the contents of the function with `Library.debug.profilebegin()` and `Library.debug.profileend()`:
|
||||
|
||||
```lua
|
||||
local function onStepped()
|
||||
|
||||
debug.profilebegin("Raycast Spam")
|
||||
|
||||
for _ = 1, RAYS_PER_SECOND do
|
||||
local startPosition = getRandomPosition()
|
||||
local endPosition = getRandomPosition()
|
||||
local direction = endPosition - startPosition
|
||||
|
||||
Workspace:Raycast(
|
||||
startPosition,
|
||||
endPosition
|
||||
)
|
||||
end
|
||||
|
||||
debug.profileend()
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
## Confirm and fix the issue
|
||||
|
||||
1. Start testing the experience, and open the MicroProfiler again.
|
||||
|
||||
1. Note how the MicroProfiler now shows the custom label, indicating that this function was indeed the root cause.
|
||||
|
||||
<img alt="MicroProfiler detailed view with 'Raycast Spam' visible." src="../../assets/optimization/microprofiler/micro-tut-spam.png" width="500px" />
|
||||
|
||||
1. Stop the play test.
|
||||
|
||||
1. Delete or comment out the `onStepped()` function and the `RunService.Stepped:Connect(onStepped)` connection.
|
||||
|
||||
1. Start testing the experience again, and check the **Performance Summary** again.
|
||||
|
||||
<img alt="Performance summary showing 60 FPS." src="../../assets/optimization/microprofiler/micro-tut-framerate2.png" width="500px" />
|
||||
|
||||
Note the huge improvement to frame rate and corresponding drop in frame times on the MicroProfiler graph.
|
||||
Loading…
Add table
Add a link
Reference in a new issue