Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: program takes more OS threads than expected #1480

Closed
rsc opened this issue Feb 4, 2011 · 4 comments
Closed

runtime: program takes more OS threads than expected #1480

rsc opened this issue Feb 4, 2011 · 4 comments
Milestone

Comments

@rsc
Copy link
Contributor

rsc commented Feb 4, 2011

from   ziutek <ziutek@lnet.pl>
to  golang-nuts <golang-nuts@googlegroups.com>
date    Fri, Feb 4, 2011 at 09:23
subject [go-nuts] Re: How GOMAXPROCS is used by current 8g implementation?

I wrote simple test using http package:

 package main

 import (
    "log"
    "http"
 )

 func handler(wr http.ResponseWriter, req *http.Request) {
    wr.Write([]byte("Ok!\n"))
 }

 func main() {
    err := http.ListenAndServe(":8080", http.HandlerFunc(handler))
    if err != nil {
        log.Fatalln("ListenAndServe:", err)
    }
 }

Then compile it and run:

 $ 8g test.go && 8l -o test test.8
 $ GOMAXPROC=2 ./test

There is output from  ps -eL |grep test

 3176  3176 pts/0    00:00:00 test
 3176  3177 pts/0    00:00:00 test

Next I use curl to get something from this application:

 $ curl 127.0.0.1:8080
 Ok!
 $ curl 127.0.0.1:8080
 Ok!

And ps -eL:

 3176  3176 pts/0    00:00:00 test
 3176  3177 pts/0    00:00:00 test

Next I use siege with 10 concurrent simulated users:

 $ siege 127.0.0.1:8080 -c10 -d0 -t10s
 ** SIEGE 2.70
 ** Preparing 10 concurrent users for battle.
 The server is now under siege...
 Lifting the server siege.      done.
 Transactions:                 11791 hits
 Availability:                100.00 %
 Elapsed time:                  9.07 secs
 Data transferred:              0.04 MB
 Response time:                 0.01 secs
 Transaction rate:           1300.00 trans/sec
 Throughput:                    0.00 MB/sec
 Concurrency:                   9.85
 Successful transactions:       11792
 Failed transactions:              0
 Longest transaction:           0.03
 Shortest transaction:          0.00

And ps -eL:

 3176  3176 pts/0    00:00:00 test
 3176  3177 pts/0    00:00:00 test
 3176  3260 pts/0    00:00:01 test
 3176  3261 pts/0    00:00:00 test
 3176  3262 pts/0    00:00:01 test
 3176  3263 pts/0    00:00:01 test
 3176  3264 pts/0    00:00:01 test
 3176  3265 pts/0    00:00:01 test

there is 8 persistent threads. This number of threads is constant even
if I use siege with 100 concurrent users.

Is this the expected behavior? Maybe it is related to my 36 threads
"problem" (it isn't any problem for me if the number of threads will
not increase in time).
@rsc
Copy link
Contributor Author

rsc commented Dec 9, 2011

Comment 1:

Labels changed: added priority-later.

@rsc
Copy link
Contributor Author

rsc commented Dec 12, 2011

Comment 2:

Labels changed: added priority-go1.

@robpike
Copy link
Contributor

robpike commented Jan 13, 2012

Comment 3:

Owner changed to builder@golang.org.

@rsc
Copy link
Contributor Author

rsc commented Feb 12, 2012

Comment 5:

I looked into this.  I think this is expected behavior.
There will always be a few extra threads because you've got different goroutines running
system calls, and the runtime creates new threads as necessary to avoid blocking the
entire program just because a few goroutines are executing system calls.
You can profile where the threads are coming from by running this variant of your
program:
package main
import (
    "log"
    "net/http"
    _ "net/http/pprof"
)
func handler(wr http.ResponseWriter, req *http.Request) {
    wr.Write([]byte("Ok!\n"))
}
func main() {
    http.HandleFunc("/", handler)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatalln("ListenAndServe:", err)
    }
}
after sieging it, run
go tool pprof http://localhost:8081/debug/pprof/thread
and at the (pprof) prompt, run web.  It will show the call stacks
that led to the creation of new threads.  Especially if you see
the thread count growing without bound, this will help you figure
out why (and that would be a bug; please report it).  But 8 threads
seems fine.

Status changed to WorkingAsIntended.

@rsc rsc added this to the Go1 milestone Apr 10, 2015
@rsc rsc removed the priority-go1 label Apr 10, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants