Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Browse files

Task events

  • Loading branch information...
commit 2a9a0364d4624ebacc51dd8636ad04fbcf333366 1 parent 0e30f0f
@scpmw authored
5 GHC/RTS/EventLogFormat.h
@@ -228,6 +228,11 @@
#define EVENT_SAMPLES 205
+#define EVENT_TASK_CREATE 210
+#define EVENT_TASK_START 211
+#define EVENT_TASK_STOP 212
+#define EVENT_TASK_DEPEND 213
* Status values for EVENT_STOP_THREAD
9 GHC/RTS/EventTypes.hs
@@ -72,6 +72,10 @@ sz_future_id = 8
sz_instrptr :: EventTypeSize
sz_instrptr = 8
+-- Sizes for tasks
+sz_taskid :: EventTypeSize
+sz_taskid = 4
- Data type delcarations to build the GHC RTS data format,
- which is a (header, data) pair.
@@ -299,6 +303,11 @@ data EventInfo
samples :: !(UArray Word16 Word64),
weights :: !(UArray Word16 Word64) }
+ | CreateTask { taskId :: Word32 }
+ | StartTask { taskId :: Word32 }
+ | StopTask { taskId :: Word32 }
+ | TaskDependency { taskId1 :: Word32, taskId2 :: Word32 }
deriving Show
--sync with ghc/includes/Constants.h
42 GHC/RTS/Events.hs
@@ -39,6 +39,7 @@ import Data.Binary
import Data.Binary.Get hiding (skip, getByteString)
import qualified Data.Binary.Get as G
import Data.Binary.Put
+import Control.Applicative
import Control.Monad
import Data.IntMap (IntMap)
import qualified Data.IntMap as M
@@ -636,6 +637,14 @@ debugParsers = [
+taskParsers =
+ [
+ (FixedSizeParser EVENT_TASK_CREATE sz_taskid (CreateTask <$> getE)),
+ (FixedSizeParser EVENT_TASK_START sz_taskid (StartTask <$> getE)),
+ (FixedSizeParser EVENT_TASK_STOP sz_taskid (StopTask <$> getE)),
+ (FixedSizeParser EVENT_TASK_DEPEND (2*sz_taskid) (TaskDependency <$> getE <*> getE))
+ ]
getData :: GetEvents Data
getData = do
db <- getE :: GetEvents Marker
@@ -681,7 +690,7 @@ getEventLog = do
event_parsers = if is_ghc_6
then standardParsers ++ ghc6Parsers
else standardParsers ++ ghc7Parsers ++
- mercuryParsers ++ debugParsers
+ mercuryParsers ++ debugParsers ++ taskParsers
parsers = mkEventTypeParsers imap event_parsers
dat <- runReaderT getData (EventParsers parsers)
return (EventLog header dat)
@@ -906,8 +915,19 @@ showEventInfo spec =
DebugPtrRange low high ->
printf "Debug pointer range 0x%08x-0x%08x" low high
Samples cap typBy typ ips weights ->
- let ppIps = zipWith (printf "%08x (x%d)") (UA.elems ips) (UA.elems weights)
- in printf "Sample %s by %s cap %d: %s" (show typ) (show typBy) cap (intercalate "," ppIps)
+ let ppIps = zipWith (pp) (UA.elems ips) (UA.elems weights)
+ pp ip 1 = printf "%08x" ip
+ pp ip n = printf "%d*%08x" n ip
+ in printf "Sample %s by %s cap %d: %s" (show typ) (show typBy) cap (intercalate ", " ppIps)
+ CreateTask task ->
+ printf "Create task %d" task
+ StartTask task ->
+ printf "Start task %d" task
+ StopTask task ->
+ printf "Stop task %d" task
+ TaskDependency task1 task2 ->
+ printf "Task dependency of %d on %d" task1 task2
where bsToStr = map (chr.fromIntegral) . BS.unpack
showThreadStopStatus :: ThreadStopStatus -> String
@@ -1084,7 +1104,11 @@ eventTypeNum e = case e of
DebugSource {} -> EVENT_DEBUG_SOURCE
DebugCore {} -> EVENT_DEBUG_CORE
+ CreateTask {} -> EVENT_TASK_CREATE
+ StartTask {} -> EVENT_TASK_START
+ StopTask {} -> EVENT_TASK_STOP
+ TaskDependency {} -> EVENT_TASK_DEPEND
putEvent :: Event -> PutEvents ()
putEvent (Event t spec) = do
putType (eventTypeNum spec)
@@ -1397,6 +1421,16 @@ putEventSpec (DebugPtrRange low high) = do
putE low
putE high
+putEventSpec (CreateTask task) = do
+ putE task
+putEventSpec (StartTask task) = do
+ putE task
+putEventSpec (StopTask task) = do
+ putE task
+putEventSpec (TaskDependency task1 task2) = do
+ putE task1
+ putE task2
-- [] == []
-- [x] == x\0
-- [x, y, z] == x\0y\0

9 comments on commit 2a9a036


OOI, do the task events have anything in common with the events defined in the other ghc-events (and TS) fork here:


And is GHC being modified to emit the task events? It already emits the other task events, AFAIK.

(Note that I don't even start to comprehend the politics, if any, of the separate ghc-events and TS forks and if my actions (or inaction) had anything to do with the work duplication, if any, I'm truly sorry.)


BTW, how about we express the forks as proper github forks? Most probably you didn't use my darcs to git bridge to start off your repo, so right now the git commits in both repos are completely unrelated. I'm ready to delete my repos and fork off your repo if you want to host all the branches, etc., since I won't contribute significantly to TS in the foreseeable future. What do you think?


No politics involved - this is pretty much just a private experiment. There's especially no connection whatsoever to the tasks tracking in GHC. Calling it like this was clearly an unfortunate choice.

Concerning forking structure: I should probably have put more effort into starting off with existing Git history, sorry for the duplication. Note that my history for both ghc-events and ThreadScope contains a number of debug/profiling changes (see 85dbf28) for which there is no official GHC support. I will start working on that soon - which will probably mean rebasing all changes anyway, so I can easily move to whatever is considered the "main line" at that point.

The only changes that could become part of the main line right now would be 3bdd321 and 92ca333, which pretty much just make ghc-events a bit more robust against errors in the event log data or the handlers.


Thank you for filling me in. The two commits do look useful.

To be honest, the darcs-git bridge is unofficial, but I guess the official maintainer can be easily persuaded to make one of our repos the official repo in place of the current darcs repo. Especially if we sync our repos at some point and some of your changes are merged to master. I can update the TS web pages and/or Hackage info to match the new repo location, etc.

Have fun with your experiments and please merge your stuff before you move to some other project and forget about it all. :)


