Android-os cocos2d-x környezet fordításának felgyorsítása

Posted by | · · · · · | Webstar Works | Nincs hozzászólás a(z) Android-os cocos2d-x környezet fordításának felgyorsítása bejegyzéshez

Ez egy igen jól hangzó cím! A projekt jelenlegi állapotában (tehát csupán a HelloCpp példa másolata az sqlite3 és a cJSON könyvtárak implementálásával) egy fordítás, vagyis a natív (C/C++) rész fordítása 46.23 másodperc. Ez egy korábbi fordítást feltételező állapot, tehát a cocos2d-x függvénykönyvtárait már lefordította az első fordítás során, és mivel azok statikus függvénykönyvtárak csak tisztítás, vagy a módosítása után fordulnak le újra.

Ez adta az ötletet, hogy milyen jó lenne ha statikus függvénykönyvtárként le tudnám fordítani az sqlite3 és a cJSON függvénykönyvtárakat, mivel így nem fordulnának le minden egyes fordítás során.

A bejegyzésben leírt megoldások feltételezik a korábbi példák projekt környezetét, melyek elérhetőek itt, itt és itt.

Első lépésként létre kell hozni egy-egy Android.mk fájlt a Classes/Extensions/Sqlite és cJSON mappákban, a következő tartalmakkal.

Classes/Extensions/Sqlite/Android.mk Classes/Extensions/cJSON/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sqlite3_static
LOCAL_MODULE_FILENAME := libsqlite3
LOCAL_SRC_FILES := sqlite3.c
include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cjson_static
LOCAL_MODULE_FILENAME := libcjson
LOCAL_SRC_FILES := cJSON.c
include $(BUILD_STATIC_LIBRARY)

Ezután módosítanunk kell a jni/Android.mk fájlt, hogy a fordítási folyamatban is használja ezeket a statikus függvénykönyvtárakat.

A LOCAL_WHOLE_STATIC_LIBRARIES sor végére fűzzük az sqlite3_static valamint a cjson_static szavakat szóközzel elválasztva.

Tehát a:

LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static

sorból:

LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static sqlite3_static cjson_static

lesz.

Ez még mindig nem elég, be kell illesztenünk két sort szintén ugyanebbe a fájlba.
Az egyiket a $(call import-add-path sorok közé, tehát:

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d-x) 
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d-x/cocos2dx/platform/third_party/android/prebuilt) 
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d-x/CocosDenshion)

sorokból:

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d-x) 
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d-x/cocos2dx/platform/third_party/android/prebuilt) 
$(call import-add-path,$(LOCAL_PATH)/../../Classes/Extensions) 
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d-x/CocosDenshion)

lesz.

Utolsó lépésként még a betöltendő modulok közé is fel kell vennünk az új statikus könyvtárainkat.

$(call import-module,cocosdenshion) 
$(call import-module,cocos2dx) 
$(call import-module,extensions)

sorokból:

$(call import-module,cocosdenshion) 
$(call import-module,cocos2dx) 
$(call import-module,extensions) 
$(call import-module,Sqlite) 
$(call import-module,cJson)

lesz.

Ezek után 3,6 másodperces fordítási időt sikerült elérni, ami lényegesen gyorsabb mint a korábbi. (A korábbi 46 másodperc volt, tehát a cJSON és az sqlite3 ~43 másodperc alatt fordult le)

Természetesen ahogy gyarapodnak a sorok a forráskódjainkban a folyamat úgy lassul, de egy 43 másodperces rövidítés így is sokat jelent.

Gyorsítás még…

A blog bejegyzés írása közben találtam egy érdekes StackOverflow bejegyzést.

http://stackoverflow.com/questions/12640377/how-to-speed-up-android-ndk-builds

Félelmetesen egyszerű a megoldás, párhuzamosítsuk a fordítási folyamatot! 🙂 (Érdekesség: Az utóbbi két és fél hónap fejlesztés alatt, körülbelül 17 órával kevesebbet töltöttem volna fordítással…. a fene :S )

Magát a párhuzamosítást egy -j vagy beszédesebben –jobs kapcsolóval szabályozhatjuk. Használata egyszerű, a build_native.sh fájlban a következő sor(oka)t kell szerkesztenünk:


if [[ "$buildexternalsfromsource" ]]; then
   echo "Building external dependencies from source"
   "$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $*
else
   echo "Using prebuilt externals"
   "$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $*
fi

a következőre:


if [[ "$buildexternalsfromsource" ]]; then
   echo "Building external dependencies from source"
   "$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* --jobs=N
else
   echo "Using prebuilt externals"
   "$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* --jobs=N
fi

ahol N a fordítási folyamat által párhuzamosan használt szálak (job-ok)  száma.

Na de mennyi is legyen az N??

Elkezdtem próbálgatni a számokat, vagyis 2 hatványait.

Kipróbáltam pár beállítást, a teszt gépemben egy AMD Athlon(tm) II X4 635 CPU volt.

Az alábbi grafikon mutatja a fordítási idő alakulását a párhuzamos szálak függvényében:

forditas-magok

Ahol az X tengelyen a magok számát, az Y tengelyen a fordítási időt látjuk

A grafikonból látszik, hogy amíg nem értük el a processzor magok számát (az én esetemben 4) a párhuzamos szálak számával, addig komoly sebesség növekedést tapasztalhattunk. Amint túlléptünk ezen, a sebesség növekedés elhanyagolható. Ezért 4 esetleg 8 párhuzamos fordítási szálnál több használatának nem sok értelme van, csak a processzor által futtatott folyamatok száma növekszik, a sebesség kevésbé.

A saját build_native.sh fordítási szkriptünket módosítottam, hogy lekérje a futtató processzor magjainak számát, és ezzel megegyező számú párhuzamos szálon futtassa a fordítást. (Ez a módosítás is benne van a letölthető tömörített fájlban)

Összefoglalás

A bejegyzés magáért beszél, rengeteg időt nyerhetünk ezzel. Használjátok egészséggel!

Jó fejlesztést!


No Comments

Leave a comment