The problem is that the profiler doesn't work with forkProcess (e.g., see #8862). In this
particular case, the issue is that the elapsed per-process time is being
reported for each sample. Since the parent
spends more time performing the forks than each child does executing
threadDelay, its elapsed time is the largest. But the parent outputs its
sample before either child, and so the samples appear out of order.
The reason this behavior does not cause a problem when using 7.10.3 is
that the sample times used to only be reported in hundredths of a second (and so were all 0.00).
As of 1da3bbd2, they are being reported with
full precision.
One possible way to work around this
is to simply increase the threadDelay intervals for each child (400000 for the
first and 800000 for the second worked for me).
David also reported seeing this while profiling GHC (#14006 (closed)). However, I think we should keep this ticket to describe the incompatibility with forkProcess. Perhaps comment on #14006 (closed) instead. It might be helpful if you could include the hp file as well.
I don't have the .hp anymore :(
It's been basically a prof stage2, compiling a module e.g. Dynflags with -fllvmng. Due to the time building ghc takes, I won't be able to reproduce this right away. Eventually I'll probably have to again, when testing the llvmng backend.
I hit this today on 8.2.1. This is on a proprietary project so I am unable to provide any substantial code to aid debugging this. Below is a highly inefficient program which re-sequences .hp so that you can at least use the data.
{-# LANGUAGE LambdaCase #-}{-# LANGUAGE OverloadedStrings #-}moduleMain(main)whereimportControl.Monad(guard)importData.Attoparsec.CombinatorasPimportData.Attoparsec.TextasPimportData.List(sort)importData.Monoid((<>))importData.TextasTimportqualifiedData.Text.IOasTimportSystem.Environment(getArgs)importSystem.Exit(exitFailure)importSystem.IO(hPutStrLn,stderr)dataSample=Sample!Double![Text]deriving(Eq)instanceOrdSamplewherecompare(Samplex_)(Sampley_)=comparexydataF=F![Text]![Sample]parseF::ParserFparseF=dols<-P.manyTill(P.takeTillisEndOfLine<*endOfLine)(P.lookAhead"BEGIN_SAMPLE")s<-P.many'parseSamplepure$!FlssparseSample::ParserSampleparseSample=dos<-"BEGIN_SAMPLE "*>double<*endOfLineletendSample=does<-"END_SAMPLE "*>double<*endOfLineguard(es==s)l=P.takeTillisEndOfLine<*endOfLinels<-P.manyTilllendSamplepure$!SampleslsrenderSample::Sample->TextrenderSample(Sampledls)=T.unlines$("BEGIN_SAMPLE "<>T.pack(showd)):ls++["END_SAMPLE "<>T.pack(showd)]main::IO()main=getArgs>>=\case[input,output]->doc<-T.readFileinputcaseparseOnlyparseFcofLefterr->dohPutStrLnstderr("Parse failed: "<>err)exitFailureRight(FstartLinessamples)->dolets'=T.concat.Prelude.maprenderSample$sortsamplesT.writeFileoutput(T.unlinesstartLines<>s')_->dohPutStrLnstderr"usage: fix-hp inputFile outputFile"exitFailure
Ohh, i'm super sorry, not to have attached my reorder script.
{-# LANGUAGE LambdaCase #-}importSystem.Environment(getArgs)importData.List(mapAccumL,isPrefixOf)importGHC.Exts(sortWith)main::IO()main=getArgs>>=\case[f]->readFilef>>=pure.unlines.reorder.lines>>=putStr_->putStrLn$"only one input"reorder::[String]->[String]reorder=mapsnd.sortWithfst.snd.mapAccumLf(-1.0)whereg::(Double,String)->(Double,(Double,String))g(x,y)=(x,(x,y))f::Double->String->(Double,(Double,String))faccline|"BEGIN_SAMPLE "`isPrefixOf`line=g(read$drop13line,line)|"END_SAMPLE "`isPrefixOf`line&&(read$drop11line)/=acc=error"BEING/END missmatch"|otherwise=g(acc,line)