[Haskell-cafe] Weird multi-threading runtime behaviour of single-threaded program with GHC-7.0.3

Herbert Valerio Riedel hvr at gnu.org
Fri Apr 1 12:37:09 CEST 2011


Hello,

I'm experiencing an unexpected behaviour with GHC-7.0.3/x86_64's
multithreading runtime when running some more demanding single-thread
computations.

I've isolated the part of the larger application which exposes the
problem down to the parsing of a ~8MiB JSON file which causes quite a
bit of memory allocations (source at end of email). The program is
compiled with

ghc --make -O2 -threaded -eventlog -rtsopts parse_aeson.hs

and I ran it with and w/o the -N12 option on a 12-core machine (the
problem is visible on a 4-core machine as well):

$ time ./parse_aeson test.json
0.000392s after readFile
0.001016s parse was a success...
6.050836s NFed parse-tree...
6.050968s NFed parse-tree...
no exception

real    0m6.100s
user    0m5.680s
sys     0m0.419s


$ time ./parse_aeson test.json +RTS -N12
0.001249s after readFile
0.001777s parse was a success...
10.048607s NFed parse-tree...
10.048738s NFed parse-tree...
no exception

real    0m10.125s
user    0m57.496s
sys     0m39.927s


When observing top(1)'s output, I saw that all HECs consumed a
substantial amount of cpu cycle, so I loaded up threadscope to see what
the remaining 11 HECs were doing all the time.


I've put the resulting eventlog files and screenshots of threadscope's
visualization online at

http://www.narf.at/~hvr/Haskell/parse_aeson.N0.eventlog.png
http://www.narf.at/~hvr/Haskell/parse_aeson.N0.eventlog.xz

http://www.narf.at/~hvr/Haskell/parse_aeson.N12.eventlog.png
http://www.narf.at/~hvr/Haskell/parse_aeson.N12.eventlog.xz


What's happening there? The actual processing work seems to be done in a
single HEC... but what are the remaining 11 HECs doing exactly? Am I
doing something wrong?


What does it mean when the GC-bars in threadscope becomes green as in
the middle of the screenshot below?

http://www.narf.at/~hvr/Haskell/parse_aeson.N4.eventlog.pdf



-------------------------------------------------------------------------
-- also available at http://www.narf.at/~hvr/Haskell/parse_aeson.hs

module Main where

import Control.DeepSeq
import Control.Exception
import Data.Aeson
import Data.Time
import System.Environment
import qualified Data.Attoparsec.Lazy as APL
import qualified Data.ByteString.Lazy.Char8 as LB

parseIt :: FilePath -> IO ()
parseIt fn = do
  t0 <- getCurrentTime

  let putStrLn' !s = do
        t0' <- getCurrentTime
        putStrLn $ show (t0' `diffUTCTime` t0) ++ " " ++ s

  json_text <- LB.readFile fn

  putStrLn' "after readFile"
  let Success p = decode json_text :: Result Value
  putStrLn' "parse was a success..."
  putStrLn' $ p `deepseq` "NFed parse-tree..."
  putStrLn' $ p `deepseq` "NFed parse-tree..."

decode :: FromJSON a => LB.ByteString -> Result a
decode = either Error fromJSON . APL.eitherResult . APL.parse json

main :: IO ()
main = do
  fns <- getArgs
  case fns of
    [fn] -> do
      res <- try $ parseIt fn
      case res of
        Left e -> putStrLn $ "caught: " ++ show (e :: SomeException)
        Right () -> putStrLn "no exception"

    _    -> putStrLn "usage: parse_aeson <json-file>"






More information about the Haskell-Cafe mailing list