Problem having many go routines

303 views
Skip to first unread message

DreamDreams

unread,
Mar 23, 2011, 8:43:34 AM3/23/11
to golang-nuts
I was trying to play with websocket using Go and have some problem
when having many goroutines.

I created a test program:

#cat test.go
package main

import (
"time"
"fmt"
)

func main() {
for x :=0 ; x < 32184; x++{
go func(){
max := 0
for {
time.Sleep(1000*1000*1000)
max ++
}
}()
}
for{
time.Sleep(1000*1000*3000)
fmt.Printf("time!\n")
}

}

The program compiles fine. And when I run it, I got following error:

runtime.entersyscall+0x28 /opt/go/src/pkg/runtime/proc.c:577
runtime.entersyscall()
syscall.Syscall6+0x6a /opt/go/src/pkg/syscall/asm_linux_amd64.s:61
syscall.Syscall6()
syscall.Select+0x69 /opt/go/src/pkg/syscall/zsyscall_linux_amd64.go:
896
syscall.Select(0x0, 0x0, 0x0, 0x0, 0xf8c7f1d220, ...)
syscall.Sleep+0x7a /opt/go/src/pkg/syscall/syscall_linux.go:189
syscall.Sleep(0x3b9aca00, 0x0, 0x0, 0x0)
time.sleep+0x40 /opt/go/src/pkg/time/sleep.go:65
time.sleep(0x120dab2736b81000, 0x3b9aca00, 0x120dab2736b80c18,
0x0, 0x0, ...)
time.Sleep+0x33 /opt/go/src/pkg/time/sleep.go:54
time.Sleep(0x3b9aca00, 0x0, 0x0, 0x200000000)
main._func_001+0x2c /home/wsong/libwebsite/test/test.go:13
main._func_001()
runtime.goexit /opt/go/src/pkg/runtime/proc.c:149
runtime.goexit()

My kernel is 2.6.38-7-generic, 8G RAM.
# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

Any idea?

John Asmuth

unread,
Mar 23, 2011, 8:48:44 AM3/23/11
to golan...@googlegroups.com, DreamDreams
When I run this, I get massive stack traces, but it's headed by

runtime: failed to create new OS thread (have 132 already; errno=12)
throw: runtime.newosproc

Perhaps that might make what's happening more clear to someone with the knowledge to answer the question.

DreamDreams

unread,
Mar 23, 2011, 9:03:08 AM3/23/11
to golang-nuts
Thanks John. I should have pasted the first several lines of the error
message which is:
panic: runtime error: invalid memory address or nil pointer
dereference

[signal 0xb code=0x1 addr=0x7b pc=0x41175c]

runtime.panic+0xac /opt/go/src/pkg/runtime/proc.c:1024
runtime.panic(0x451154, 0xf8c999a830)
runtime.panicstring+0xa3 /opt/go/src/pkg/runtime/runtime.c:117
runtime.panicstring(0x4f37af, 0x6)
runtime.sigpanic+0x144 /opt/go/src/pkg/runtime/linux/thread.c:291
runtime.sigpanic()
runtime.newosproc+0x5a /opt/go/src/pkg/runtime/linux/thread.c:256
runtime.newosproc(0xf8a6a4b780, 0xf877c4c630, 0xf8acb964b8,
0x40c5d2, 0x100000000, ...)
matchmg+0x187 /opt/go/src/pkg/runtime/proc.c:449
matchmg()
runtime.entersyscall+0x71 /opt/go/src/pkg/runtime/proc.c:585
runtime.entersyscall()
syscall.Syscall6+0x5 /opt/go/src/pkg/syscall/asm_linux_amd64.s:40
syscall.Syscall6()
syscall.Select+0x69 /opt/go/src/pkg/syscall/zsyscall_linux_amd64.go:
896
syscall.Select(0x0, 0x0, 0x0, 0x0, 0xf8c999a820, ...)
syscall.Sleep+0x7a /opt/go/src/pkg/syscall/syscall_linux.go:189
syscall.Sleep(0x3b9aca00, 0x0, 0x0, 0x0)
time.sleep+0x40 /opt/go/src/pkg/time/sleep.go:65
time.sleep(0x120dac4a15488d18, 0x3b9aca00, 0x120dac4a15488d18,
0x0, 0x0, ...)
time.Sleep+0x33 /opt/go/src/pkg/time/sleep.go:54
time.Sleep(0x3b9aca00, 0x0, 0x0, 0x200000000)
main._func_001+0x2c /home/wsong/libwebsite/test/test.go:13
main._func_001()
runtime.goexit /opt/go/src/pkg/runtime/proc.c:149
runtime.goexit()


Jan Mercl

