packages feed

hpc-strobe (empty) → 0.1

raw patch · 8 files changed

+750/−0 lines, 8 filesdep +basedep +filepathdep +hpcsetup-changed

Dependencies added: base, filepath, hpc

Files

+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2009, Thorkil Naur+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors may+   be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,257 @@+=======================================================================+README: hpc-strobe: Hpc-generated strobes for a running Haskell program+=======================================================================++hpc-strobe is a rudimentary library that demonstrates the possibility of+using Hpc (Haskell Program Coverage) to inspect the state of a running+Haskell program. Please refer to++  Andy Gill and Colin Runciman: "Haskell Program Coverage", in+  Haskell Workshop, ACM Press, 2007++for a description of Hpc. At the time of writing this (2009-May-08),+the paper is available at++  http://www.ittc.ku.edu/~andygill/papers/Hpc07.pdf++In ordinary use of Hpc, a single so-called tix file is produced at the+end of a run. The tix file records how many times each expression has+been used during the run. This can be used to mark up the source code,+identifying expressions that have not been used.++hpc-strobe uses the basic machinery provided by Hpc to produce multiple+tix files, also called strobes, representing the coverage at different+times while the program is running. By subtracting such two tix files,+again using Hpc machinery, a tix file representing the expressions used+between the times of recording the subtracted tix files is produced.+This may be used, for example, to get a better idea of what a+long-running program is doing. It could also be used as a profiling+tool, getting information about how many times individual expressions+are used.++A program is included whose strobe differences produce a crude rendering+of an analog clock when they are used to mark up the source code using+Hpc.++Use of the library involves a simple change of the main function and+also requires the program to be enabled for hpc. At the time of writing,+this means using a fairly recent version of GHC and compiling the+Haskell code with the -fhpc option.++In the rest of this README, please find (1) download information; (2)+build and install information; (3) information on how to run the+demonstration program and render the analog clock; (4) a bit of+background information; and (5) some final remarks. Information on how+to use the library can be found in the haddock documentation which is+based on comments in src/Trace/Hpc/Strobe.hs in the package.++1. Downloading hpc-strobe+-------------------------++hpc-strobe is on hackage, so for example:++  $ wget http://hackage.haskell.org/packages/archive/hpc-strobe/0.1/hpc-strobe-0.1.tar.gz++2. Building and installing hpc-strobe+-------------------------------------++First unpack the package:++  $ tar xvz hpc-strobe-0.1.tar.gz++Then build and install the Cabal way:++  $ cd hpc-strobe-0.1+  $ runhaskell Setup.hs configure # Additional options may be used+  $ runhaskell Setup.hs build+  $ runhaskell Setup.hs haddock # Optional+  $ runhaskell Setup.hs install # Privileges (sudo) may be needed++For example:++  $ tar xvfz ../../test/hpc/hpc-strobeDarcsRepository/hpc-strobe/dist/hpc-strobe-0.1.tar.gz +  hpc-strobe-0.1/+  hpc-strobe-0.1/demonstration/+  hpc-strobe-0.1/demonstration/showClock1.sh+  hpc-strobe-0.1/demonstration/StrobeClock.hs+  hpc-strobe-0.1/demonstration/strobeHpcDiff1.sh+  hpc-strobe-0.1/hpc-strobe.cabal+  hpc-strobe-0.1/LICENSE+  hpc-strobe-0.1/README+  hpc-strobe-0.1/Setup.hs+  hpc-strobe-0.1/src/+  hpc-strobe-0.1/src/Trace/+  hpc-strobe-0.1/src/Trace/Hpc/+  hpc-strobe-0.1/src/Trace/Hpc/Strobe.hs+  $ cd hpc-strobe-0.1/+  $ runhaskell Setup.hs configure --user --prefix=/Users/thorkilnaur/tn/install/hpc-strobe-0.1+  Configuring hpc-strobe-0.1...+  $ runhaskell Setup.hs build+  Preprocessing library hpc-strobe-0.1...+  Building hpc-strobe-0.1...+  [1 of 1] Compiling Trace.Hpc.Strobe ( src/Trace/Hpc/Strobe.hs, dist/build/Trace/Hpc/Strobe.o )+  ar: creating archive dist/build/libHShpc-strobe-0.1.a+  $ runhaskell Setup.hs haddock+  Preprocessing library hpc-strobe-0.1...+  Running Haddock for hpc-strobe-0.1...+  Documentation created: dist/doc/html/hpc-strobe/index.html+  $ runhaskell Setup.hs install+  Installing: /Users/thorkilnaur/tn/install/hpc-strobe-0.1/lib/hpc-strobe-0.1/ghc-6.8.2+  Registering hpc-strobe-0.1...+  Reading package info from "dist/installed-pkg-config" ... done.+  Saving old package config file... done.+  Writing new package config file... done.+  $ ++3. Running the demonstration program+------------------------------------++I show how to run he demonstration program in-place in the unpacked+package directory:++  $ cd demonstration+  $ ghc --version+  The Glorious Glasgow Haskell Compilation System, version 6.8.2+  $ ghc --make StrobeClock.hs -fhpc+  [1 of 1] Compiling Main             ( StrobeClock.hs, StrobeClock.o )+  Linking StrobeClock ...+  $ mkdir tixfiles+  $ ./StrobeClock tixfiles +  StrobeClock(2009-May-08 10.41): Canvas pixel height 39, pixel width 39+  StrobeClock(2009-May-08 10.41): 634+  StrobeClock(2009-May-08 10.41): 1266+  ...++StrobeClock never stops, so at this point, enter a separate shell and++  $ cd hpc-strobe-0.1/demonstration +  $ ls -tr tixfiles | tail -n 3+  StrobeClock_254.tix+  StrobeClock_255.tix+  StrobeClock_256.tix+  $ ++to watch the growing list of strobes.++Note: StrobeClock will not complain if you forget to create the tixfiles+directory: In that case, no tixfiles will be written. Whether this+should be considered an error or a feature, I haven't decided.++To produce a single strobe difference, a shell script strobeHpcDiff1.sh+is provided. For example:++  $ sh strobeHpcDiff1.sh . tixfiles StrobeClock 0 5+  Writing: Main.hs.html+  Writing: hpc_index.html+  Writing: hpc_index_fun.html+  Writing: hpc_index_alt.html+  Writing: hpc_index_exp.html+  strobeHpc_StrobeClock_5_SUB_0_20090508_140251/+  strobeHpc_StrobeClock_5_SUB_0_20090508_140251/Main.hs.html+  $ ++This deposits marked-up source code in a time-stamped directory. It+also produces a .tar.gz file for that directory. Please look at the+strobeHpcDiff1.sh code itself for usage information.++Now point your browser to the Main.hs.html file in the time-stamped+directory. On my Mac OS X, I can do++  $ /Applications/Firefox.app/Contents/MacOS/firefox strobeHpc_StrobeClock_5_SUB_0_20090508_140251/Main.hs.html &+  [1] 23707+  $ ++but something different may be needed. Now scroll down a few lines in+this marked-up version of the StrobeClock.hs code to display the canvas+function. You should be able to make out a crude rendering of an analog+clock, showing the local time of day. And since we have taken the+difference over 5 strobes, with 1 second between each, the seconds hand+on the clock is smeared, covering those 5 seconds.++For a more dynamic experience, with StrobeClock still running:++  $ sh showClock1.sh +  showClock1.sh: Skip over tixfiles/StrobeClock_0.tix to tixfiles/StrobeClock_1.tix+  showClock1.sh: Skip over tixfiles/StrobeClock_1.tix to tixfiles/StrobeClock_2.tix+  ...+  showClock1.sh: Skip over tixfiles/StrobeClock_30.tix to tixfiles/StrobeClock_31.tix+  showClock1.sh: Mark up tixfiles/StrobeClock_31.tix to tixfiles/StrobeClock_32.tix+  Writing: Main.hs.html+  Writing: hpc_index.html+  Writing: hpc_index_fun.html+  Writing: hpc_index_alt.html+  Writing: hpc_index_exp.html+  ...++This creates a directory, ClockDisplay, and maintains in this directory+a marked-up Main.hs.html that corresponds to the difference between the+third- and second-latest strobes in the tixfiles directory.+(showClock1.sh assumes that the tixfiles directory is named "tixfiles"+and also that the tixfile filename prefix is "StrobeClock".)++Then point your browser to this file, for example (again after entering+a new shell: showClock1.sh runs forever; also, I need to close the+other firefox before starting a new one):++  $ cd hpc-strobe-0.1/demonstration +  $ /Applications/Firefox.app/Contents/MacOS/firefox ClockDisplay/Main.hs.html &+  [1] 24813+  $ ++This will show the most recently marked-up strobe difference, hence the+current local time will be rendered in the canvas function. Smearing+may occur, but refreshing the display usually helps.++In addition to PPC Mac OS X 10.4 with GHC 6.8.2, the demonstration has+been tried successfully on Windows with GHC 6.8.2 with both MSYS and+Cygwin; and on Ubuntu x86 Linux with GHC 6.10.2.++4. Background+-------------++The path to using the reflect interface in Hpc started with my desire to+investigate a long-winding darcs pull (some GHC HEAD into GHC STABLE).+See http://bugs.darcs.net/issue1075.  Earlier, to investigate the+HughesPJ pretty-printing library, I had written a simple tracer that did+a source-to-source transformation of Haskell code, inserting calls to+Debug.Trace.trace for all top-level definitions in a Haskell module. See+http://hackage.haskell.org/trac/ghc/ticket/1337. This was at a point in+time where Hpc was not working. So my initial idea was to do something+similar to darcs, transforming selected darcs modules to figure out what+they were doing.++The work started around 2008-Sep-02. After struggling for a while, I+had settled on a modified version of the Hpc.c that comes with the GHC+runtime system that wrote out tix files regularly. Immediately+afterwards, however, I stumbled over the Trace.Hpc.Reflect and+Trace.Hpc.Tix modules that supported exactly what I needed. Thanks to+the foresight of Andy Gill and Colin Runciman, everything turned out to+be surprisingly simple. In fact, a major motivation for publishing the+present library is simply to make this technique better known. The+hpc-strobe library itself is really not adding anything significant to+Hpc itself.++At the Hac5/darcs sprint 2, I gave a brief presentation of the+technique:++  http://blog.darcs.net/2009/04/darcs-hacking-sprint-2-report.html++Thanks to Don Steward for helping here.++5. Final words+--------------++As mentioned, the contents of the hpc-strobe library itself is really+not particularly significant and it is easy to imagine a number of+generalizations and variations of the technique that opens up what I+believe is a fairly rich field of valuable applications.++I should mention the hpc-tracer library by Andy Gill and Colin Runciman:++  http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hpc-tracer++I must admit that I have not studied this library in detail, but it+clearly seems to be headed in much the same direction as hpc-strobe,+but with a more elaborate user interface.++Thorkil Naur
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ demonstration/StrobeClock.hs view
@@ -0,0 +1,203 @@+-- StrobeClock.hs: Demonstrate hpc-strobe by rendering a crude analog+-- clock in the marked-up code+-- Copyright (c) 2009, Thorkil Naur+--+-- Usage: ./StrobeClock tixfile-directory+--+-- Note: The indicated tixfile-directory must exist.+--++module Main where++  import System+  import IO+  import Time+  import Control.Concurrent+  import List++  import Trace.Hpc.Strobe++  progName = "StrobeClock"+  progStamp = "2009-May-08 17.26"++  -- The clock will be rendered in the following part of the code. The+  -- number of lines and their width may be adjusted; the width of the+  -- shortest line will determine the width of the clock.++  canvas x+    = [+          [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+        , [x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]+      ]++  -- Canvas dimensions:++  pixelHeight = (length $ canvas 0) - 1+  pixelWidth = minimum $ map ((subtract 1) . length) $ canvas 0++  -- Defines the shape of pixels: To calibrate, measure the height and+  -- width of a square part of the canvas as rendered and enter the+  -- ratio here:++  pixelHeightDividedByWidth = 16.2/17.4++  -- World coordinate system is such that a 2x2 square with (0,0) in its+  -- center fits exactly inside the canvas rectangle:++  worldDimensions+    = let+        rawDimensions = [1.0,pixelHeightDividedByWidth]+      in+        map ((*2.0) . (/(minimum rawDimensions))) rawDimensions++  worldLowerLeftCorner = map (negate . (/2.0)) worldDimensions++  -- Converting between coordinate systems:++  canvasToWorld [row,col]+    = zipWith (+) worldLowerLeftCorner $ zipWith (*) worldDimensions+        [fromIntegral col / fromIntegral pixelWidth,+          1.0 - fromIntegral row / fromIntegral pixelHeight]++  worldToCanvas wcs+    = let+        [c0,r0]+          = zipWith (/) (zipWith (-) wcs worldLowerLeftCorner)+              worldDimensions+      in+        [round $ (1.0 - r0) * fromIntegral pixelHeight,+          round $ c0 * fromIntegral pixelWidth]++  -- Shade outside unit circle:++  circleShade+    = filter ((>1.0) . sum . map (^2) . canvasToWorld)+        [ [row,col] | row <- [0..pixelHeight], col <- [0..pixelWidth] ]++  -- Line:++  canvasLine [r1,c1] [r2,c2]+    = if abs (r2 - r1) > abs (c2 - c1) then+        map reverse $ canvasLine [c1,r1] [c2,r2]+      else+        if abs (c2 - c1) > 0 then+          let+            [(c1',r1'),(c2',r2')] = sort [(c1,r1),(c2,r2)]+          in+            [ [r,c] | c <- [c1'..c2'],+              let r = r1' + (round $ fromIntegral (r2' - r1')+                              * fromIntegral (c - c1')+                              / fromIntegral (c2' - c1')) ]+        else+          [[r1,c1]]++  worldLine [x1,y1] [x2,y2]+    = canvasLine (worldToCanvas [x1,y1]) (worldToCanvas [x2,y2])++  -- Piece of radial line, angle measured in degrees from vertical,+  -- clockwise:++  worldRadial angle from to+    = let+        radians = (90.0 - angle) / 180.0 * pi+        [p1,p2]+          = map (\t -> map (*t) [cos radians,sin radians]) [from,to]+      in+        worldLine p1 p2++  -- Clock:++  worldClockFixed+    = concat [ worldRadial (fromIntegral a) 0.9 1.0+               | a <- [30,60..360] ]+      ++ concat [ worldRadial (fromIntegral a) 0.8 1.0+                  | a <- [90,180..360] ]+      ++ circleShade++  worldClockVariable h m s+    = concat [ worldRadial ah 0.0 0.55 ]+      ++ concat [ worldRadial (ah+4.0) 0.0 0.45 ]+      ++ concat [ worldRadial (ah-4.0) 0.0 0.45 ]+      ++ concat [ worldRadial am 0.0 0.9 ]+      ++ concat [ worldRadial (am-2.5) 0.0 0.8 ]+      ++ concat [ worldRadial (am+2.5) 0.0 0.8 ]+      ++ concat [ worldRadial as (-0.15) 1.0 ]+      where+      as = fromIntegral s * (360.0/60.0)+      m' = fromIntegral m + fromIntegral s / 60.0+      am = m'*(360/60.0)+      ah = (fromIntegral h + m'/60.0)*(360.0/12.0)++  main'+    = do+        putStrLn $+          progName ++ "(" ++ progStamp ++ "): Canvas pixel height "+            ++ show pixelHeight ++ ", pixel width " ++ show pixelWidth+        mapM_+          (\n ->+            do+              clTime <- getClockTime+              localTime@(CalendarTime{ctHour = hr,+                ctMin = mn, ctSec = sc}) <- toCalendarTime clTime+              let+                timeStamp = calendarTimeToString localTime+                in+                  do+                    putStrLn $ progName ++ "(" ++ progStamp ++ "): "+                      ++ (show $+                            sum [ ((canvas n)!!i)!!j+                                  | [i,j] <- worldClockFixed+                                     ++ worldClockVariable hr mn sc ])+              threadDelay 950000+          ) [1..]++  mainArgsInterpret [tixfileDirectory]+    = withStrobesWrittenRegularly tixfileDirectory progName 1000000+        main'++  mainArgsInterpret args+    = error $ "Usage: \"./" ++ progName ++ " tixfile-directory\""++  main+    = do+        hSetBuffering stdout NoBuffering+        args <- getArgs+        mainArgsInterpret args
+ demonstration/showClock1.sh view
@@ -0,0 +1,39 @@+#!/bin/sh+# showClock1.sh: Show latest difference between clock tix+#   sh showClock1.sh+# 2009-Apr-27 21.00 / TN++PREFIX=tixfiles/StrobeClock_++CURRENT=0++mkdir -p ClockDisplay++while true; do++  NEXT=`expr $CURRENT + 1`+  AFTER=`expr $NEXT + 1`++  while [ ! -f ${PREFIX}${AFTER}.tix ]; do echo $0: Waiting for ${PREFIX}${AFTER}.tix; sleep 1; done++  TWOAFTER=`expr $AFTER + 1`++  if [ -f ${PREFIX}${TWOAFTER}.tix ]; then++    echo $0: Skip over ${PREFIX}${CURRENT}.tix to ${PREFIX}${NEXT}.tix++  else++    echo $0: Mark up ${PREFIX}${CURRENT}.tix to ${PREFIX}${NEXT}.tix++    hpc combine --function=SUB --output=showClock1.tix ${PREFIX}${NEXT}.tix ${PREFIX}${CURRENT}.tix++    hpc markup --highlight-covered showClock1.tix++    mv Main.hs.html ClockDisplay/++  fi++  CURRENT=$NEXT++done
+ demonstration/strobeHpcDiff1.sh view
@@ -0,0 +1,100 @@+#!/bin/sh+# strobeHpcDiff1.sh: Difference between tix strobe files 1+#   sh strobeHpcDiff1.sh source-directory strobe-tix-directory strobe-tix-file-suffix strobe-from strobe-to+# 2008-Sep-14 11.57 / TN+# 2009-May-08 17.43 / TN: Replace "==" by "=" in tests++COUNT=0+for F in *.html; do+  if [ -e "$F" ]; then+    COUNT=`expr $COUNT + 1`+    echo 1>&2 $0: Found .html file \"$F\"+  fi+done++if [ "$COUNT" != 0 ]; then+  echo 1>&2 $0: Please clean out .html files+  exit 1+fi++if [ "$#" = "0" ]; then+  echo 1>&2 $0: Please specify source-directory parameter+  exit 1+fi+SOURCE_DIRECTORY="$1"+shift++if [ "$#" = "0" ]; then+  echo 1>&2 $0: Please specify strobe-tix-directory parameter+  exit 1+fi+STROBE_TIX_DIRECTORY="$1"+shift++if [ "$#" = "0" ]; then+  echo 1>&2 $0: Please specify strobe-tix-file-suffix parameter+  exit 1+fi+STROBE_TIX_FILE_SUFFIX="$1"+shift++if [ "$#" = "0" ]; then+  echo 1>&2 $0: Please specify strobe-from parameter+  exit 1+fi+STROBE_FROM="$1"+shift++if [ "$#" = "0" ]; then+  echo 1>&2 $0: Please specify strobe-to parameter+  exit 1+fi+STROBE_TO="$1"+shift++if [ "$#" != 0 ]; then+  echo 1>&2 $0: There are $# superfluous parameters: "$@"+  exit 1+fi++STROBE_TIX_SUFFIX=${STROBE_TIX_DIRECTORY}/${STROBE_TIX_FILE_SUFFIX}_+STROBE_TIX_OUTPUT=${STROBE_TIX_FILE_SUFFIX}_${STROBE_TO}_SUB_${STROBE_FROM}+STROBE_TIX_OUTPUT_FILE=${STROBE_TIX_OUTPUT}.tix++hpc combine --function=SUB --output=${STROBE_TIX_OUTPUT_FILE} ${STROBE_TIX_SUFFIX}${STROBE_TO}.tix ${STROBE_TIX_SUFFIX}${STROBE_FROM}.tix+RC="$?"+if [ "$RC" != 0 ]; then+  echo 1>&2 $0: hpc combine: Unexpected return code $RC+  exit 1+fi++hpc markup --highlight-covered --srcdir=${SOURCE_DIRECTORY} ${STROBE_TIX_OUTPUT_FILE}+RC="$?"+if [ "$RC" != 0 ]; then+  echo 1>&2 $0: hpc combine: Unexpected return code $RC+  exit 1+fi++WORKING_DIR=strobeHpc_${STROBE_TIX_OUTPUT}_`date +%Y%m%d_%H%M%S`++mkdir ${WORKING_DIR}+RC="$?"+if [ "$RC" != 0 ]; then+  echo 1>&2 $0: mkdir ${WORKING_DIR}: Unexpected return code $RC+  exit 1+fi++mv `grep -l '"istickedoff"' *.html` ${WORKING_DIR}+RC="$?"+if [ "$RC" != 0 ]; then+  echo 1>&2 $0: mv `grep -l '"istickedoff"' ${WORKING_DIR}/*.html` .: Unexpected return code $RC+  exit 1+fi++tar cvzf ${WORKING_DIR}.tar.gz ${WORKING_DIR}++rm *.html++# Exit OK:++exit 0
+ hpc-strobe.cabal view
@@ -0,0 +1,41 @@+Name:               hpc-strobe+Version:            0.1+Synopsis:           Hpc-generated strobes for a running Haskell program+License:            BSD3+License-file:       LICENSE+Author:             Thorkil Naur+Maintainer:         naur@post11.tele.dk+Build-Type:         Simple+Cabal-Version:      >=1.2+Description:        A rudimentary library that demonstrates the+                    possibility of using Hpc (Haskell Program Coverage)+                    to inspect the state of a running Haskell program.+                    Use of the library involves a simple change of the+                    main function and also requires the program to be+                    enabled for hpc. At the time of writing, this means+                    using a fairly recent version of GHC and compiling+                    the Haskell code with the @-fhpc@ option.+Category:           Trace, Debug+extra-source-files: README+                    demonstration/StrobeClock.hs+                    demonstration/strobeHpcDiff1.sh+                    demonstration/showClock1.sh++Library+  Build-Depends:    base, hpc, filepath+  Exposed-modules:  Trace.Hpc.Strobe+  hs-source-dirs:   src+  ghc-options:      -Wall++--+-- Note: Checking the package on+-- http://hackage.haskell.org/packages/upload.html reports:+--+--   Exposed modules use unallocated top-level names: Trace+--+-- I feel somewhat justified in keeping this name, since the hpc+-- package itself uses Trace.Hpc.Tix and Trace.Hpc.Reflect. But I am+-- certainly open to suggested alternative names.+--+-- Regards Thorkil+--
+ src/Trace/Hpc/Strobe.hs view
@@ -0,0 +1,79 @@+------------------------------------------------------------------------+-- |+-- Module      : Trace.Hpc.Strobe+-- Copyright   : (C) 2009, Thorkil Naur+-- License     : BSD3-style (see LICENSE)+--+-- Maintainer  : Thorkil Naur+-- Stability   : unstable+-- Portability : Requires GHC with Hpc support.+--+-- A rudimentary library that demonstrates the possibility of+-- using Hpc (Haskell Program Coverage) to inspect the state of+-- a running Haskell program. Use of the library involves a+-- simple change of the main function and also requires the+-- program to be enabled for hpc. At the time of writing, this+-- means using a fairly recent version of GHC and compiling the+-- Haskell code with the @-fhpc@ option.+--+------------------------------------------------------------------------++module Trace.Hpc.Strobe (++    -- * Write strobes (tix files) regularly while program is running+      withStrobesWrittenRegularly++  ) where++import System.FilePath+import Control.Concurrent+import Trace.Hpc.Tix+import Trace.Hpc.Reflect++strobe :: FilePath -> String -> Int -> IO ()+strobe directory filePrefix interval+  = do mapM_ go [0..]+    where+    go :: Integer -> IO ()+    go d = do strobeTix d+              threadDelay interval+    fileName n = (filePrefix ++ "_" ++ show n) <.> "tix"+    strobeTix n = do tix <- examineTix+                     writeTix (directory </> fileName n) tix++-- | Replace+--+-- @+-- main = \<your main function>+-- @+--+-- by+--+-- @+-- myMain = \<your main function>+-- main = withStrobesWrittenRegularly+--          \"\<tixfile directory>\"+--          \"myMain\"+--          1000000+--          myMain+-- @+--+-- and strobes (separate Hpc tix files) will be written regularly,+-- with 1 second (1000000 microseconds) between each writing of a+-- strobe. The tix files will be deposited in the indicated tixfile+-- directory and be named \"myMain_\<index>.tix\" where the+-- index is taken from [0..].++withStrobesWrittenRegularly+  :: FilePath     -- ^ Name of directory where .tix files are deposited.+                  -- If this directory does not exist, no tix files are+                  -- written.+  -> String       -- ^ Prefix of file name for .tix files.+  -> Int          -- ^ Microseconds between writing a .tix file.+  -> IO ()        -- ^ The main function to be strobe'd.+  -> IO ()        -- ^ The modified main function.++withStrobesWrittenRegularly directory filePrefix interval mainFunction+  = do+      forkIO $ strobe directory filePrefix interval+      mainFunction