moduleTest.MaybenchwhereimportSystem.TimeimportSystem.Cmd(system)-- ideally this should use System.Process in the future, but for the sake of a first version this will do.importData.Maybe(maybe,isJust,fromJust)importControl.Monad(when)importControl.Monad.State(MonadIO,liftIO)importSystem.Directory(findExecutable)importSystem.IO(putStr,hPutStr,hClose,hGetContents)importSystem.Process(waitForProcess,runInteractiveProcess)importTest.Maybench.Command(CommandModifier,Command(Cmd),modifyCmd)importTest.BenchPress(benchmark,mean)dataBenchmark=Benchmark{benchIters::Int,benchTimes::[TimeDiff]}run::MonadIOm=>CommandModifierm->m(String,String)runcmd=modifyCmdcmd>>=(\m->runC$m(Cmd""[]""))runC::MonadIOm=>Command->m(String,String)runC(Cmdexe'argsinput)=liftIO$doexe<-findExecutableexe'>>=maybe(fail$"cannot find "++exe')returnputStr"Running... "letcmd_str=unwords$mapshowSh(exe:args)putStrLncmd_str(output,err)<-runProcessWithInputexeargsinputreturn(output,err)whereshowShx|' '`elem`x=showx|otherwise=xrunProcessWithInput::FilePath->[String]->String->IO(String,String)runProcessWithInputcmdargsinput=do(pin,pout,perr,ph)<-runInteractiveProcesscmdargsNothingNothinghPutStrpininputhClosepinoutput<-hGetContentspoutwhen(output==output)$return()err<-hGetContentsperrwhen(err==err)$return()hClosepouthCloseperrwaitForProcessph-- should check exit code here...return(output,err)averageTime::String->String->String->Int->IODoubleaverageTimecmdsetupcleanupn=dostats<-benchmarkn(systemsetup)(const$systemcleanup)(const$systemcmd)return$mean$sndstatsshowTimeDiff::(String,TimeDiff)->StringshowTimeDiff(cmd,td)=casefilterisJust[helpertdYear"years",helpertdMonth"months",helpertdDay"days",helpertdHour"hours",helpertdMin"minutes",helpertdSec"seconds"]of[]->(showcmd)++" took less than a second."xs->(((showcmd)++" took ")++).intercalate", ".mapfromJust$xswherehelperaccessorstring=ifaccessortd>0then(Just(show(accessortd)++" "++string))elseNothingintercalate_[]=[]intercalatex(y:ys)=y++x++intercalatexysprintTimeDiff::(String,TimeDiff)->IO()printTimeDiff=putStrLn.showTimeDiffminute,hour,day,month,year::Intminute=60hour=minute*60day=hour*24month=day*30year=day*365timeDiffToSeconds::TimeDiff->InttimeDiffToSecondstd=tdSectd+(tdMintd)*minute+(tdHourtd)*hour+(tdDaytd)*day+(tdMonthtd)*month+(tdYeartd)*yearsecondsToTimeDiff::Int->TimeDiffsecondsToTimeDiffsec=normalizeTimeDiff$TimeDiff00000sec0compareTimes::Fractionala=>(String,a)->(String,a)->MaybeStringcompareTimes(cmd1,t1)(cmd2,t2)=Just$showcmd2++" took "++show(t1`percentage`t2)++"% of the time "++showcmd1++" took."wherepercentagexy=(100*x/y)