4

I need to profile a large number of haskell executables, hopefully in parallel. I was able to get the clock time with measure and measTime from the Criterion library, but couldn't get measCpuTime or any GC report to work (measCpuTime returns a time that's impossibly short). The code looks like:

buildProj :: FilePath -> IO ExitCode
buildProj projDir = system $ "cd " ++ projDir ++ "; cabal sandbox init; cabal configure; cabal build"

-- Time a project
instance NFData ExitCode
  where 
    rnf ExitSuccess = ()
    rnf (ExitFailure _) = ()


benchmark :: FilePath -> Int64 -> IO Double
benchmark projDir runs =  do  
  let runProj = "./" ++ projDir ++ "/dist/build/" ++ projDir ++ "/" ++ projDir ++ "> /dev/null"
  exit <- timeout 17000000 $ system runProj -- TODO hardcode timeout
  case exit of
       Just ExitSuccess     -> do {(m, _) <- measure (nfIO $ system runProj) runs; 
                              return $! measTime m}
       Just (ExitFailure _) -> return 100 
       Nothing              -> return 100 

In short, I'm running the executables with System.Process.system as an IO action and I've declared ExitCode as NFData in order to get nfIO to work. What have I done wrong? Are there better tools to do the task?

The file's here if you want to play with it.

rem
  • 893
  • 4
  • 18
  • Well your child process's CPU time is not your CPU time, so no surprise that `measCpuTime` doesn't do what you want. Not sure how to measure the child process's CPU time, though it is obviously possible since `time` does it. – Reid Barton Oct 12 '15 at 20:11
  • I'm thinking to use the GHC API to do the profile, but not sure where to start looking – rem Oct 13 '15 at 20:57

1 Answers1

0

I took a look at this SO question and got some ideas. First note that criterion uses cbits to enable system-dependent cpu time functions. Let's pretend you're on unix. The simplest thing to do is to directly read from /proc/PID/stat/cutime at the start and end of your runs and take the difference. Beyond that, you can actually use the c code provided in that question, link it in yourself as a foreign import, and then call that directly from your own code.

Community
  • 1
  • 1
sclv
  • 38,665
  • 7
  • 99
  • 204