#!/bin/sh # # This script generates statistics (build size, speed) for successive # revisions of the code. It checks out git commits one an a time, compiles # various ports to determine their size, and runs pystone on the unix port. # Results are collected in the output file. # # Note: you will need to copy this file out of the tools directory before # executing because it does not exist in old revisions of the repository. # check that we are in the root directory of the repository if [ ! -d py -o ! -d ports/unix -o ! -d ports/stm32 ]; then echo "script must be run from root of the repository" exit 1 fi # output file for the data; data is appended if file already exists output=codestats.dat # utility programs RM=/bin/rm AWK=awk MAKE="make -j2" # these are the binaries that are built; some have 2 or 3 depending on version bin_unix=ports/unix/micropython bin_stm32=ports/stm32/build-PYBV10/firmware.elf bin_barearm_1=ports/bare-arm/build/flash.elf bin_barearm_2=ports/bare-arm/build/firmware.elf bin_minimal=ports/minimal/build/firmware.elf bin_cc3200_1=ports/cc3200/build/LAUNCHXL/application.axf bin_cc3200_2=ports/cc3200/build/LAUNCHXL/release/application.axf bin_cc3200_3=ports/cc3200/build/WIPY/release/application.axf # start at zero size; if build fails reuse previous valid size size_unix="0" size_stm32="0" size_barearm="0" size_minimal="0" size_cc3200="0" # start at zero pystones pystones="0" # this code runs pystone and averages the results pystoneavg=/tmp/pystoneavg.py cat > $pystoneavg << EOF import pystone samples = [pystone.pystones(300000)[1] for i in range(5)] samples.sort() stones = sum(samples[1:-1]) / (len(samples) - 2) # exclude smallest and largest print("stones %g" % stones) EOF function get_size() { if [ -r $2 ]; then size $2 | tail -n1 | $AWK '{print $1}' else echo $1 fi } function get_size2() { if [ -r $2 ]; then size $2 | tail -n1 | $AWK '{print $1}' elif [ -r $3 ]; then size $3 | tail -n1 | $AWK '{print $1}' else echo $1 fi } function get_size3() { if [ -r $2 ]; then size $2 | tail -n1 | $AWK '{print $1}' elif [ -r $3 ]; then size $3 | tail -n1 | $AWK '{print $1}' elif [ -r $4 ]; then size $4 | tail -n1 | $AWK '{print $1}' else echo $1 fi } # get the last revision in the data file; or start at v1.0 if no file if [ -r $output ]; then last_rev=$(tail -n1 $output | $AWK '{print $1}') else echo "# hash size_unix size_stm32 size_barearm size_minimal size_cc3200 pystones" > $output last_rev="v1.0" fi # get a list of hashes between last revision (exclusive) and main hashes=$(git log --format=format:"%H" --reverse ${last_rev}..main) #hashes=$(git log --format=format:"%H" --reverse ${last_rev}..main | $AWK '{if (NR % 10 == 0) print $0}') # do every 10th one for hash in $hashes; do #### checkout the revision #### git checkout $hash if [ $? -ne 0 ]; then echo "aborting" exit 1 fi #### apply patches to get it to build #### if grep -q '#if defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000000) // POSIX' unix/modtime.c; then echo apply patch git apply - << EOF diff --git a/unix/modtime.c b/unix/modtime.c index 77d2945..dae0644 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -55,10 +55,8 @@ void msec_sleep_tv(struct timeval *tv) { #define MP_CLOCKS_PER_SEC CLOCKS_PER_SEC #endif -#if defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000000) // POSIX -#define CLOCK_DIV 1000.0 -#elif defined(MP_CLOCKS_PER_SEC) && (MP_CLOCKS_PER_SEC == 1000) // WIN32 -#define CLOCK_DIV 1.0 +#if defined(MP_CLOCKS_PER_SEC) +#define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F) #else #error Unsupported clock() implementation #endif EOF fi #### unix #### $RM $bin_unix $MAKE -C ports/unix CFLAGS_EXTRA=-DNDEBUG size_unix=$(get_size $size_unix $bin_unix) # undo patch if it was applied git checkout unix/modtime.c #### stm32 #### $RM $bin_stm32 $MAKE -C ports/stm32 board=PYBV10 size_stm32=$(get_size $size_stm32 $bin_stm32) #### bare-arm #### $RM $bin_barearm_1 $bin_barearm_2 $MAKE -C ports/bare-arm size_barearm=$(get_size2 $size_barearm $bin_barearm_1 $bin_barearm_2) #### minimal #### if [ -r ports/minimal/Makefile ]; then $RM $bin_minimal $MAKE -C ports/minimal CROSS=1 size_minimal=$(get_size $size_minimal $bin_minimal) fi #### cc3200 #### if [ -r ports/cc3200/Makefile ]; then $RM $bin_cc3200_1 $bin_cc3200_2 $bin_cc3200_3 $MAKE -C ports/cc3200 BTARGET=application size_cc3200=$(get_size3 $size_cc3200 $bin_cc3200_1 $bin_cc3200_2 $bin_cc3200_3) fi #### run pystone #### if [ -x $bin_unix ]; then new_pystones=$($bin_unix $pystoneavg) # only update the variable if pystone executed successfully if echo $new_pystones | grep -q "^stones"; then pystones=$(echo $new_pystones | $AWK '{print $2}') fi fi #### output data for this commit #### echo "$hash $size_unix $size_stm32 $size_barearm $size_minimal $size_cc3200 $pystones" >> $output done # checkout main and cleanup git checkout main $RM $pystoneavg