1. 程式人生 > 其它 >Android使用PGO優化native庫執行速度

Android使用PGO優化native庫執行速度

Profile-guided optimization (PGO),配置檔案引導的優化,基於插樁或採樣從程式執行時生成配置檔案,使編譯器對內聯和程式碼佈局做優化,可以獲得免費的效能提升。在安卓中使用的教程較少,實際操作時會遇到一些問題,在這裡記錄一下使用插樁的方式。

1. 使用-fprofile-generate編譯和連結經過插樁的動態庫

新增編譯引數

android {
    ...

    defaultConfig {
        ...
        
        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11 -fprofile-generate'
            }
        }
    }
}

2. 執行具有代表性的流程,收集配置檔案

安卓中生成配置檔案需在最後手動呼叫__llvm_profile_write_file方法,在C++中需要新增extern "C",否則連結時會找不到此方法

extern "C" {
extern int __llvm_profile_write_file(void);
}

載入動態庫前需設定環境變數 LLVM_PROFILE_FILE指定配置檔案生成位置

static {
    try {
        Os.setenv("LLVM_PROFILE_FILE", "/path/to/%m.profraw", true);
    } catch (ErrnoException e) {
        e.printStackTrace();
    }
    System.loadLibrary("native-lib");
}

LLVM_PROFILE_FILE可以使用下面的修飾符來設定配置檔案路徑

  • %p 程序ID
  • %h hostname
  • %m 唯一的配置檔名稱

如果出現以下錯誤

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__start___llvm_prf_vnds" referenced by "... .so"

需要改連結程式為lld或者gold,ndk r22開始已經預設使用lld,也可以升級ndk到r22

android {
   ...
   
   ndkVersion '22.1.7171670'
}

3. 使用llvm-profdata合併轉換配置檔案

如果有多個配置檔案,用下面的命令合併和轉換

$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-profdata \
    merge --output=pgo_profile.profdata \
    <list-of-profraw-files>

即使只有一個配置檔案也需要用此命令轉換格式

4.使用配置檔案編譯

android {
    ...

    defaultConfig {
        ...
        
        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11 -fprofile-use=/path/to/<>.profdata'
            }
        }
    }
}

程式碼更改後也可以使用這個配置檔案,如果無法繼續使用,編譯器會生成 -Wprofile-instr-out-of-date警告

參考

  1. Profile guided optimization for native Android applications

  2. 使用配置檔案引導的優化 (PGO)

  3. How to compile with Profile Guided Optimization (PGO)