开发者

Program crashing when trying to create multiple threads

开发者 https://www.devze.com 2023-03-04 03:11 出处:网络
I have the following program: module Main where import System (getArgs) import Control.Concurrent import Control.Monad

I have the following program:

module Main where

import System (getArgs)
import Control.Concurrent
import Control.Monad

spawn left id = do
   right <- newEmptyMVar
   forkIO (thread id left right) 
   return right

thread id left right = go 
   where go = do l <- takeMVar left
                 putStrLn (show id)
                 putMVar right ()

main = do
   args <- getArgs
   if null args then
      putStrLn "Arguments not supplied"
   else do
      initial <- newEmptyMVar
      final <- foldM spawn initial [1..(read (head args))]
      putMVar initial ()
      takeMVar final

As you can see, it just creates a bunch of threads: each thread pri开发者_如何学Cnts an integer, but the second thread waits for the first before printing, the third waits for the second and so on. Let us not discuss the usefulness of this program (it's just an exercise).

Now, when I try to create one million threads, the program is killed with SIGKILL. I'd like to know the reason of this. Is it because of too many MVars?

Thanks.


Every thread that's created requires its own program stack. I don't actually know how large of a stack Haskell uses for its threads, but if it's 4kbytes (which would be terribly small, actually) that's going to be 4GB just for the million stacks. If you're on a 32-bit machine, that's all of addressable memory, so that's obviously not going to work. And typical stack sizes are more like a megabyte!


According to the GHC docs, the initial stack size for each thread is by default 1K, and it can grow on demand to 8M per thread.

You can adjust these numbers by using the RTS options -k and -K, for example:

$ ./Threads 1000000 +RTS -k512 -K1K -s

Your program runs fine on my system (64-bit with 6GB RAM), but it does consume over 2GB at its peak.

   4,743,629,168 bytes allocated in the heap
   4,368,720,328 bytes copied during GC
   1,043,256,808 bytes maximum residency (11 sample(s))
     221,352,512 bytes maximum slop
            2413 MB total memory in use (0 MB lost due to fragmentation)

  Generation 0:  8707 collections,     0 parallel,  1.46s,  1.59s elapsed
  Generation 1:    11 collections,     0 parallel,  1.72s,  3.16s elapsed

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    5.86s  ( 15.76s elapsed)
  GC    time    3.18s  (  4.75s elapsed)
  EXIT  time    0.08s  (  0.08s elapsed)
  Total time    9.12s  ( 20.59s elapsed)

  %GC time      34.9%  (23.1% elapsed)

  Alloc rate    798,590,769 bytes per MUT second

  Productivity  65.1% of total user, 28.9% of total elapsed

./Threads 1000000 +RTS -K1K -s  9.12s user 3.92s system 62% cpu 20.815 total
0

精彩评论

暂无评论...
验证码 换一张
取 消