| ... |
... |
@@ -44,13 +44,13 @@ import qualified GHC.Exts.Heap as Heap |
|
44
|
44
|
#endif
|
|
45
|
45
|
import GHC.ForeignSrcLang
|
|
46
|
46
|
import GHC.Fingerprint
|
|
47
|
|
-import GHC.Conc (pseq, par)
|
|
48
|
47
|
import Control.Concurrent
|
|
49
|
48
|
import Control.DeepSeq
|
|
50
|
49
|
import Control.Exception
|
|
51
|
50
|
#if MIN_VERSION_base(4,20,0)
|
|
52
|
51
|
import Control.Exception.Context
|
|
53
|
52
|
#endif
|
|
|
53
|
+import Control.Monad.ST
|
|
54
|
54
|
import Data.Binary
|
|
55
|
55
|
import Data.Binary.Get
|
|
56
|
56
|
import Data.Binary.Put
|
| ... |
... |
@@ -66,6 +66,7 @@ import Data.Map (Map) |
|
66
|
66
|
import Foreign
|
|
67
|
67
|
import GHC.Generics
|
|
68
|
68
|
import GHC.Stack.CCS
|
|
|
69
|
+import GHC.Utils.Spark
|
|
69
|
70
|
import qualified GHC.Boot.TH.Syntax as TH
|
|
70
|
71
|
import qualified GHC.Boot.TH.Monad as TH
|
|
71
|
72
|
import System.Exit
|
| ... |
... |
@@ -572,7 +573,7 @@ getMessage = do |
|
572
|
573
|
9 -> Msg <$> RemoveLibrarySearchPath <$> get
|
|
573
|
574
|
10 -> Msg <$> return ResolveObjs
|
|
574
|
575
|
11 -> Msg <$> FindSystemLibrary <$> get
|
|
575
|
|
- 12 -> Msg <$> (CreateBCOs . concatMap (runGet get)) <$> (get :: Get [LB.ByteString])
|
|
|
576
|
+ 12 -> Msg <$> (CreateBCOs . fmap (runGet get)) <$> (get :: Get [LB.ByteString])
|
|
576
|
577
|
-- See Note [Parallelize CreateBCOs serialization]
|
|
577
|
578
|
13 -> Msg <$> FreeHValueRefs <$> get
|
|
578
|
579
|
14 -> Msg <$> MallocData <$> get
|
| ... |
... |
@@ -653,29 +654,17 @@ putMessage m = case m of |
|
653
|
654
|
Note [Parallelize CreateBCOs serialization]
|
|
654
|
655
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
655
|
656
|
Serializing ResolvedBCO is expensive, so we do it in parallel.
|
|
656
|
|
-We split the list [ResolvedBCO] into chunks of length <= 100,
|
|
657
|
|
-and serialize every chunk in parallel, getting a [LB.ByteString]
|
|
658
|
|
-where every bytestring corresponds to a single chunk (multiple ResolvedBCOs).
|
|
|
657
|
+For each element in the list [ResolvedBCO], we spawn a spark which
|
|
|
658
|
+serializes it, getting a [LB.ByteString] where every fully evaluated
|
|
|
659
|
+lazy ByteString corresponds to a single ResolvedBCO.
|
|
659
|
660
|
|
|
660
|
661
|
Previously, we stored [LB.ByteString] in the Message object, but that
|
|
661
|
662
|
incurs unneccessary serialization with the internal interpreter (#23919).
|
|
662
|
663
|
-}
|
|
663
|
664
|
|
|
664
|
665
|
serializeBCOs :: [ResolvedBCO] -> [LB.ByteString]
|
|
665
|
|
-serializeBCOs rbcos = parMap doChunk (chunkList 100 rbcos)
|
|
666
|
|
- where
|
|
667
|
|
- -- make sure we force the whole lazy ByteString
|
|
668
|
|
- doChunk c = pseq (LB.length bs) bs
|
|
669
|
|
- where bs = runPut (put c)
|
|
670
|
|
-
|
|
671
|
|
- -- We don't have the parallel package, so roll our own simple parMap
|
|
672
|
|
- parMap _ [] = []
|
|
673
|
|
- parMap f (x:xs) = fx `par` (fxs `pseq` (fx : fxs))
|
|
674
|
|
- where fx = f x; fxs = parMap f xs
|
|
675
|
|
-
|
|
676
|
|
- chunkList :: Int -> [a] -> [[a]]
|
|
677
|
|
- chunkList _ [] = []
|
|
678
|
|
- chunkList n xs = as : chunkList n bs where (as,bs) = splitAt n xs
|
|
|
666
|
+serializeBCOs rbcos =
|
|
|
667
|
+ runST $ traverse (sparkST . pure . force . runPut . put) rbcos
|
|
679
|
668
|
|
|
680
|
669
|
-- -----------------------------------------------------------------------------
|
|
681
|
670
|
-- Reading/writing messages
|