VrApi Stats Definition Guide

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 VrApi.

For information on how to use logcat, see Logcat. For an introduction to ADB, see ADB.

Sample usage:

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:

VrApi: FPS=72,Prd=46ms,Tear=0,Early=72,Stale=0,VSnc=1,Lat=1,Fov=0,CPU4/GPU=2/4,1651/670MHz,OC=FF,TA=0/E0/0,SP=N/F/N,Mem=1804MHz,Free=1642MB,PSM=0,PLS=0,Temp=31.0C/0.0C,TW=3.40ms,App=0.69ms,GD=0.97ms,CPU&GPU=3.86ms,LCnt=3,GPU%=0.37,CPU%=0.08(W0.10)

The following table describes each statistic and gives guidance in interpreting them:

FPS=72Shows 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.
Prd=46msShows 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.
Tear=0Shows 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.
Early=72Shows 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.
Stale=0Shows 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
VSnc=1Shows the value of MinimumVsyncs, which is the number of vsyncs between frames. In Oculus Quest development, this should almost always be set to 1, as 2 can cause the app to render at half rate, which can be uncomfortable with 6DOF movement. `

MinimumVsyncs may be set to 2 for debugging purposes, but this setting should never be used in a published app because it’s noticeable whenever the user turns their head.
Lat=1Indicates 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 vrapi_SetExtraLatencyMode.
Fov=0Indicates 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).
CPU4/GPU=2/4Specifies the CPU and GPU clock levels set by the app. The number following CPU indicates the core being measured. While these levels can be set manually, use of dynamic clock throttling, which increases these numbers if the app is not hitting frame rate at a requested level, is recommended. `

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.
1651/670MHzSpecifies 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.
OC=FFShows 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.
TA=0/E0/0These 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.
SP=N/F/NThese characters refer to the scheduling priority of the ATW, main, and render threads. F is SCHED_FIFO, which is the highest priority, and N is SCHED_NORMAL for normal priority. On Oculus Quest, ATW should always be N. On Oculus Go, ATW should be F, otherwise there may be tearing. The main and render thread scheduling priority can be set natively with vrapi_SetPerfThread.
Mem=1804MHzSpecifies the speed of the memory.
Free=1642MBIndicates 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.
PSM=0Indicates 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 PLS.
PLS=0Indicates the current power level of the device. The reported levels are NORMAL (0), SAVE (1), and DANGER (2). As the device heats up, the power level will automatically change from NORMAL, to SAVE, and eventually to DANGER. Once DANGER is reached, an overheat dialog is displayed. `

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.
Temp=31.0C/0.0CThese 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, PSM and PLS can be used as indicators of when temperature is affecting the device’s performance.
TW=3.40msDisplays 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.
App=0.69msDisplays 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.
GD=0.97msDisplays 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.
CPU&GPU=3.86msDisplays 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 (App) from this value, an approximate clock time for the render thread can be determined, which can be useful if it is a bottleneck.
LCnt=3Specifies 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 (GD), and keeping it to a minimum will help avoid screen tearing in video apps.
GPU%=0.37Displays 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%.
CPU%=0.08(W0.10)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 (GPU%). With most apps being multithreaded and the scheduler assigning threads to whichever core is available, the main thread might only be represented in the average percentage, unless it’s running on the worst-performing core.