########################################################################## # makefike ########################################################################## SHELL := bash .ONESHELL: ########################################################################## EXE = $(basename $(SRC)) LOG = $(EXE:=.log) REP = 10 SRC = $(wildcard *.cc) STA = $(EXE:=.sta) TXT = $(EXE:=.txt) W1 = 12 W2 = 8 W3 != bc <<< "$(W1) + $(W2) * 9" ########################################################################## CXXFLAGS = -fanalyzer -O3 -std=c++20 -Wall ########################################################################## all: @if make -qs $(TXT); then make -s sort else make -s stat fi clave: @printf '%$(W3)s\n' | tr ' ' '-' # echo -e "clave: una calavera ('☠') tras el nombre indica error" echo "clave: una símbolo ('#') tras el nombre indica error" echo " n : número de hebras que atraviesan la barrera" echo " t : tiempo real de ejecución" echo " amin : mínimo número de antes" echo " amax : máximo número de antes" echo " dmin : mínimo número de después" echo " dmax : máximo número de después" echo " msg : número total de mensajes" echo " cpu : tiempo de cpu promedio de 10 ejecuciones (ms)" echo " ratio : msg / tiempo (msg/ms)" clean: -rm -fv $(CAC) $(CAL) $(DAT) $(EXE) $(FOL) $(LOG) $(REC) $(STA) $(SVG) $(TXT) core* *-[[:digit:]]*.log *.cal-* *~ -find -mindepth 2 -maxdepth 2 -name makefile -execdir make $@ \; default: n8 10ms exe: $(EXE) sort: clave @declare -a N=(2 8 9 10) declare -a F=('n' 'msg' 'cpu' 'ratio') declare -a R=('r' 'r' '' 'r') for (( i=0; i<$${#N[@]}; ++i )); do printf '%$(W3)s\n' | tr ' ' '-' head -n 1 $(firstword $(TXT)) | sed "s/ $${F[$$i]}/\[$${F[$$i]}\]/" printf '%$(W3)s\n' | tr ' ' '-' make stat | grep -v ':' | grep -E -w "$$(echo $(EXE) | tr ' ' '|')" | sort -k$${N[$$i]},$${N[$$i]}$${R[$$i]} -k14,14nr -k13,13n -k5,5nr -s done printf '%$(W3)s\n' | tr ' ' '-' stat: clave @printf '%$(W3)s\n' | tr ' ' '-' for i in $(TXT); do make -s $$i if [[ "$$i" == "$(firstword $(TXT))" ]]; then head -n1 $$i printf '%$(W3)s\n' | tr ' ' '-' fi tail -n1 $$i done printf '%$(W3)s\n' | tr ' ' '-' #################################################| head -n1################# boost: LDLIBS += -lboost_system -lboost_thread pthread: CXXFLAGS += -pthread ########################################################################## %.log: % @for (( i=0; i<$(REP); ++i )); do ./$< > $<-$$i.log done sort -k1,1n -k2,2g $$(ls -S $<-[[:digit:]]*.log | head -n1) | uniq -c > $@ -rm -f $<-[[:digit:]]*.log %.sta: % @LC_ALL=C perf stat -r 10 -x ' ' -- ./$< 1> /dev/null 2> >(grep 'task-clock' | cut -d' ' -f1 > $@) %.txt: %.log %.sta @LC_ALL=C n=$$(grep después $*.log | wc -l) t=$$(sed -n 's/^ std::this_thread::sleep_for(\(.*\));/\1/p' $*.cc) amin=$$(grep antes $*.log | sort | head -n1 | sed 's/\(.*\) .* .*/\1/') amax=$$(grep antes $*.log | sort | tail -n1 | sed 's/\(.*\) .* .*/\1/') dmin=$$(grep después $*.log | sort | head -n1 | sed 's/\(.*\) .* .*/\1/') dmax=$$(grep después $*.log | sort | tail -n1 | sed 's/\(.*\) .* .*/\1/') msg=$$(cat $*.log | tr -s ' ' | cut -d' ' -f2 | paste -sd+ | bc) cpu=$$(cat $*.sta) ratio=$$(printf '%.1f' $$(bc -l <<< "$$msg / $$cpu")) cpu=$$(printf '%.1f' $$(cat $*.sta)) if (( n == 0 )); then amin=$${amin:=0} amax=$${amax:=0} dmin=$${dmin:=0} dmax=$${dmax:=0} fi if (( (amax - dmin) > 2 )); then prog="$*#"; else prog="$*"; fi printf '%$(W1)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s\n' programa n t amin amax dmin dmax msg cpu ratio > $@ printf '%$(W1)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s%$(W2)s\n' $$prog $$n $$t $$amin $$amax $$dmin $$dmax $$msg $$cpu $$ratio >> $@ ########################################################################## n%: $(SRC) @n=$@ sed --follow-symlinks -i "s/const size_t N = .*;/const size_t N = $${n:1};/" $^ %ms: $(SRC) @sed --follow-symlinks -i "s/^ std::this_thread::sleep_for(.*);/ std::this_thread::sleep_for($@);/" $^ ########################################################################## .PHONY: all clean clave default exe sort stat .PRECIOUS: $(LOG) $(STA) $(TXT) ########################################################################## CAC = $(EXE:=.cac) CAL = $(EXE:=.cal) DAT = $(EXE:=.dat) FOL = $(EXE:=.flo) REC = $(EXE:=.rec) SVG = $(EXE:=.svg) %.cga: %.cac cg_annotate --auto=yes $< %.dat: % -perf record --call-graph=dwarf -o $@ -- ./$< %.cac: % -valgrind --cachegrind-out-file=$@ --cache-sim=yes --demangle=yes --tool=cachegrind ./$< %.cal: % -valgrind --branch-sim=yes --cacheuse=yes --callgrind-out-file=$@ --cache-sim=yes --collect-jumps=yes --demangle=yes --dump-instr=yes --instr-atstart=yes -q --separate-threads=yes --tool=callgrind --trace-jump=yes ./$< %.fg: %.svg eog $< & %.fol: %.dat -perf script -i $< | stackcollapse-perf.pl | grep -v cpu_idle > $@ %.hel: % valgrind -s --tool=helgrind ./$< %.kcg: %.cal kcachegrind $< %.leak: % # valgrind --leak-check=full --show-error-list=yes --show-leak-kinds=all --track-origins=yes --verbose ./$< valgrind --leak-check=summary --show-leak-kinds=all --track-origins=yes ./$< %.ltrace: % @printf "%79s\n \t$*\n%79s\n" | tr ' ' '#' ltrace -cf ./$< |& c++filt | cut -c 1-$$(tput cols) %.perf: %.dat -perf report -i $< %.strace: % @printf "%79s\n \t$*\n%79s\n" | tr ' ' '#' strace -cf -qq ./$< |& c++filt | cut -c 1-$$(tput cols) %.svg: %.fol flamegraph.pl $< > $@ %.trace: % @printf "%79s\n \t$*\n%79s\n" | tr ' ' '#' ltrace -cfS ./$< |& c++filt | cut -c 1-$$(tput cols) ##########################################################################