Wednesday, March 02, 2011

FTQ for platform jitter analysis

FTQ is a useful tool dug up by Bruce which we've started using for jitter analysis and it's showing up some surprising results. The idea is simple - how many iterations of a variable can be performed in a fixed time.

I started by running the threaded version on our 8 core, dual cpu server for approximately 3 minutes using the following command:

t_ftq -t 8 -n 450000

Using Octave, I calculated the variance (42133) and standard deviation (2485.1.) Plotting this gave this over populated graph:


Next I thought I'd run it over seven cores and got a smoother profile. But graphs are fine and dandy but you need to look at the data and the percentiles. So as a first pass, I wrote this nifty awk script:

#!/bin/bash

FACTOR=2
CORES="`grep -c processor /proc/cpuinfo`"
THREADS=`echo "$CORES * $FACTOR" | bc`

while [ "$THREADS" -gt 1 ]
do
./t_ftq -t $THREADS

for FILE in ftq*counts.dat
do

awk 'BEGIN {

minimum = 4500000
maximum = 0
average = 0
}
{
if($1 < minimum =" $1"> maximum)
{
maximum = $1
}

average += $1

}
END {
printf("THREADS=%d min=%d:max=%d:avg=%d:var=%d\n", '"$THREADS"', minimum, maximum, average/NR, maximum-minimum)
}' $FILE

done

THREADS="`expr $THREADS - 1`"

rm -f *.dat

echo

done

exit 0

Which produced this output when run with a loading factor of 1:

THREADS=8 min=19080:max=43090:avg=41247:var=24010
THREADS=8 min=8401:max=43090:avg=41971:var=34689
THREADS=8 min=8401:max=43090:avg=42596:var=34689
THREADS=8 min=8956:max=43090:avg=42453:var=34134
THREADS=8 min=21515:max=43090:avg=42326:var=21575
THREADS=8 min=11157:max=43090:avg=42548:var=31933
THREADS=8 min=6351:max=43090:avg=42619:var=36739
THREADS=8 min=6351:max=43090:avg=42381:var=36739

THREADS=7 min=20666:max=43090:avg=42217:var=22424
THREADS=7 min=7591:max=43090:avg=42264:var=35499
THREADS=7 min=7591:max=43090:avg=42487:var=35499
THREADS=7 min=25263:max=43090:avg=42566:var=17827
THREADS=7 min=20513:max=43090:avg=42603:var=22577
THREADS=7 min=15328:max=43090:avg=42528:var=27762
THREADS=7 min=9555:max=43090:avg=41859:var=33535

THREADS=6 min=9324:max=43090:avg=40872:var=33766
THREADS=6 min=10144:max=43090:avg=41454:var=32946
THREADS=6 min=29223:max=43090:avg=42749:var=13867
THREADS=6 min=25239:max=43090:avg=42590:var=17851
THREADS=6 min=20013:max=43090:avg=42357:var=23077
THREADS=6 min=4612:max=43090:avg=42114:var=38478

THREADS=5 min=457:max=43090:avg=42351:var=42633
THREADS=5 min=457:max=43090:avg=41645:var=42633
THREADS=5 min=15064:max=43090:avg=41190:var=28026
THREADS=5 min=16821:max=43090:avg=41614:var=26269
THREADS=5 min=15204:max=43090:avg=41272:var=27886

THREADS=4 min=21561:max=43090:avg=42436:var=21529
THREADS=4 min=23847:max=43090:avg=42158:var=19243
THREADS=4 min=5588:max=43090:avg=41406:var=37502
THREADS=4 min=5588:max=43090:avg=41282:var=37502

THREADS=3 min=26739:max=43090:avg=42303:var=16351
THREADS=3 min=19834:max=43090:avg=42021:var=23256
THREADS=3 min=12879:max=43090:avg=41332:var=30211

THREADS=2 min=10438:max=43090:avg=41910:var=32652
THREADS=2 min=10438:max=43090:avg=41816:var=32652

Which is quite surprising in that on the two thread run, there are surprising minimums. In 5, 7 and 8, two adjacent threads have the same minima/maxima which is weird. So with FACTOR set to 2, this is what we get:

