-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathghc-events-perf.hs
102 lines (89 loc) · 3.62 KB
/
ghc-events-perf.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
-----------------------------------------------------------------------------
-- |
-- Copyright : (c) 2012 Duncan Coutts, Bernie Pope, Mikolaj Konarski
-- License : BSD-style
-- Maintainer : florbitous@gmail.com
-- Stability : experimental
-- Portability : ghc
--
-- A tool to help profiling a Haskell program using Linux 'perf',
-- ghc-events and, eventually, Threadscope.
--
-- The ghc-events-perf tool has a couple of commands
-- for obtaining 'perf' performance data for a Haskell program,
-- translating it to the ghc-events format, synchronizing and merging
-- with the standard ghc-events eventlog for the Haskell program,
-- and so making the data ready for display in Threadscope.
--
-- Usage:
--
-- > ghc-events-perf command command-args
--
-- Getting help:
--
-- > ghc-events-perf help
-- > ghc-events-perf help command
-----------------------------------------------------------------------------
module Main where
import System.Posix.Process
import System.Environment
import System.Exit
import System.FilePath
import System.Process
import System.IO (hPutStrLn, stderr)
import Control.Monad
main :: IO ()
main = getArgs >>= command
command :: [String] -> IO ()
command [helpString] | helpString `elem` ["-h", "--help", "help"] =
putStrLn usage
command ["help", "help"] =
putStrLn "Helps."
command ["help", "record"] = do
let args = ["+GhcEventsPerf", "-h"]
executeFile "ghc-events-perf-record" True args Nothing
command ["help", "convert"] =
putStr $ unlines $
[ "Usage: ghc-events-perf convert program-name [out-file perf-file eventlog-file]"
, " program-name the name of the profiled Haskell program"
, " out-file where to save the resulting compound eventlog"
, " perf-file path to the perf data file for the Haskell program"
, " eventlog-file path to the GHC RTS eventlog of the Haskell program"
]
command ("record" : args) = do
myPath <- getExecutablePath
let commonPath = fst $ splitFileName myPath
-- We assume ghc-events-perf-record is in the same directory
-- as ghc-events-perf. Needed for 'sudo', because root needn't
-- have user's ~/.cabal/bin in his PATH.
recordPath = combine commonPath "ghc-events-perf-record"
recordArgs = "--RTS" : args
executeFile recordPath True recordArgs Nothing
command ["convert", program_name, out_file, perf_file, eventlog_file] = do
let sync_eventlog_file = program_name ++ ".perf.eventlog"
syncArgs = [ program_name
, perf_file
, sync_eventlog_file
]
putStrLn "Translating and synchronizing..."
syncHandle <- runProcess "ghc-events-perf-sync" syncArgs
Nothing Nothing Nothing Nothing Nothing
void $ waitForProcess syncHandle
let mergeArgs = [ "merge"
, out_file
, eventlog_file
, sync_eventlog_file
]
putStrLn "Merging with the standard eventlog..."
executeFile "ghc-events" True mergeArgs Nothing
command ["convert", program_name] = do
let out_file = program_name ++ ".total.eventlog"
perf_file = "data.perf" -- the same as defaultPerfOutputFile in record
eventlog_file = program_name ++ ".eventlog"
command ["convert", program_name, out_file, perf_file, eventlog_file]
command _ = putStrLn usage >> Main.die "Unrecognized command"
usage :: String
usage = "Usage: ghc-events-perf command command-args\n\nThe available commands are: record convert help.\n\nSee 'ghc-events-perf help command' for more information on a specific command."
-- Exit the program with an error message.
die :: String -> IO a
die s = hPutStrLn stderr s >> exitWith (ExitFailure 1)