program define benchmark

    version 18.0
	syntax , cmd(string) [repeat(integer 1)] [save(string)]

	local from=1
	local to=c(processors_max)

	assert (`repeat'>=1)

	tempname tmp
	frame create `tmp'
	frame `tmp' {
	  generate int CPUs=.
	  generate long iteration=.
	  generate double Time=.
	  format Time %8.2f
	}

	forval c=`from'/`to' {
		quietly set processors `c'
		display as text "CPUs is set to: {result:`c'}" _continue

		// dry run to have the ado-files loaded, etc.
		quietly `cmd'

		forval i=1/`repeat' {
			preserve

			quietly {
				timer clear 1
				timer on 1
				`cmd'
				timer off 1
				timer list 1
				local t=r(t1)
			}
			frame post `tmp' (`c') (`i') (`t')
			restore
			display "." _continue
		}
		display ""
	}

	display as text `" {break}Average execution time over {result:`repeat'} runs (in seconds){break}"'
	frame `tmp' {
		if (`"`save'"'!="") frame copy `tmp' `save'
		graph box Time, over(CPUs) name(box) ytitle("Time, seconds")
		collapse Time, by(CPUs)
		sort CPUs
		generate double Ratio=Time[1]/Time
		format Ratio %8.2f
	    list, clean noobs
		graph bar Time, over(CPUs) name(bar) ytitle("Average time, seconds")
		graph bar Ratio, over(CPUs) name(ratio) ytitle("Acceleration over 1 CPU")
	}

end

// END OF FILE