unread,
Mar 23, 2011, 9:08:47 AM3/23/11
to golan...@googlegroups.com, DreamDreams
On Wednesday, March 23, 2011 1:43:34 PM UTC+1, DreamDreams wrote:
The program compiles fine. And when I run it, I got following error:

The program works fine for me on Ubuntu 10.04 LTS.

$ uname -a
Linux shinigami 2.6.32-30-generic #59-Ubuntu SMP Tue Mar 1 21:30:46 UTC 2011 x86_64 GNU/Linux
$ hg id
3b4e9c85b643 weekly/weekly.2011-03-15

Ibrahim M. Ghazal

unread,
Mar 23, 2011, 9:14:46 AM3/23/11
to DreamDreams, golan...@googlegroups.com

I'm guessing the problem is that the goroutines are blocking on the
sleep call. When a goroutine blocks, the thread it's running on cannot
run other goroutines (they're moved to other threads). So, while you
can practically create thousands of goroutines, you can only have n
goroutines blocking at the same time (where n is the maximum number of
threads your operating system can create for a process).

John Asmuth

unread,
Mar 23, 2011, 9:20:18 AM3/23/11
to golan...@googlegroups.com, DreamDreams, Ibrahim M. Ghazal
I don't believe this is true. The whole point of goroutines is that you can have many on a single process, and when one blocks the others can run. Otherwise they'd just be...processes?

This is assuming that time.Sleep() causes a yield. In any sane world, it will.

Russ Cox

unread,
Mar 23, 2011, 9:24:53 AM3/23/11
to golan...@googlegroups.com, John Asmuth, DreamDreams, Ibrahim M. Ghazal
> This is assuming that time.Sleep() causes a yield.
> In any sane world, it will.

It should, but it doesn't right now.
More runtime work is needed.

Russ

roger peppe

unread,
Mar 23, 2011, 9:46:18 AM3/23/11
to DreamDreams, golang-nuts

as a work around, if you use time.After (or time.NewTimer) you should
avoid this problem - only one goroutine will call Sleep at a time.

Ibrahim M. Ghazal

unread,
Mar 23, 2011, 9:58:03 AM3/23/11
to John Asmuth, golan...@googlegroups.com

Threads and goroutines are N:M; a thread can have multiple goroutines,
and a goroutine can move between different threads. When a goroutine
blocks on a syscall (other kinds of blocking, such as channel
operations, don't cause this AFAIK), the other goroutines on the same
thread are moved to other threads.

time.Sleep currently calls sleep syscall every time it's called, but
it can be implemented without it. time.After uses such trick.

Message has been deleted

Wenqiang Song

unread,
Mar 23, 2011, 10:11:30 AM3/23/11
to roger peppe, golang-nuts
You are right. time.After works fine. 
Thanks.

On Wed, Mar 23, 2011 at 9:46 PM, roger peppe <rogp...@gmail.com> wrote:



--
有志者,事竟成,破釜沉舟,百二秦关终属楚
苦心人,天不负,卧薪尝胆,三千越甲可吞吴

John Asmuth

unread,
Mar 23, 2011, 10:30:49 AM3/23/11
to Ibrahim M. Ghazal, golan...@googlegroups.com
I was under the impression that syscalls, channel ops, file io all caused the goroutine to yield. Is time.Sleep a special case, or did I add syscalls to that list by mistake?

- John

Russ Cox

unread,
Mar 23, 2011, 10:33:00 AM3/23/11
to John Asmuth, Ibrahim M. Ghazal, golan...@googlegroups.com
On Wed, Mar 23, 2011 at 10:30, John Asmuth <jas...@gmail.com> wrote:
> I was under the impression that syscalls, channel ops, file io all caused
> the goroutine to yield. Is time.Sleep a special case, or did I add syscalls
> to that list by mistake?

syscalls have to block the whole thread.
That's just what they do - your operating
system kernel is not aware of Go.
The runtime takes care of making sure that
if a thread gets blocked by one goroutine,
the other goroutines run in some other thread.

Russ

Rob 'Commander' Pike

unread,
Mar 23, 2011, 12:54:12 PM3/23/11
to r...@golang.org, John Asmuth, Ibrahim M. Ghazal, golan...@googlegroups.com
Sleep should be implemented in the runtime rather than by a system
call. Until then, time.After is your friend.

-rob

John Asmuth

unread,
Mar 23, 2011, 1:24:07 PM3/23/11
to golan...@googlegroups.com, r...@golang.org, John Asmuth, Ibrahim M. Ghazal, Rob 'Commander' Pike
Why not, in the time pkg,

func Sleep(ns int64) {
  <-After(ns)
}
Reply all
Reply to author
Forward
0 new messages