THREADS=16 min=23:max=43090:avg=39844:var=43067
THREADS=16 min=22:max=43090:avg=41978:var=43068
THREADS=16 min=9:max=43090:avg=39131:var=43081
THREADS=16 min=9:max=43090:avg=37050:var=43081
THREADS=16 min=17:max=43090:avg=39012:var=43073
THREADS=16 min=17:max=43090:avg=40153:var=43073
THREADS=16 min=4:max=43090:avg=41036:var=43086
THREADS=16 min=23:max=43090:avg=40206:var=43067
THREADS=16 min=32:max=43090:avg=40174:var=43058
THREADS=16 min=68:max=43090:avg=40551:var=43022
THREADS=16 min=23:max=43090:avg=40927:var=43067
THREADS=16 min=23:max=43090:avg=40747:var=43067
THREADS=16 min=28:max=43090:avg=40886:var=43062
THREADS=16 min=8:max=43090:avg=39380:var=43082
THREADS=16 min=8:max=43090:avg=36551:var=43082
THREADS=16 min=22:max=43090:avg=38743:var=43068

THREADS=15 min=139:max=43090:avg=39622:var=42951
THREADS=15 min=12:max=43090:avg=40690:var=43078
THREADS=15 min=64:max=43090:avg=39721:var=43026
THREADS=15 min=3:max=43090:avg=39207:var=43087
THREADS=15 min=3:max=43090:avg=40143:var=43087
THREADS=15 min=3213:max=43090:avg=41611:var=39877
THREADS=15 min=18:max=43090:avg=39399:var=43072
THREADS=15 min=18:max=43090:avg=39894:var=43072
THREADS=15 min=3:max=43090:avg=39579:var=43087
THREADS=15 min=3:max=43090:avg=39027:var=43087
THREADS=15 min=9:max=43090:avg=39910:var=43081
THREADS=15 min=77:max=43090:avg=40085:var=43013
THREADS=15 min=16:max=43090:avg=40392:var=43074
THREADS=15 min=13:max=43090:avg=41455:var=43077
THREADS=15 min=12:max=43090:avg=41152:var=43078

THREADS=14 min=63:max=43090:avg=41229:var=43027
THREADS=14 min=64:max=43090:avg=40931:var=43026
THREADS=14 min=12:max=43090:avg=39935:var=43078
THREADS=14 min=12:max=43090:avg=39307:var=43078
THREADS=14 min=37:max=43090:avg=39408:var=43053
THREADS=14 min=202:max=43090:avg=41830:var=42888
THREADS=14 min=18517:max=43090:avg=42397:var=24573
THREADS=14 min=87:max=43090:avg=41449:var=43003
THREADS=14 min=87:max=43090:avg=41352:var=43003
THREADS=14 min=17:max=43090:avg=41919:var=43073
THREADS=14 min=17:max=43090:avg=41896:var=43073
THREADS=14 min=5902:max=43090:avg=42156:var=37188
THREADS=14 min=3620:max=43090:avg=41960:var=39470
THREADS=14 min=64:max=43090:avg=41448:var=43026

THREADS=13 min=20:max=43090:avg=39998:var=43070
THREADS=13 min=124:max=43090:avg=40715:var=42966
THREADS=13 min=1:max=43090:avg=38856:var=43089
THREADS=13 min=1:max=43090:avg=39265:var=43089
THREADS=13 min=18:max=43090:avg=40026:var=43072
THREADS=13 min=18:max=43090:avg=40526:var=43072
THREADS=13 min=1:max=43090:avg=38695:var=43089
THREADS=13 min=1:max=43090:avg=38107:var=43089
THREADS=13 min=76:max=43090:avg=40457:var=43014
THREADS=13 min=76:max=43090:avg=39891:var=43014
THREADS=13 min=283:max=43090:avg=40472:var=42807
THREADS=13 min=119:max=43090:avg=40724:var=42971
THREADS=13 min=119:max=43090:avg=40402:var=42971

THREADS=12 min=130:max=43090:avg=42537:var=42960
THREADS=12 min=10:max=43090:avg=40826:var=43080
THREADS=12 min=54:max=43090:avg=39270:var=43036
THREADS=12 min=151:max=43090:avg=41114:var=42939
THREADS=12 min=151:max=43090:avg=40087:var=42939
THREADS=12 min=466:max=43090:avg=41241:var=42624
THREADS=12 min=164:max=43090:avg=42035:var=42926
THREADS=12 min=164:max=43090:avg=41621:var=42926
THREADS=12 min=3398:max=43090:avg=41298:var=39692
THREADS=12 min=3398:max=43090:avg=41979:var=39692
THREADS=12 min=758:max=43090:avg=42505:var=42332
THREADS=12 min=10:max=43090:avg=41605:var=43080

