Why does forkIO also create native threads?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Why does forkIO also create native threads?

Lych
I wrote a simple ECHO server like this:
----------------------------------------------------
import Network
import System.IO
import Control.Concurrent

service cs = do
        ln <- hGetContents cs
        hPutStr cs ln
        service cs


acceptloop ls = do
     (cs, host, port) <- accept ls
     hSetBuffering cs LineBuffering
     forkIO (service cs)
     acceptloop ls

main = do
     ls <- listenOn (PortNumber 10061)
     acceptloop ls
----------------------------------------------------

And tested it with a client that initiates as many parallel
connections as possible. The number of connections can just reach to
1000+ on my machine, but I thought it should be more, since forkIO
generates lightweight threads. I also examined the number of threads
in this process with some tool and it proved there was one native
thread per connection. When I replaced the 'forkIO' in the program
with 'forkOS', I got an exactly similar result. Have I thought
something wrong about forkIO?
Reply | Threaded
Open this post in threaded view
|

Why does forkIO also create native threads?

Peter Verswyvelen-2
It seems that it's not the forkIO that is creating native threads (using GHC
6.10.1, -O flag)
For example, the following code only has 5 threads on my Windows box, while
I fork 10 lightweight threads

import System.IO
import Control.Concurrent
import Control.Monad

entry :: Char -> IO()
entry c  = do
  forever $ putChar c
main = do
hSetBuffering stdout NoBuffering
mapM_ (forkIO . entry) ['0'..'9']
putStrLn "all forked; press ENTER to quit"
getLine
However, things can get bizarre. When we change the entry function into

entry :: Char -> IO()
entry c  = do
  putChar c
  threadDelay maxBound

Then on my machine 13 native threads *are* created. This might make sense
because its waiting forever, but native threads are also created for the
following code:

entry :: Char -> IO()
entry c  = do
  putChar c
  forever $ threadDelay 0

This feels like overkill, so it seems threadDelay always forks a new native
thread, although this is not documented.

We can also get into the dark corners of GHC's lightweight thread
scheduling: a thread switch only happens when memory is allocated on the GC
head (but this is documented in the API)

So the following code will not work, the runtime seems to get stuck in an
infinite loop after the first thread is created.

entry :: Char -> IO()
entry c  = do
  putChar c
  forever $ return ()

In artificial cases like this you can use yield

entry :: Char -> IO()
entry c  = do
  putChar c
  forever yield

On Mon, Apr 13, 2009 at 10:37 AM, Lych <[hidden email]> wrote:

> I wrote a simple ECHO server like this:
> ----------------------------------------------------
> import Network
> import System.IO
> import Control.Concurrent
>
> service cs = do
>        ln <- hGetContents cs
>        hPutStr cs ln
>        service cs
>
>
> acceptloop ls = do
>     (cs, host, port) <- accept ls
>     hSetBuffering cs LineBuffering
>     forkIO (service cs)
>     acceptloop ls
>
> main = do
>     ls <- listenOn (PortNumber 10061)
>     acceptloop ls
> ----------------------------------------------------
>
> And tested it with a client that initiates as many parallel
> connections as possible. The number of connections can just reach to
> 1000+ on my machine, but I thought it should be more, since forkIO
> generates lightweight threads. I also examined the number of threads
> in this process with some tool and it proved there was one native
> thread per connection. When I replaced the 'forkIO' in the program
> with 'forkOS', I got an exactly similar result. Have I thought
> something wrong about forkIO?
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090413/12b5b9ba/attachment.htm