Add loading time recording functions

It is important to record when your game is performing loading events for two reasons:

  1. To avoid polluting your frame time data while loading.
  2. To analyze load times to see when and where load times are longer than acceptable.

A loading event can have associated metadata:

typedef struct TuningFork_LoadingTimeMetadata {
    enum LoadingState {
        UNKNOWN_STATE = 0,
        // The first time the game is run
        FIRST_RUN = 1,
        // App is not backgrounded
        COLD_START = 2,
        // App is backgrounded
        WARM_START = 3,
        // App is backgrounded, least work needed
        HOT_START = 4,
        // Asset loading between levels
        INTER_LEVEL = 5
    } state;
    enum LoadingSource {
        UNKNOWN_SOURCE = 0,
        // Uncompressing data.
        MEMORY = 1,
        // Reading assets from APK bundle.
        APK = 2,
        // Reading assets from device storage.
        DEVICE_STORAGE = 3,
        // Reading assets from external storage, e.g. SD card.
        EXTERNAL_STORAGE = 4,
        // Loading assets from the network.
        NETWORK = 5,
        // Shader compilation.
        SHADER_COMPILATION = 6,
        // Time spent between process starting and onCreate.
        PRE_ACTIVITY = 7,
        // Total time spent between process starting and first render frame.
        FIRST_TOUCH_TO_FIRST_FRAME = 8
    } source;
    int32_t compression_level;  // 0 = no compression, 100 = max compression
    enum NetworkConnectivity {
        UNKNOWN = 0,
        WIFI = 1,
        CELLULAR_NETWORK = 2
    } network_connectivity;
    uint64_t network_transfer_speed_bps;  // bandwidth in bits per second
    uint64_t network_latency_ns;          // latency in nanoseconds
} TuningFork_LoadingTimeMetadata;

Any fields that aren't relevant to your needs can be zero.

A loading event can also have an associated annotation. This is defined in the same way as frame time annotations, using one or more fields in the Annotation message in the dev_tuningfork.proto file.

TuningFork_ErrorCode TuningFork_startRecordingLoadingTime( const TuningFork_LoadingTimeMetadata* eventMetadata, uint32_t eventMetadataSize, const TuningFork_CProtobufSerialization* annotation, TuningFork_LoadingEventHandle* handle);

This function starts recording a loading time event associated with the given metadata and annotation, and fills in a handle to be used in the TuningFork_stopRecordingLoadingTime() function.

TuningFork_ErrorCode TuningFork_stopRecordingLoadingTime( TuningFork_LoadingEventHandle handle);

This function stops recording an event previously started by TuningFork_startRecordingLoadingTime(). The event is uploaded at the next session flush.

TuningFork_ErrorCode TuningFork_recordLoadingTime( uint64_t time_ns, const TuningFork_LoadingTimeMetadata* eventMetadata, uint32_t eventMetadataSize, const TuningFork_CProtobufSerialization* annotation);

We strongly recommend directly using the start and stop functions described previously. If you can't do this, however, you can call this function to record a duration and its associated metadata and annotation.

Loading group functions

In your game, you may record several loading events for a single loading period seen by the user. Some examples include (but aren't limited to) file loading, decompression, and shader compilation.

It is important to inform Tuning Fork that loading events are part of such a group so that it can provide better insights. Bracket your loading events with the following start and stop functions in order to do this.

TuningFork_ErrorCode TuningFork_startLoadingGroup( const TuningFork_LoadingTimeMetadata* eventMetadata, uint32_t eventMetadataSize, const TuningFork_CProtobufSerialization* annotation, TuningFork_LoadingEventHandle* handle);

This function starts a loading group associated with the given metadata and annotation, and fills in a handle to be used in the TuningFork_stopLoadingGroup() function. The metadata and annotation are currently not used by the Play backend and can be set to nullptr. All subsequent loading events will be tagged by a unique group ID.

TuningFork_ErrorCode TuningFork_stopLoadingGroup( TuningFork_LoadingEventHandle handle);

This function stops a loading group previously started by TuningFork_startLoadingGroup(). Subsequent loading events will not have a group ID until TuningFork_startLoadingGroup() is called again.

Figure 1. Example of the loading group.