Re making ghc-events a bit more robust against errors in the event log data, there are two opposing forces there. On one hand, it's really nice to have an error message closer to the actual cause of failure. OTOH, people want to be able to work with broken eventlogs (e.g., due to logs from interrupted executions or due to changes in how GHC generates the events). The latter force is evident, e.g., here:

We probably can't have the best of both worlds, but it's worth thinking about, IMHO.


Fair point - though both really shouldn't have to be mutually exclusive. One approach would be to make the errors non-fatal, possibly add recovery code, and put "ErrorEvent" nodes into the stream. Then ThreadScope/ghc-events could pop up a generic "stream might be inconsistent" warning, and everybody should be reasonably happy.

On the topic of incomplete files, just as food for thought: I tried last year to allow ghc-events to process incomplete input by porting it over to attoparsec and use proper "try" fallbacks. That has the nice property that it could also allow us progressive reading at some point down the line. On the other hand, I couldn't get it to work for some reason - so I also have no idea whether performance would be acceptable. If there's interest I could probably dig the code out.


I've made a note in the trac issue. If that's not too much archeological effort, sharing the code can't hurt. :)


Okay, I have dug it out and fixed some bugs, 0f226db seems to somewhat work now. Note though that it is based on a version of ghc-events that is really ancient and has a few spurious extra changes - such as an attempt to get rid of the magic numbers a bit...


Oh, great, now it's saved for posterity (or for any interesting parties, if they can find it). :)

Please sign in to comment.
Something went wrong with that request. Please try again.