[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-08-26 (世界標準時間)。"],[],[],null,["This topic describes how to integrate Android Performance Tuner, also known as the\nTuning Fork library, to record and upload frame time data from native (C\nand C++) game engines.\n| **Note:** For a guided tutorial, see the [Integrating Android Performance Tuner into your native Android game Codelab](https://codelabs.developers.google.com/codelabs/android-performance-tuner-native).\n\nFor the Unity game engine, see the\n[guide for Unity](/games/sdk/performance-tuner/unity).\n\nBackground\n\nA key component of the game experience is *rendering performance*. Rendering\nperformance is an outcome of the following two inputs:\n\n- Frame rate: How often a frame is drawn.\n- Graphical quality settings: Level of fidelity at which a frame is presented, including simulation fidelity as well as graphics.\n\nFor games, good rendering performance is defined as the following:\n\n- Delivering a stable, consistent frame rate (that is, the percentage of frames rendering at the desired frequency).\n- Rendering frames at the highest frequency possible while maintaining stability, typically 30 or 60 FPS depending on the type of game.\n- Maximizing the level of detail for a user given their screen size and density while still achieving a desired, stable frame rate.\n\nThe [Android Frame Pacing library](/games/sdk/frame-pacing) limits much of the\nvariation in frame times, providing a stable frame rate for games. The remaining\nvariation in frame times is due to the level of detail displayed during certain\nscenes in gameplay and the graphical capabilities of the device. Using\nAndroid Performance Tuner, you can pinpoint times during gameplay when the frame time\nis slower or faster than your target, and correlate these issues and\nopportunities to:\n\n- Specific quality settings\n- Specific scenes in your game\n- Specific device models or device specs\n\nRecord and upload data\n\nThe Tuning Fork library relies on one of its\n[tick functions](/games/sdk/performance-tuner/custom-engine/add-functions#per-frame-functions)\nbeing called each frame by the Android Frame Pacing library. Within the library,\nthis tick information is aggregated into histograms which are then periodically\nuploaded to Google Play through an HTTP endpoint. Each tick is recorded as\nbeing associated with an [instrument key](#instrument-keys) and an\n[annotation](#annotations), the definitions for which you specify in a protocol\nbuffer file.\n\nInstrument keys\n\nAn instrument key indicates where in the frame the tick comes from and is an\ninteger that must be passed to each tick function call. The Android Frame Pacing\nlibrary uses a predefined set of instrument keys, defined in `swappy_common.h`.\nYou can also define your own instrument keys if you do not use the Frame Pacing\nlibrary.\n\nAnnotations\n\nAnnotations give contextual information about what your game is doing when a\ntick is recorded. For example, an annotation could identify any of the\nfollowing:\n\n- The current game level\n- A \"big boss\" is on the screen\n- Any other relevant game state information\n\nAnnotations are defined by the `com.google.tuningfork.Annotation` protocol\nbuffer message. To set the current annotation, you pass a serialization of the\nmessage you defined to\n[`TuningFork_setCurrentAnnotation()`](/games/sdk/reference/performance-tuner/custom-engine/group/tuningfork#tuningfork_setcurrentannotation).\nAll subsequent tick data is then associated with this annotation until another\nannotation is set. The following is an example proto definition for annotations: \n\n import \"tuningfork.proto\"\n enum Level {\n INVALID_LEVEL = 0;\n Level_1 = 1;\n Level_2 = 2;\n Level_3 = 3;\n }\n message Annotation {\n optional Level level = 1;\n }\n\nFidelity parameters\n\nFidelity parameters influence the performance and graphical fidelity of your\ngame, such as mesh level-of-detail, texture resolution, and anti-aliasing\nmethod. Like annotations, fidelity parameters are defined using the\n`com.google.tuningfork.FidelityParams` protocol buffer message. The following is\nan example proto definition for fidelity parameters: \n\n import \"tuningfork.proto\"\n message FidelityParams {\n int32 texture_quality_level = 1;\n int32 shadow_resolution = 2;\n float terrain_details_percent = 3;\n int32 post_processing_effects_level = 4;\n }\n\nAt Tuning Fork initialization, you pass a serialization of the\nparameters that the game uses. You can change these parameters if, for example,\nthe user changes the game rendering settings, and your subsequent uploaded data\nis associated with the new parameters.\n\nIn order for Google Play to understand the annotations and fidelity parameters\nthat you define, the protocol buffer file holding these definitions must be\nbundled within the game's APK, together with initialization settings. You also\nneed to provide default values for common fidelity parameter combinations in\nyour APK in order to have your data segmented by them in the Google Play UI.\nFor more information, see\n[Define quality levels](/games/sdk/performance-tuner/custom-engine/define-parameters#define-quality-levels).\n\nMemory and CPU overhead\n\nAll memory used by the Tuning Fork library is allocated at\ninitialization in order to avoid surprises during gameplay. The size of the data\ndepends on the number of instrument keys, number of possible annotations, and\nnumber of buckets in each histogram; it is a multiple of all of these times four\nbytes for each bucket. There are also two copies of all histograms to allow for\nsubmission in a double-buffered fashion.\n\nSubmission occurs on a separate thread and doesn't block tick calls. If no\nupload connection is available, the submission is queued for later upload.\n\nThere is little processing overhead to calling a tick function: it simply\ncalculates an index into the array of histogram buckets and increments an\ninteger count.\n\nIntegrate the Tuning Fork library\n\nThis integration guide is divided into two parts. The first part describes how\nto run an end-to-end test using a demo app and the Google Play Console. The\nsecond part describes how to integrate the Tuning Fork library into\nyour toolchain and how to use the functions that the library provides. Click the\n**Next** link below to get started."]]