From f2fa4f982502dfa1079392c36163c7c4d841e918 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Sat, 11 Nov 2023 15:23:32 +0530 Subject: [PATCH 01/10] Add an executable to collect live statitics --- cabal.project.user | 5 + haskell-perf.cabal | 15 ++ stat-collector-src/Main.hs | 307 +++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 stat-collector-src/Main.hs diff --git a/cabal.project.user b/cabal.project.user index a178b69..23b949c 100644 --- a/cabal.project.user +++ b/cabal.project.user @@ -5,3 +5,8 @@ source-repository-package location: https://github.com/composewell/streamly.git tag: master subdir: core + +source-repository-package + type: git + location: https://github.com/composewell/streamly.git + tag: master diff --git a/haskell-perf.cabal b/haskell-perf.cabal index eb93ddf..dc684a6 100644 --- a/haskell-perf.cabal +++ b/haskell-perf.cabal @@ -117,3 +117,18 @@ executable hperf , streamly-core == 0.2.0 , format-numbers , text + +executable stat-collector + import: compile-options + hs-source-dirs: stat-collector-src + main-is: Main.hs + ghc-options: -O2 -fmax-worker-args=16 -fspec-constr-recursive=16 + build-depends: + base + , streamly-core + , streamly + , containers + , ansi-terminal + , format-numbers + , unix + , text diff --git a/stat-collector-src/Main.hs b/stat-collector-src/Main.hs new file mode 100644 index 0000000..253ea23 --- /dev/null +++ b/stat-collector-src/Main.hs @@ -0,0 +1,307 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Main (main) where + +-------------------------------------------------------------------------------- +-- Imports +-------------------------------------------------------------------------------- + +-- import Control.Concurrent (threadDelay) +import Data.Int (Int32, Int64) +import System.Environment (getArgs) +import Control.Monad.IO.Class (MonadIO(..)) +import Data.Function ((&)) +import Data.List (foldl', findIndex, sortBy, find) +import Data.Map (Map) +import Data.Maybe (fromMaybe, fromJust) +import Data.Word (Word8) +import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr) +import Foreign.Storable (Storable, peek) +import Numeric (showFFloat) +import Streamly.Data.Array (Array) +import Streamly.Data.Fold (Fold) +import Streamly.Data.Stream (Stream) +import Streamly.Internal.Data.Fold (Fold(..), Step(..)) +import Streamly.Internal.Data.Ring (slidingWindow) +import Streamly.Internal.Data.Tuple.Strict (Tuple3Fused' (Tuple3Fused')) +import Streamly.Unicode.String (str) +import System.IO (hFlush, stdout, stdin) +import Text.Read (readMaybe) +import System.Posix.Signals (installHandler, Handler(Catch), sigINT, sigTERM) +import Data.Text.Format.Numbers (prettyI) + +import qualified Data.Text as Text +import qualified Data.Map as Map +import qualified Streamly.Data.Fold as Fold +import qualified Streamly.Data.Stream.Prelude as Stream +import qualified Streamly.FileSystem.Handle as Handle +import qualified Streamly.Internal.Data.Fold as Fold +import qualified Streamly.Internal.Data.Ring as Ring +import qualified Streamly.Unicode.Stream as Unicode +import qualified System.Console.ANSI as ANSI + +-------------------------------------------------------------------------------- +-- Utils +-------------------------------------------------------------------------------- + +double :: Int -> Double +double = fromIntegral + +-------------------------------------------------------------------------------- +-- Types +-------------------------------------------------------------------------------- + +data Boundary a b + = Start a + | End a (Maybe b) + deriving (Read, Show, Ord, Eq) + +getWindowId :: Boundary WindowId Label -> WindowId +getWindowId (Start a) = a +getWindowId (End a _) = a + +data Counter + = ThreadCpuTime + | ProcessCpuTime + | WallClockTime + | Allocated + | SchedOut + deriving (Read, Show, Ord, Eq) + +type WindowId = String +type Label = String +type ThreadId = Int32 +type Tag = String +type Value = Int64 + +data EventId = + EventId + { evTid :: ThreadId + , evCounter :: Counter + , evTag :: Tag + } + deriving (Eq, Ord, Show) + +data UnboundedEvent + = UEvent (Boundary WindowId Label) ThreadId Counter Value + deriving (Show) + +data Event + = Event EventId Value + deriving (Show) + +getEventId :: Event -> EventId +getEventId (Event evId _) = evId + +getEventVal :: Event -> Value +getEventVal (Event _ evVal) = evVal + +-------------------------------------------------------------------------------- +-- Folds +-------------------------------------------------------------------------------- + +statsLayout :: [String] +statsLayout = + [ "latest", "total", "count", "avg", "minimum", "maximum", "stddev"] + +{-# INLINE stats #-} +stats :: Fold IO Int64 [(String, Int)] +stats = + Fold.lmap (fromIntegral :: Int64 -> Int) + $ Fold.distribute + [ fmap (\x -> ("latest", fromJust x)) Fold.latest + , fmap (\x -> ("total", x)) Fold.sum + , fmap (\x -> ("count", x)) Fold.length + , fmap (\x -> ("avg", round x)) (Fold.lmap double Fold.mean) + , fmap (\x -> ("minimum", fromJust x)) Fold.minimum + , fmap (\x -> ("maximum", fromJust x)) Fold.maximum + , fmap (\x -> ("stddev", round x)) (Fold.lmap double Fold.stdDev) + ] + +-------------------------------------------------------------------------------- +-- Parsing Input +-------------------------------------------------------------------------------- + +-- Event format: +-- Start//