bench.sh 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #!/bin/bash
  2. # download the code and all its dependencies
  3. _go_get() {
  4. go get -u \
  5. "github.com/ugorji/go/codec" "github.com/ugorji/go/codec"/codecgen \
  6. github.com/tinylib/msgp/msgp github.com/tinylib/msgp \
  7. github.com/pquerna/ffjson/ffjson github.com/pquerna/ffjson \
  8. github.com/Sereal/Sereal/Go/sereal \
  9. bitbucket.org/bodhisnarkva/cbor/go \
  10. github.com/davecgh/go-xdr/xdr2 \
  11. gopkg.in/mgo.v2/bson \
  12. gopkg.in/vmihailenco/msgpack.v2 \
  13. github.com/json-iterator/go \
  14. go.mongodb.org/mongo-driver/bson \
  15. github.com/mailru/easyjson/...
  16. }
  17. # add generated tag to the top of each file
  18. _prependbt() {
  19. cat > ${2} <<EOF
  20. // +build generated
  21. EOF
  22. cat ${1} >> ${2}
  23. rm -f ${1}
  24. }
  25. # To run the full suite of benchmarks, including executing against the external frameworks
  26. # listed above, you MUST first run code generation for the frameworks that support it.
  27. #
  28. # If you want to run the benchmarks against code generated values.
  29. # Then first generate the code generated values from values_test.go named typed.
  30. # we cannot normally read a _test.go file, so temporarily copy it into a readable file.
  31. _gen() {
  32. local zsfx="_generated_test.go"
  33. # local z=`pwd`
  34. # z=${z%%/src/*}
  35. # Note: ensure you run the codecgen for this codebase
  36. cp values_test.go v.go &&
  37. echo "codecgen ..." &&
  38. codecgen -nx -rt codecgen -t 'codecgen generated' -o values_codecgen${zsfx} -d 19780 v.go &&
  39. echo "msgp ... " &&
  40. msgp -unexported -tests=false -o=m9.go -file=v.go &&
  41. _prependbt m9.go values_msgp${zsfx} &&
  42. echo "easyjson ... " &&
  43. easyjson -all -no_std_marshalers -omit_empty -output_filename e9.go v.go &&
  44. _prependbt e9.go values_easyjson${zsfx} &&
  45. echo "ffjson ... " &&
  46. ffjson -force-regenerate -reset-fields -w f9.go v.go &&
  47. _prependbt f9.go values_ffjson${zsfx} &&
  48. sed -i '' -e 's+ MarshalJSON(+ _MarshalJSON(+g' values_ffjson${zsfx} &&
  49. sed -i '' -e 's+ UnmarshalJSON(+ _UnmarshalJSON(+g' values_ffjson${zsfx} &&
  50. rm -f easyjson-bootstrap*.go ffjson-inception* &&
  51. rm -f v.go &&
  52. echo "... DONE"
  53. }
  54. # run the full suite of tests
  55. #
  56. # Basically, its a sequence of
  57. # go test -tags "alltests x safe codecgen generated" -bench "CodecSuite or AllSuite or XSuite" -benchmem
  58. #
  59. _suite_tests() {
  60. if [[ "${do_x}" = "1" ]]; then
  61. printf "\n==== X Baseline ====\n"
  62. go test "${zargs[@]}" -tags x -v
  63. else
  64. printf "\n==== Baseline ====\n"
  65. go test "${zargs[@]}" -v
  66. fi
  67. if [[ "${do_x}" = "1" ]]; then
  68. printf "\n==== X Generated ====\n"
  69. go test "${zargs[@]}" -tags "x generated" -v
  70. else
  71. printf "\n==== Generated ====\n"
  72. go test "${zargs[@]}" -tags "generated" -v
  73. fi
  74. }
  75. _suite_tests_strip_file_line() {
  76. # sed -e 's/^\([^a-zA-Z0-9]\+\)[a-zA-Z0-9_]\+\.go:[0-9]\+:/\1/'
  77. sed -e 's/[a-zA-Z0-9_]*.go:[0-9]*://g'
  78. }
  79. _suite_any() {
  80. local x="$1"
  81. local g="$2"
  82. local b="$3"
  83. shift; shift; shift
  84. local a=( "" "safe" "notfastpath" "notfastpath safe" "codecgen" "codecgen safe")
  85. if [[ "$g" = "g" ]]; then a=( "generated" "generated safe"); fi
  86. for i in "${a[@]}"; do
  87. echo ">>>> bench TAGS: 'alltests $x $i' SUITE: $b"
  88. go test "${zargs[@]}" -tags "alltests $x $i" -bench "$b" -benchmem "$@"
  89. done
  90. }
  91. # _suite() {
  92. # local t="alltests x"
  93. # local a=( "" "safe" "notfastpath" "notfastpath safe" "codecgen" "codecgen safe")
  94. # for i in "${a[@]}"
  95. # do
  96. # echo ">>>> bench TAGS: '$t $i' SUITE: BenchmarkCodecXSuite"
  97. # go test "${zargs[@]}" -tags "$t $i" -bench BenchmarkCodecXSuite -benchmem "$@"
  98. # done
  99. # }
  100. # _suite_gen() {
  101. # local t="alltests x"
  102. # local b=( "generated" "generated safe")
  103. # for i in "${b[@]}"
  104. # do
  105. # echo ">>>> bench TAGS: '$t $i' SUITE: BenchmarkCodecXGenSuite"
  106. # go test "${zargs[@]}" -tags "$t $i" -bench BenchmarkCodecXGenSuite -benchmem "$@"
  107. # done
  108. # }
  109. # _suite_json() {
  110. # local t="alltests x"
  111. # local a=( "" "safe" "notfastpath" "notfastpath safe" "codecgen" "codecgen safe")
  112. # for i in "${a[@]}"
  113. # do
  114. # echo ">>>> bench TAGS: '$t $i' SUITE: BenchmarkCodecQuickAllJsonSuite"
  115. # go test "${zargs[@]}" -tags "$t $i" -bench BenchmarkCodecQuickAllJsonSuite -benchmem "$@"
  116. # done
  117. # }
  118. # _suite_very_quick_json() {
  119. # # Quickly get numbers for json, stdjson, jsoniter and json (codecgen)"
  120. # echo ">>>> very quick json bench"
  121. # go test "${zargs[@]}" -tags "alltests x" -bench "__(Json|Std_Json|JsonIter)__" -benchmem "$@"
  122. # echo
  123. # go test "${zargs[@]}" -tags "alltests codecgen" -bench "__Json____" -benchmem "$@"
  124. # }
  125. _suite_very_quick_json_via_suite() {
  126. # Quickly get numbers for json, stdjson, jsoniter and json (codecgen)"
  127. echo ">>>> very quick json bench"
  128. local prefix="BenchmarkCodecVeryQuickAllJsonSuite/json-all-bd1......../"
  129. go test "${zargs[@]}" -tags "alltests x" -bench BenchmarkCodecVeryQuickAllJsonSuite -benchmem "$@" |
  130. sed -e "s+^$prefix++"
  131. echo "---- CODECGEN RESULTS ----"
  132. go test "${zargs[@]}" -tags "x generated" -bench "__(Json|Easyjson)__" -benchmem "$@"
  133. }
  134. _suite_very_quick_json_non_suite() {
  135. # Quickly get numbers for json, stdjson, jsoniter and json (codecgen)"
  136. echo ">>>> very quick json bench"
  137. for j in "En" "De"; do
  138. echo "---- codecgen ----"
  139. # go test "${zargs[@]}" -tags "generated" -bench "__(Json|Easyjson)__.*${j}" -benchmem "$@"
  140. go test "${zargs[@]}" -tags "x generated" -bench "__(Json|Easyjson)__.*${j}" -benchmem "$@"
  141. echo "---- no codecgen ----"
  142. # go test "${zargs[@]}" -tags "" -bench "__(Json|Std_Json|JsonIter)__.*${j}" -benchmem "$@"
  143. go test "${zargs[@]}" -tags "x" -bench "__(Json|Std_Json|JsonIter)__.*${j}" -benchmem "$@"
  144. echo
  145. done
  146. }
  147. _suite_very_quick_json_only_profile() {
  148. local a="Json"
  149. case "$1" in
  150. Json|Cbor|Msgpack|Simple|Binc) a="${1}"; shift ;;
  151. esac
  152. local b="${1}"
  153. go test "${zargs[@]}" -tags "alltests" -bench "__${a}__.*${b}" \
  154. -benchmem -benchtime 4s \
  155. -cpuprofile cpu.out -memprofile mem.out -memprofilerate 1
  156. }
  157. _suite_trim_output() {
  158. grep -v -E "^(goos:|goarch:|pkg:|PASS|ok|=== RUN|--- PASS)"
  159. }
  160. _usage() {
  161. printf "usage: bench.sh -[dcbsgjqp] for \n"
  162. printf "\t-d download\n"
  163. printf "\t-c code-generate\n"
  164. printf "\t-tx tests (show stats for each format and whether encoded == decoded); if x, do external also\n"
  165. printf "\t-sgx run test suite for codec; if g, use generated files; if x, do external also\n"
  166. printf "\t-jqp run test suite for [json, json-quick, json-profile]\n"
  167. }
  168. _main() {
  169. if [[ "$1" == "" || "$1" == "-h" || "$1" == "-?" ]]
  170. then
  171. _usage
  172. return 1
  173. fi
  174. local zargs=("-count" "1")
  175. local args=()
  176. local do_x="0"
  177. local do_g="0"
  178. while getopts "dcbsjqptxklg" flag
  179. do
  180. case "$flag" in
  181. d|c|b|s|j|q|p|t|x|k|l|g) args+=( "$flag" ) ;;
  182. *) _usage; return 1 ;;
  183. esac
  184. done
  185. shift "$((OPTIND-1))"
  186. [[ " ${args[*]} " == *"x"* ]] && do_x="1"
  187. [[ " ${args[*]} " == *"g"* ]] && do_g="1"
  188. [[ " ${args[*]} " == *"k"* ]] && zargs+=("-gcflags" "all=-B")
  189. [[ " ${args[*]} " == *"l"* ]] && zargs+=("-gcflags" "all=-l=4")
  190. [[ " ${args[*]} " == *"d"* ]] && _go_get "$@"
  191. [[ " ${args[*]} " == *"c"* ]] && _gen "$@"
  192. [[ " ${args[*]} " == *"s"* && "${do_x}" == 0 && "${do_g}" == 0 ]] && _suite_any - - BenchmarkCodecSuite "$@" | _suite_trim_output
  193. [[ " ${args[*]} " == *"s"* && "${do_x}" == 0 && "${do_g}" == 1 ]] && _suite_any - g BenchmarkCodecSuite "$@" | _suite_trim_output
  194. [[ " ${args[*]} " == *"s"* && "${do_x}" == 1 && "${do_g}" == 0 ]] && _suite_any x - BenchmarkCodecXSuite "$@" | _suite_trim_output
  195. [[ " ${args[*]} " == *"s"* && "${do_x}" == 1 && "${do_g}" == 1 ]] && _suite_any x g BenchmarkCodecXGenSuite "$@" | _suite_trim_output
  196. [[ " ${args[*]} " == *"j"* ]] && _suite_any x - BenchmarkCodecQuickAllJsonSuite "$@" | _suite_trim_output
  197. [[ " ${args[*]} " == *"q"* ]] && _suite_very_quick_json_non_suite "$@" | _suite_trim_output
  198. [[ " ${args[*]} " == *"p"* ]] && _suite_very_quick_json_only_profile "$@" | _suite_trim_output
  199. [[ " ${args[*]} " == *"t"* ]] && _suite_tests "$@" | _suite_trim_output | _suite_tests_strip_file_line
  200. true
  201. # shift $((OPTIND-1))
  202. }
  203. if [ "." = `dirname $0` ]
  204. then
  205. _main "$@"
  206. else
  207. echo "bench.sh must be run from the directory it resides in"
  208. _usage
  209. fi