Skip to content

Instantly share code, notes, and snippets.

@elaberge
Created November 4, 2016 22:56
Show Gist options
  • Save elaberge/2e51f1178b2dda8fdcd0dd6a4494668c to your computer and use it in GitHub Desktop.
Save elaberge/2e51f1178b2dda8fdcd0dd6a4494668c to your computer and use it in GitHub Desktop.
Unity App Size Analyzer
#!/usr/bin/env bash
function dumpBundle {
FILE=$1
OUTDIR=$2
LZMADIR=$3
OUTPATH="$OUTDIR/$FILE"
LZMAPATH="$LZMADIR/$FILE"
mkdir -p $(dirname "$OUTPATH")
cp "$TMP_FOLDER/$FILE" "$OUTPATH.unity3d"
$DISUNITY extract-raw "$OUTPATH.unity3d" > /dev/null 2>&1
CABDIR=`ls -d $OUTPATH/CAB-* 2>/dev/null`
if [ -n "$CABDIR" ]; then
mv $CABDIR/* "$OUTPATH/"
rmdir "$CABDIR"
fi
while read line; do
NAME=`echo $line | cut -d'|' -f6 | tr -d '[[:space:]]'`
if [ -n "$NAME" ]; then
ID=`echo $line | cut -d'|' -f1`
printf -v PADDED "%06d" $ID
CATEGORY=`echo $line | cut -d'|' -f3 | tr -d '[[:space:]]'`
mv "$OUTPATH/$CATEGORY/$PADDED.bin" "$OUTPATH/$CATEGORY/$NAME.bin"
fi
done < <($DISUNITY list "$OUTPATH.unity3d" 2>/dev/null | grep "^[0-9]\+")
rm "$OUTPATH.unity3d"
mkdir -p $(dirname "$LZMAPATH")
cp -r "$OUTPATH" "$LZMAPATH"
find "$LZMAPATH" -type f -name "*.bin" -print0 | xargs -0 -n32 -P8 lzma -z9
}
function explode {
FILE=$1
COMPRESSED=$2
DIR=$(dirname "$FILE")
mkdir -p "dump/compressed/$DIR"
dd if=/dev/zero of="dump/compressed/$FILE" bs=$COMPRESSED count=1 > /dev/null 2>&1
if [[ $FILE =~ /((level[0-9]+)|(mainData)|(.*\.assets)|(unity default resources)|(.*\.unity3d))$ ]]; then
dumpBundle "$FILE" dump/unbundled dump/lzma
else
mkdir -p "dump/unbundled/$DIR"
mkdir -p "dump/lzma/$DIR"
cp "$TMP_FOLDER/$FILE" "dump/unbundled/$FILE"
cp "dump/compressed/$FILE" "dump/lzma/$FILE"
fi
}
BASEDIR=$(dirname "$0")
DISUNITY="java -jar $BASEDIR/disunity/disunity.jar"
TMP_FOLDER=`mktemp -d -t 'unitySize'`
echo "Decompressing $1" 1>&2
unzip -q $1 -d $TMP_FOLDER
PLISTFILE=`find $TMP_FOLDER -type f -maxdepth 3 -name Info.plist`
EXENAME=`defaults read $PLISTFILE CFBundleExecutable`
EXEPATH=$(dirname "${PLISTFILE#$TMP_FOLDER/}")/$EXENAME
DISTSIZE=0
while read line; do
DIR=`echo $line | cut -c 1`
SIZE=`echo $line | cut -d' ' -f4`
COMPRESSED=`echo $line | cut -d' ' -f6`
FILE=`echo $line | cut -d' ' -f10-`
# Exécutable encrypté
if [ "$FILE" == "$EXEPATH" ]; then
COMPRESSED=$SIZE
fi
if [ "$DIR" != "d" ]; then
explode "$FILE" "$COMPRESSED"
fi
((DISTSIZE += COMPRESSED))
done < <(zipinfo --h-tl "$1")
echo "Expected distribution size: $DISTSIZE" 1>&2
rm -rf $TMP_FOLDER
@elaberge
Copy link
Author

elaberge commented Nov 4, 2016

This quick (well, slow) and dirty tool requires disunity (see line #57) to work. It uses macOS utilities and thus won't work on other systems without further modifications.

It takes an iOS Unity .ipa file as argument and creates files of similar sizes in the dump subfolder. It tries to rename these files to their initial asset files for diagnostic purpose.

A visual drive inspection utility such as Disk Inventory X can be used for a quick view of relative asset sizes by opening the Data subfolders in the application packages from the dump/lzma subfolder.

The script does not currently map file names for bundles containing multiple scenes, but it should be relatively trivial to fix.

@GabLeRoux
Copy link

GabLeRoux commented Nov 5, 2016

Hey Eric, thanks so much for this, I really appreciate that! :D This is going to help me a lot to on how to figure out what's heavy on my ios build ❤️ Life saver!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment