Logcat for Basic Performance Stats

Important

All Oculus Quest developers MUST PASS the concept review prior to gaining publishing access to the Quest Store and additional resources. Submit a concept document for review as early in your Quest application development cycle as possible. For additional information and context, please see Submitting Your App to the Oculus Quest Store.

A simple way to get some basic performance numbers is to use logcat, which is an Android tool you can run with adb that provides a log of system messages. For an introduction to the logcat, see Logcat. For an introduction to adb, see Adb.

To retrieve performance numbers, run logcat with the adb shell tool, and add a filter for VrApi.

Sample usage:

adb logcat -s VrApi

A line resembling this example will be displayed every second:

I/VrApi (26422):
FPS=72,Prd=45ms,Tear=0,Early=73,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=1961MB,PSM=0,PLS=0,Temp=26.0C/0.0C,TW=2.94ms,App=7.37ms,GD=0.00ms,CPU&GPU=4.88ms,LCnt=3,GPU%=0.54,CPU%=0.08(W0.15)

Following is a list of possible log entries and their meaning:

EntryDescription
FPSFrames per second. An application that performs well will continuously display 72 FPS.
PrdThe number of milliseconds between the latest sensor sampling for tracking and the anticipated display time of new eye images. New eye images are not generated for the time the rendering code is executed, but are instead generated for the time they will be displayed. When an application begins generating new eye images, the time they will be displayed is predicted. The tracking state (head orientation, and so on) is also predicted ahead for this time.
TearsThe number of tears per second. A well-behaved and well-performing application will display zero tears. Tears can be related to Asynchronous TimeWarp, which takes the last completed eye images and warps them onto the display. The time warp runs on a high priority thread using a high priority OpenGL ES context. As such, the time warp should be able to preempt any application rendering and warp the latest eye images onto the display just in time for the display refresh. However, when there are a lot of heavyweight background operations, or the application renders many triangles to a small part of the screen or uses a very expensive fragment program, then the time warp may have to wait for this work to be completed. This may result in the time warp not executing in time for the display refresh, which, in return, may result in a visible tear line across one of the eyes or both eyes.
EarlyThe number of frames that are completed a whole frame early.
StaleThe number of stale frames per second. A well-behaved application performing well displays zero stale frames. New eye images are generated for a predicted display time. If, however, the new eye images are not completed by this time, then the time warp may have to re-project and display a previous set of eye images. In other words, the time warp displays a stale frame. Even though the time warp re-projects old eye images to make them line up with the latest head orientation, the user may still notice some degree of intra-frame motion judder when displaying old images.
VsncThe value of MinimumVsyncs, which is the number of V-Syncs between displayed frames.
FovSpecifies the Fixed Foveated Rendering (FFR) level, with 0 = off, 1 = low, 2 = medium, 3 = high, 4 = high top. FFR renders the edges of the eye textures at a lower resolution than the center. The effect lowers the fidelity of the scene in the viewer’s peripheral vision, reducing the GPU load as a result of reduced pixel shading requirements. FFR can dramatically increase the resolution of the eye texture, improving the image shown in the headset. Complex fragment shaders also benefit from this form of multi-resolution rendering.
CPU#/GPUThe CPU and GPU clock levels and associated clock frequencies, set by the application. Lower clock levels result in less heat and less battery drain.
F/F [Thread Affinity]This field describes the thread affinity of the main thread (first hex nibble) and renderer thread (second hex nibbles). Each bit represents a core, with 1 indicating affinity and 0 indicating no affinity. For example, F/1 (= 1111 0001) indicates the main thread can run on any of the lower four cores, while the rendered thread can only run on the first core. In practice, F/F and F0/F0 are common results.
FreeThe amount of available memory, displayed every second. It is important to keep a reasonable amount of memory available to prevent Android from killing backgrounded applications like Oculus Home.
PLSPower Level State, where “0” = normal, “1” = throttled, and “2” = undock required.
TempTemperature in degrees Celsius. Well-optimized applications do not cause the temperature to rise quickly. There is always room for more optimization, which allows lower clock levels to be used, which, in return, reduces the amount of heat that is generated.
AppGPU rendering time spent on the main thread of the application.
CPU&GPUThe average time spent in the last second on the application’s CPU plus GPU time, from the vrapi_waitframe call to the return of the GPU fence.
GPU%GPU utilization percentage.
CPU%Average CPU utilization percentage, with the worst performing core in parentheses.