Logcat provides a simple way to get basic performance statistics on an app in development. Logcat retrieves logs of Android OS and application messages from a connected device via adb. This topic describes the information provided in Oculus Mobile logs, which use the logcat tag
adb logcat -s VrApi
When logcat is executed on a connected device running an Oculus mobile app, a line resembling this example will be displayed every second:
The following table describes each statistic and gives guidance in interpreting them:
|Shows the number of frames per second displayed. An application that performs well will consistently show a frame rate that matches the selected refresh rate for the app.|
|Shows the prediction time. This is the absolute time between when an app queries the pose before rendering and the time the frame is displayed on the HMD screen. `|
This should almost always be a fixed number between 45ms and 50ms. If this number is much higher than expected, the app likely has latency issues when rendering.
|Shows the number of screen tears. This reports when Asynchronous TimeWarp (ATW) takes too long and experiences a screen tear. `|
Screen tears should not happen on Oculus apps unless too many layers are being used. This might occur if quad or cylinder layers are being used to display UI elements, or if multiple overlapping equirect video layers are displayed.
|Shows the number of early frames. This indicates the number of frames delivered before they were needed. Early frames are possible when extra latency mode is being used. `|
When a few early frames can be ignored, but if this number is persistently high, make sure the CPU and GPU levels aren’t set higher than necessary. If the number of early frames matches the FPS, it’s recommended to either turn off extra latency mode, or take advantage of the headroom by increasing the resolution or shader complexity.
|Shows the number of stale frames. This indicates the number of times a frame wasn’t delivered on time, and the previous frame was used instead. `|
Because the CPU and GPU are working in parallel, sometimes rendering a frame takes longer than a single frame’s total time length, but neither the CPU or GPU take longer than a frame individually themselves. Therefore, it is possible for an app to run at 72 FPS, but have 72 stale frames per second. In such situations, the latency between rendering and display time will be higher, but the release tempo of frames will be steady. `
Stale frames become an issue when the value is greater than 0 and less than the refresh rate. At this point, some frames are displayed twice in a row, some frames are skipped, and the user will have a poor experience. Extra latency mode can be used in such situations. This feature, which is on by default in Unity and Unreal Engine) tells ATW to always wait an extra frame, and not to consider frames stale unless they aren’t ready after the second frame. If the app does render quickly, the frame will be considered early, but everything will look smooth. `
For further reading on how stale frames work, read the blog post Understanding Gameplay Latency for Oculus Quest, Oculus Go and Gear VR
|Shows the value of |
|Indicates whether extra latency mode is enabled. This feature tells ATW to always wait an extra frame and use the previously submitted frame. This allows usage of the whole frame for CPU and GPU, making it easier to hit frame targets with the downside of the loss of one frame of latency. Extra latency mode can make hitting performance targets easier, and its use is recommended. `|
Extra latency mode is enabled by default when developing with Unity and Unreal Engine. For native mobile development, enable extra latency mode with
|Indicates the level of Fixed Foveated Rendering (FFR) intensity. This feature can be used to render the edges of your eye textures at a lower resolution than the center, lowering the fidelity of the scene in the viewer’s peripheral vision while reducing the GPU load. This number has direct GPU performance implications, and there will be noticeable visible artifacts on the edge of the screen at higher levels. Pick the most visually acceptable level for the performance increase needed. `|
For more information and recommendations, see Fixed Foveated Rendering (FFR).
|Specifies the CPU and GPU clock levels set by the app. The number following |
If an app is not making frame rate, reviewing the clock levels can help quickly indicate if performance is CPU or GPU bound, providing a target area for optimization. For example, if an app with performance issues is at CPU 4 and GPU 2, the app must be CPU bound since there is still available GPU overhead. However, if both levels are 4 and the app has issues, this number is not as useful, and other metrics should be used to find potential areas for optimization, such as stale frames, app GPU time, and CPU/GPU utilization. `
For more information on the CPU and GPU clock levels, see Power Management.
|Specifies the clock speeds of the CPU and GPU, which are changed when the CPU and GPU clock levels are adjusted. The CPU and GPU clock levels are more useful to monitor since they can be directly adjusted and changed. The clock speeds tied to those levels vary with different SoC’s, and the frequencies cannot be changed.|
|Shows the online core mask. Certain older CPUs found in phones used with Gear VR devices would power down cores to reduce energy usage. Current CPUs in Oculus devices no longer do this, and can reduce energy usage on cores without taking them offline, so this feature is no longer used.|
|These values represent the ATW, main, and render thread affinities. It’s recommended that developers avoid manually setting thread affinity, but these values are useful for verifying your threads are running on big cores. On Oculus Quest, the ATW thread will report 0.|
|These characters refer to the scheduling priority of the ATW, main, and render threads. F is |
|Specifies the speed of the memory.|
|Indicates the available memory as reported by Android. On Android, memory is handled in a somewhat opaque way, which makes this value useful for only general guidance. For example, if an app goes to the background, the newly foregrounded app and OS operations will pull a lot of memory, and it may crash your app even if `Free` is reporting that there is memory available. `|
This value is most useful as a way to monitor whether memory is being allocated faster than expected, or if memory isn’t being released when expected.
|Indicates whether the device has entered power save mode. PSM is a binary value that indicates whether the power level is SAVE (1). For more information, see |
|Indicates the current power level of the device. The reported levels are |
Applications should monitor the power level and change their behavior to reduce rendering costs when it enters power save mode. For more information on this topic, see Power Management.
|These values indicate the battery and sensor temperature. These values were specifically important for phone-based VR development. For temperature concerns on Oculus Quest and Oculus Go, |
|Displays the ATW GPU time, which is the amount of time ATW takes to render. This time directly correlates to the number of layers used and their complexity, with equirect and cylinder layers being more expensive on the GPU than quad and projection layers. `|
This value may be useful to video apps because ATW taking too long can result in screen tearing in playback.
|Displays the app GPU time, which is the amount of time the application spends rendering a single frame. `|
This value is one of the most useful numbers to monitor when optimizing an application. If the length of time shown is longer than a single frame’s length (13.88ms for 72 frames per second), the app is GPU bound. If the length is less than a frame’s length, the app is probably CPU bound. `
In addition to using this metric to determine if an app is GPU or CPU bound, it’s also useful to monitor it as you change shaders, add textures, change meshes, and make other changes. This can allow insight into how much headroom remains on the GPU, and if debug logic is used to turn on and off specific objects, you can tell how performance-intensive those objects are.
|Displays the Guardian GPU time, which is the amount of GPU time used by the Guardian boundary. This number is not actionable, but there may be interest in knowing how much time is used by Guardian.|
|Displays the total time it took to render a frame. This is currently only available when using Unity or Unreal Engine, and measures from when the render or RHI thread begins processing the frame until the GPU completes rendering. `|
By subtracting the app GPU time (
|Specifies the number of layers that ATW is rendering per frame, including system layers. There is a direct correlation between this value and the ATW GPU time (|
|Displays the GPU utilization percentage. If this value is maxed 100%, the app is GPU bound. Performance issues due to scheduling may occur if this number is over 90%.|
|Displays the CPU utilization percentage. This first number is the average utilization percentage of all CPU cores, with the second being the percentage of the worst-performing core. These numbers are less useful than the GPU utilization percentage (|