module Timeline.HEC ( renderHEC ) where import Timeline.Render.Constants import EventTree import EventDuration import State import CairoDrawing import ViewerColours import Graphics.Rendering.Cairo import qualified Graphics.Rendering.Cairo as C import Graphics.UI.Gtk import qualified GHC.RTS.Events as GHC import GHC.RTS.Events hiding (Event, GCWork, GCIdle) import Control.Monad renderHEC :: Int -> ViewParameters -> Timestamp -> Timestamp -> (DurationTree,EventTree) -> Render () renderHEC cap params@ViewParameters{..} start end (dtree,etree) = do renderDurations cap params start end dtree when (scaleValue < detailThreshold) $ case etree of EventTree ltime etime tree -> renderEvents cap params ltime etime start end tree detailThreshold :: Double detailThreshold = 3000 ------------------------------------------------------------------------------- -- hecView draws the trace for a single HEC renderDurations :: Int -> ViewParameters -> Timestamp -> Timestamp -> DurationTree -> Render () renderDurations _ _ _ _ DurationTreeEmpty = return () renderDurations c params@ViewParameters{..} startPos endPos (DurationTreeLeaf e) | inView startPos endPos e = drawDuration c params e | otherwise = return () renderDurations !c params@ViewParameters{..} !startPos !endPos (DurationSplit s splitTime e lhs rhs runAv gcAv) | startPos < splitTime && endPos >= splitTime && (fromIntegral (e - s) / scaleValue) <= fromIntegral detail = -- View spans both left and right sub-tree. -- trace (printf "hecView (average): start:%d end:%d s:%d e:%d" startPos endPos s e) $ drawAverageDuration c params s e runAv gcAv | otherwise = -- trace (printf "hecView: start:%d end:%d s:%d e:%d" startPos endPos s e) $ do when (startPos < splitTime) $ renderDurations c params startPos endPos lhs when (endPos >= splitTime) $ renderDurations c params startPos endPos rhs ------------------------------------------------------------------------------- renderEvents :: Int -> ViewParameters -> Timestamp -- start time of this tree node -> Timestamp -- end time of this tree node -> Timestamp -> Timestamp -> EventNode -> Render () renderEvents !c params@ViewParameters{..} !s !e !startPos !endPos (EventTreeLeaf es) = sequence_ [ drawEvent c params e | e <- es, let t = time e, t >= startPos && t < endPos ] renderEvents !c params@ViewParameters{..} !s !e !startPos !endPos (EventTreeOne ev) | t >= startPos && t < endPos = drawEvent c params ev | otherwise = return () where t = time ev renderEvents !c params@ViewParameters{..} !s !e !startPos !endPos (EventSplit splitTime lhs rhs) | startPos < splitTime && endPos >= splitTime && (fromIntegral (e - s) / scaleValue) <= fromIntegral detail = drawTooManyEvents c params s e | otherwise = do when (startPos < splitTime) $ renderEvents c params s splitTime startPos endPos lhs when (endPos >= splitTime) $ renderEvents c params splitTime e startPos endPos rhs ------------------------------------------------------------------------------- -- An event is in view if it is not outside the view. inView :: Timestamp -> Timestamp -> EventDuration -> Bool inView viewStart viewEnd event = not (eStart > viewEnd || eEnd <= viewStart) where eStart = startTimeOf event eEnd = endTimeOf event ------------------------------------------------------------------------------- drawAverageDuration :: Int -> ViewParameters -> Timestamp -> Timestamp -> Timestamp -> Timestamp -> Render () drawAverageDuration c ViewParameters{..} startTime endTime runAv gcAv = do setSourceRGBAhex (if not bwMode then runningColour else black) 1.0 when (runAv > 0) $ draw_rectangle startTime hecBarOff -- x, y (endTime - startTime) -- w hecBarHeight setSourceRGBAhex black 1.0 --move_to (oxs + startTime, 0) --relMoveTo (4/scaleValue) 13 --unscaledText scaleValue (show nrEvents) setSourceRGBAhex (if not bwMode then gcColour else black) gcRatio draw_rectangle startTime -- x (hecBarOff+hecBarHeight) -- y (endTime - startTime) -- w (hecBarHeight `div` 2) -- h where duration = endTime - startTime -- runRatio :: Double -- runRatio = (fromIntegral runAv) / (fromIntegral duration) gcRatio :: Double gcRatio = (fromIntegral gcAv) / (fromIntegral duration) ------------------------------------------------------------------------------- unscaledText :: String -> Render () unscaledText text = do m <- getMatrix identityMatrix textPath text C.fill setMatrix m ------------------------------------------------------------------------------- textWidth :: Double -> String -> Render TextExtents textWidth _scaleValue text = do m <- getMatrix identityMatrix tExtent <- textExtents text setMatrix m return tExtent ------------------------------------------------------------------------------- drawDuration :: Int -> ViewParameters -> EventDuration -> Render () drawDuration c ViewParameters{..} (ThreadRun t s startTime endTime) = do setSourceRGBAhex (if not bwMode then runningColour else black) 1.0 setLineWidth (1/scaleValue) draw_rectangle_opt False startTime -- x hecBarOff -- y (endTime - startTime) -- w hecBarHeight -- h -- Optionally label the bar with the threadID if there is room tExtent <- textWidth scaleValue tStr let tw = textExtentsWidth tExtent th = textExtentsHeight tExtent when (tw + 6 < fromIntegral rectWidth) $ do setSourceRGBAhex labelTextColour 1.0 move_to (fromIntegral startTime + truncate (4*scaleValue), hecBarOff + (hecBarHeight + round th) `quot` 2) unscaledText tStr -- Optionally write the reason for the thread being stopped -- depending on the zoom value labelAt labelsMode endTime $ show t ++ " " ++ showThreadStopStatus s where rectWidth = truncate (fromIntegral (endTime - startTime) / scaleValue) -- as pixels tStr = show t drawDuration c ViewParameters{..} (GCStart startTime endTime) = gcBar (if bwMode then black else gcStartColour) startTime endTime drawDuration c ViewParameters{..} (GCWork startTime endTime) = gcBar (if bwMode then black else gcWorkColour) startTime endTime drawDuration c ViewParameters{..} (GCIdle startTime endTime) = gcBar (if bwMode then black else gcIdleColour) startTime endTime drawDuration c ViewParameters{..} (GCEnd startTime endTime) = gcBar (if bwMode then black else gcEndColour) startTime endTime gcBar :: Color -> Timestamp -> Timestamp -> Render () gcBar col !startTime !endTime = do setSourceRGBAhex col 1.0 draw_rectangle_opt False startTime -- x (hecBarOff+hecBarHeight) -- y (endTime - startTime) -- w (hecBarHeight `div` 2) -- h labelAt :: Bool -> Timestamp -> String -> Render () labelAt labelsMode t str | not labelsMode = return () | otherwise = do setSourceRGB 0.0 0.0 0.0 move_to (t, hecBarOff+hecBarHeight+12) save identityMatrix rotate (pi/4) textPath str C.fill restore drawEvent :: Int -> ViewParameters -> GHC.Event -> Render () drawEvent c params@ViewParameters{..} event = case spec event of CreateThread{} -> renderInstantEvent params event createThreadColour RunSpark{} -> renderInstantEvent params event runSparkColour StealSpark{} -> renderInstantEvent params event stealSparkColour ThreadRunnable{} -> renderInstantEvent params event threadRunnableColour RequestSeqGC{} -> renderInstantEvent params event seqGCReqColour RequestParGC{} -> renderInstantEvent params event parGCReqColour MigrateThread{} -> renderInstantEvent params event migrateThreadColour WakeupThread{} -> renderInstantEvent params event threadRunnableColour Shutdown{} -> renderInstantEvent params event shutdownColour RunThread{} -> return () StopThread{} -> return () StartGC{} -> return () _ -> return () renderInstantEvent :: ViewParameters -> GHC.Event -> Color -> Render () renderInstantEvent ViewParameters{..} event color = do setSourceRGBAhex color 1.0 setLineWidth (3 * scaleValue) let t = time event draw_line (t, hecBarOff-4) (t, hecBarOff+hecBarHeight+4) labelAt labelsMode t $ showEventTypeSpecificInfo (spec event) drawTooManyEvents :: Int -> ViewParameters -> Timestamp -> Timestamp -> Render () drawTooManyEvents c params@ViewParameters{..} start end = do return () -- setSourceRGBAhex grey 1.0 -- setLineWidth (3 * scaleValue) -- draw_rectangle start (hecBarOff-4) (end - start) 4 -- draw_rectangle start (hecBarOff+hecBarHeight) (end - start) 4 -------------------------------------------------------------------------------