THREADS=11 min=1416:max=43090:avg=41151:var=41674
THREADS=11 min=9554:max=43090:avg=42649:var=33536
THREADS=11 min=1416:max=43090:avg=41709:var=41674
THREADS=11 min=21903:max=43090:avg=42534:var=21187
THREADS=11 min=93:max=43090:avg=41279:var=42997
THREADS=11 min=93:max=43090:avg=40962:var=42997
THREADS=11 min=239:max=43090:avg=41907:var=42851
THREADS=11 min=53:max=43090:avg=42096:var=43037
THREADS=11 min=53:max=43090:avg=41543:var=43037
THREADS=11 min=408:max=43090:avg=40986:var=42682
THREADS=11 min=1971:max=43090:avg=42006:var=41119

THREADS=10 min=27331:max=43090:avg=42582:var=15759
THREADS=10 min=5713:max=43090:avg=42033:var=37377
THREADS=10 min=3765:max=43090:avg=41529:var=39325
THREADS=10 min=3765:max=43090:avg=42201:var=39325
THREADS=10 min=207:max=43090:avg=42670:var=42883
THREADS=10 min=207:max=43090:avg=41863:var=42883
THREADS=10 min=4105:max=43090:avg=40956:var=38985
THREADS=10 min=140:max=43090:avg=41083:var=42950
THREADS=10 min=140:max=43090:avg=42134:var=42950
THREADS=10 min=176:max=43090:avg=41888:var=42914

THREADS=9 min=629:max=43090:avg=41771:var=42461
THREADS=9 min=1938:max=43090:avg=41748:var=41152
THREADS=9 min=435:max=43090:avg=41567:var=42655
THREADS=9 min=435:max=43090:avg=41126:var=42655
THREADS=9 min=7019:max=43090:avg=40533:var=36071
THREADS=9 min=133:max=43090:avg=41031:var=42957
THREADS=9 min=133:max=43090:avg=41695:var=42957
THREADS=9 min=118:max=43090:avg=41558:var=42972
THREADS=9 min=65:max=43090:avg=41412:var=43025

THREADS=8 min=3028:max=43090:avg=41970:var=40062
THREADS=8 min=4713:max=43090:avg=41803:var=38377
THREADS=8 min=4713:max=43090:avg=41633:var=38377
THREADS=8 min=1184:max=43090:avg=41842:var=41906
THREADS=8 min=1184:max=43090:avg=41401:var=41906
THREADS=8 min=12598:max=43090:avg=41587:var=30492
THREADS=8 min=19076:max=43090:avg=42217:var=24014
THREADS=8 min=9136:max=43090:avg=42355:var=33954

THREADS=7 min=12260:max=43090:avg=41692:var=30830
THREADS=7 min=12489:max=43090:avg=42036:var=30601
THREADS=7 min=272:max=43090:avg=42520:var=42818
THREADS=7 min=272:max=43090:avg=42526:var=42818
THREADS=7 min=18847:max=43090:avg=42556:var=24243
THREADS=7 min=12026:max=43090:avg=42078:var=31064
THREADS=7 min=12026:max=43090:avg=41752:var=31064

THREADS=6 min=14357:max=43090:avg=42024:var=28733
THREADS=6 min=14357:max=43090:avg=42175:var=28733
THREADS=6 min=22221:max=43090:avg=42552:var=20869
THREADS=6 min=23168:max=43090:avg=42747:var=19922
THREADS=6 min=26899:max=43090:avg=42721:var=16191
THREADS=6 min=6890:max=43090:avg=42610:var=36200

THREADS=5 min=22566:max=43090:avg=42447:var=20524
THREADS=5 min=16706:max=43090:avg=42329:var=26384
THREADS=5 min=16706:max=43090:avg=42252:var=26384
THREADS=5 min=15030:max=43090:avg=42335:var=28060
THREADS=5 min=15030:max=43090:avg=42263:var=28060

THREADS=4 min=7988:max=43090:avg=42158:var=35102
THREADS=4 min=8031:max=43090:avg=42410:var=35059
THREADS=4 min=10691:max=43090:avg=42238:var=32399
THREADS=4 min=10691:max=43090:avg=41725:var=32399

THREADS=3 min=15163:max=43090:avg=42264:var=27927
THREADS=3 min=17850:max=43090:avg=42188:var=25240
THREADS=3 min=6638:max=43090:avg=41799:var=36452

THREADS=2 min=6497:max=43090:avg=41353:var=36593
THREADS=2 min=6497:max=43090:avg=41521:var=36593

So a very rough heuristic visual analysis tells me that I'd be best having 6 cores at most running my trading engine. Time to play with Octave...