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);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_startrecordingloadingtime)

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);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_stoprecordingloadingtime)

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);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_recordLoadingtime)

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

| **Warning:** All loading events must be part of a loading group.

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.
| **Note:** Only one loading group can be active at a time.

[`TuningFork_ErrorCode TuningFork_startLoadingGroup(
const TuningFork_LoadingTimeMetadata* eventMetadata,
uint32_t eventMetadataSize,
const TuningFork_CProtobufSerialization* annotation,
TuningFork_LoadingEventHandle* handle);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_startloadinggroup)

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);`](https://developer.android.com/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_stoploadingGroup)

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.

![](https://developer.android.com/static/images/games/performance-tuner/loading-groups-custom.png)
**Figure 1.** Example of the loading group.