packages feed

packed-data-0.1.0.2: benchmark/report/Go.hs

module Go where

import Control.Monad (unless)
import Data.Char (isDigit, isSpace)
import Data.List (groupBy, isPrefixOf)
import System.Directory (doesFileExist)
import System.IO hiding (stdout)
import System.Process
import Text.Read (readMaybe)
import Types
import Prelude

goTestPath :: String
goTestPath = "benchmark/report/go/benchmarks_test.go"

runGoBenchmarks :: BenchSuite -> IO [BenchmarkResult]
runGoBenchmarks s = do
    goIsFound <- doesFileExist goTestPath
    unless goIsFound $
        fail ("Could not find the Golang benchmark in " ++ goTestPath)
    (_, Just hout, _, _) <-
        createProcess (shell golangCmd){std_out = CreatePipe}
    hGetContents hout >>= parseOutput s
  where
    golangTestSuiteName = suiteToGolangBenchName s
    golangCmd = "go test " ++ goTestPath ++ " -bench " ++ golangTestSuiteName

suiteToGolangBenchName :: BenchSuite -> String
suiteToGolangBenchName = \case
    AST -> "BenchmarkAST"
    Sum -> "BenchmarkSum"
    RightMost -> "BenchmarkGetRightMost"
    Incr -> "BenchmarkIncrement"

parseOutput :: (MonadFail m) => BenchSuite -> String -> m [BenchmarkResult]
parseOutput s stdout = do
    parsedLines <- parseOutputLine `mapM` l
    let groups = groupBy (\(sa, _, _) (sb, _, _) -> sa == sb) parsedLines
    return $ groupToBenchRes <$> groups
  where
    groupToBenchRes group =
        let
            (label, _, _) = head group
            n = if label == "BenchmarkIncrementInplace" then "Inplace" else "Produces new tree"
            v = (\(_, size, time) -> (size, time)) <$> group
         in
            BenchmarkResult{suite = s, values = v, language = "Golang", name = Just n}
    suiteName = suiteToGolangBenchName s
    l = filter (suiteName `isPrefixOf`) $ lines stdout

parseOutputLine :: (MonadFail m) => String -> m (String, Int, Double)
parseOutputLine bs =
    let res = do
            let suiteName = takeWhile (/= '_') bs
            treeSize <- readMaybe rawTreeSize
            time <- readMaybe rawTime
            return (suiteName, treeSize, time * 10 ^^ (-9))
     in maybe (fail "Parsing error") return res
  where
    -- BenchmarkSum_5-10 -> 5
    rawTreeSize = takeWhile (/= '-') (drop 1 $ dropWhile (/= '_') bs)
    -- BenchmarkEval_5-10             	11866071	      101.7 ns/op -> 101.7
    rawTime =
        takeWhile (\c -> c == '.' || isDigit c) $
            dropWhile isSpace $
                dropWhile isDigit $
                    dropWhile isSpace $
                        dropWhile (not . isSpace) bs