谈点对goroutine的理解

1976 views
Skip to first unread message

Hoping White

unread,
Feb 3, 2012, 1:50:09 AM2/3/12
to golang...@googlegroups.com

说点我对goroutine的看法

 

传统多线程程序

 

Thread1

Do-something

Do-something-block

....

 

thread1 block之后,如果还想要干其他事情,

那就只有再开一个thread来做事了

这样一来,当线程足够多时,性能就会下降,这是显然的

 

 

于是就有了非阻塞式/异步 比如epoll

 

Thread1

Do-something

Do-something-unblock-with-callback

...

 

ThreadN

Callback

Do-somehting

 

也即将原来可能阻塞的地方的代码以回调,事件等方式分解,在别的时候当条件满足时再执行。

这样就可以利用为数不多的线程来高效的完成任务。

 

但是显然这种方式,写起来很费劲,读起来很费劲,调试起来也很费劲。

 

go语言利用goroutine来解决了这一点,goroutine替代原来的thread成了最小调度单元,

一旦goroutine中的某个函数比如网络读写,或者sleep函数阻塞时,goroutine被挂起,

当前执行goroutine的线程可以再去找一个需要执行的goroutine去执行它,如果没找到,好吧,那就是死锁了。

 

其实goroutine的设计跟asio是很像的,毕竟都是基于CSP模型的,只不过它直接在语言层面实现的,使得代码看起来更加清晰,直观。

 

对我而言go语言最有魅力的地方就是goroutine这里了。上面是一些个人理解,如果有不对的,还请大家指正。

 

洪瑞琦

unread,
Feb 3, 2012, 3:12:35 AM2/3/12
to golang...@googlegroups.com

一旦goroutine中的某个函数比如网络读写,或者sleep函数阻塞时,goroutine被挂起,

当前执行goroutine的线程可以再去找一个需要执行的goroutine去执行它

 
 
实际的情况是,当前线程阻塞时,其它的goroutine并不是在当前线程执行的,而是被分配到空闲的线程(阻塞不是空闲),如果没有空闲线程就新建一个。新建线程中的goroutine执行完毕后,线程不会退出,成为空闲线程(一个动态增加的线程池) 

Hoping White

unread,
Feb 3, 2012, 3:27:14 AM2/3/12
to golang...@googlegroups.com

嗯,谢谢瑞琦,这里说错了,Proc.c里确实是这样做的。

补充一点,创建新线程不是无限限制的,而有一个上限的,如果当前的线程数达到上限

那么goroutine就进入等待队列了。

 

目前对于网络层的阻塞操作实际上似乎是将goroutine挂起的,将当前thread标志来空闲,然后等待epoll来重新调度的。

我不知道其他的系统调用是不是有直接阻塞的?

--
来自: Golang-China ~ 中文Go语言技术邮件列表
发言: golang...@googlegroups.com
详情: http://groups.google.com/group/golang-china
官网: http://golang-china.org/
翻译: http://github.com/border/golang-china/
论坛: http://bbs.golang-china.org/
@golangchina

洪瑞琦

unread,
Feb 3, 2012, 3:35:00 AM2/3/12
to golang...@googlegroups.com

最大线程数倒是没有注意,这个是系统限制的,还是由go自身限制的?默认是多少呢?谢谢

Hoping White

unread,
Feb 3, 2012, 4:12:47 AM2/3/12
to golang...@googlegroups.com

func GOMAXPROCS(n int) int

GOMAXPROCS sets the maximum number of CPUs that can be executing simultaneously and returns the previous setting. If n < 1, it does not change the current setting. The number of logical CPUs on the local machine can be queried with NumCPU. This call will go away when the scheduler improves.

另外可以参考proc.c里的atomic

 

// The atomic word in sched is an atomic uint32 that

// holds these fields.

//

//  [15 bits] mcpu      number of m's executing on cpu

//  [15 bits] mcpumax   max number of m's allowed on cpu

//  [1 bit] waitstop    some g is waiting on stopped

//  [1 bit] gwaiting    gwait != 0

洪瑞琦

unread,
Feb 3, 2012, 4:20:42 AM2/3/12
to golang...@googlegroups.com
看了几个地方,没看完整就是了
GOMAXPROC和mcpumax好像都是限制的活动线程数,并非总线程数

Hoping White

unread,
Feb 3, 2012, 5:54:26 AM2/3/12
to golang...@googlegroups.com

应该确实是最大同时执行的thread数,但是这里有个问题,当执行syscall时,当前的线程是什么状态?它可以转让出去给其他goroutine使用吗?

洪瑞琦

unread,
Feb 3, 2012, 6:13:06 AM2/3/12
to golang...@googlegroups.com
IO相关的Syscall会先执行调度,把可运行的goroutine放到其它线程运行(同时运行的<=GOMAXPROC),然后当前线程阻塞
其它的Syscall则直接阻塞当前线程

Hoping White

unread,
Feb 3, 2012, 6:33:34 AM2/3/12
to golang...@googlegroups.com

多谢,汇编已经看不懂了,许多地方靠猜了,继续再看看runtime

Yili Zhao

unread,
Feb 3, 2012, 9:37:41 AM2/3/12
to golang...@googlegroups.com
在 2012年2月3日 下午7:13,洪瑞琦 <hong...@gmail.com> 写道:
> IO相关的Syscall会先执行调度,把可运行的goroutine放到其它线程运行(同时运行的<=GOMAXPROC),然后当前线程阻塞
> 其它的Syscall则直接阻塞当前线程

对了,例如像fmt.Println()这样的调用应该是系统调用吧?

因此如果当前线程有fmt.Println(),则会被阻塞,然后Go的运行时会试着在其他线程中运行可运行的goroutine(如果有的话)?

另外,由于发生fmt.Println()而被阻塞的线程,什么时候会被重新调用?Go的运行时如何知道这个线程可以被重新调用,而不是继续阻塞?

谢谢!

--
Yili Zhao

mon...@gmail.com

unread,
Feb 3, 2012, 3:55:21 PM2/3/12
to golang...@googlegroups.com
Hoping White wrote, On 02/03/2012 06:33 AM:
> ��л������Ѿ��������ˣ����ط������ˣ������ٿ���runtime
>

OTһ�£��ܷ���"��"������Re:����RE:������ʱ�������?

> *������:*golang...@googlegroups.com
> [mailto:golang...@googlegroups.com] *��� *������
> *����ʱ��:*2012��2��3��19:13
> *�ռ���:*golang...@googlegroups.com
> *����:*Re: ��: ��: ��: [gocn:2051] ̸���goroutine�����
>
> IO��ص�Syscall����ִ�е��ȣ��ѿ����е�goroutine�ŵ������߳����У�ͬʱ��
> �е�<=GOMAXPROC����Ȼ��ǰ�߳�����
>
> �����Syscall��ֱ������ǰ�߳�
>
> ��2012��2��3�� ����6:54��Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>���
>
> Ӧ��ȷʵ�����ͬʱִ�е�thread���������и����⣬��ִ��syscallʱ����
> ǰ���߳���ʲô״̬�������ת�ó�ȥ������goroutineʹ����
>
> *������:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *��� *
>
> ������
> *����ʱ��:*2012��2��3��17:21
> *�ռ���:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *����:*Re: ��: ��: [gocn:2046] ̸���goroutine�����
>
> ���˼����ط���û�����������
>
> GOMAXPROC��mcpumax���������ƵĻ�߳�������߳���
>
> ��2012��2��3�� ����5:12��Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>���


>
> func GOMAXPROCS(n int) int
>
> GOMAXPROCS sets the maximum number of CPUs that can be executing
> simultaneously and returns the previous setting. If n < 1, it does not
> change the current setting. The number of logical CPUs on the local
> machine can be queried with NumCPU. This call will go away when the
> scheduler improves.
>

> ������Բο�proc.c���atomic


>
> // The atomic word in sched is an atomic uint32 that
>
> // holds these fields.
>
> //
>
> // [15 bits] mcpu number of m's executing on cpu
>
> // [15 bits] mcpumax max number of m's allowed on cpu
>
> // [1 bit] waitstop some g is waiting on stopped
>
> // [1 bit] gwaiting gwait != 0
>

> *������:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *��� *
>
> ������
> *����ʱ��:*2012��2��3��16:35
> *�ռ���:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *����:*Re: ��: [gocn:2044] ̸���goroutine�����
>
>
> ����߳�����û��ע�⣬�����ϵͳ���Ƶģ�������go�������Ƶģ�Ĭ���Ƕ���
> �أ�лл
>
> ��2012��2��3�� ����4:27��Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>���
>
> �ţ�лл��������˵���ˣ�Proc.c��ȷʵ���������ġ�
>
> ����һ�㣬�������̲߳����������Ƶģ�����һ�����޵ģ����ǰ���߳���ﵽ����
>
> ��ôgoroutine�ͽ���ȴ�����ˡ�
>
> Ŀǰ�����������������ʵ�����ƺ��ǽ�goroutine����ģ�����ǰthread��־
> �����У�Ȼ��ȴ�epoll�����µ��ȵġ�
>
> �Ҳ�֪�������ϵͳ�����Dz�����ֱ������ģ�
>
> *������:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *��� *������
> *����ʱ��:*2012��2��3��16:13
> *�ռ���:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *����:*Re: [gocn:2042] ̸���goroutine�����
>
> һ��goroutine�е�ij��������������д������sleep��������
> ʱ��goroutine������
>
> ��ǰִ��goroutine���߳̿�����ȥ��һ����Ҫִ�е�goroutineȥִ����
>
> ʵ�ʵ�����ǣ���ǰ�߳�����ʱ�������goroutine�������ڵ�ǰ�߳�ִ�еģ���
> �DZ����䵽���е��̣߳������ǿ��У������û�п����߳̾��½�һ�����½���
> ���е�goroutineִ����Ϻ��̲߳����˳�����Ϊ�����̣߳�һ����̬���ӵ���
> �̳أ�
>
> --
>
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com <mailto:golang...@googlegroups.com>
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina
>
> --
> ����: Golang-China ~ ����Go���Լ����ʼ��б�
> ����: golang...@googlegroups.com
> ����: http://groups.google.com/group/golang-china
> ����: http://golang-china.org/
> ����: http://github.com/border/golang-china/
> ��̳: http://bbs.golang-china.org/
> @golangchina

洪瑞琦

unread,
Feb 3, 2012, 7:08:18 PM2/3/12
to golang...@googlegroups.com
系统调用结束时,阻塞也结束了,调用系统调用的goroutine会重新加入可运行队列中等待调度,线程也被重新加入空闲列表(大概吧)

在 2012年2月4日 上午4:55,mon...@gmail.com <mon...@gmail.com>写道:
Hoping White wrote, On 02/03/2012 06:33 AM:
> 多谢,汇编已经看不懂了,许多地方靠猜了,继续再看看runtime
>

OT一下,能否不用"答复",改用Re:或者RE:,方便时间线整理。

> *发件人:*golang...@googlegroups.com
> [mailto:golang...@googlegroups.com] *代表 *洪瑞琦
> *发送时间:*2012年2月3日19:13
> *收件人:*golang...@googlegroups.com
> *主题:*Re: 答复: 答复: 答复: [gocn:2051] 谈点对goroutine的理解

>
> IO相关的Syscall会先执行调度,把可运行的goroutine放到其它线程运行(同时运
> 行的<=GOMAXPROC),然后当前线程阻塞
>
> 其它的Syscall则直接阻塞当前线程
>
> 在2012年2月3日 下午6:54,Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>写道:
>
> 应该确实是最大同时执行的thread数,但是这里有个问题,当执行syscall时,当
> 前的线程是什么状态?它可以转让出去给其他goroutine使用吗?
>
> *发件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *代表 *
>
> 洪瑞琦
> *发送时间:*2012年2月3日17:21
> *收件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *主题:*Re: 答复: 答复: [gocn:2046] 谈点对goroutine的理解
>
> 看了几个地方,没看完整就是了
>
> GOMAXPROC和mcpumax好像都是限制的活动线程数,并非总线程数
>
> 在2012年2月3日 下午5:12,Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>写道:
>
> func GOMAXPROCS(n int) int
>
> GOMAXPROCS sets the maximum number of CPUs that can be executing
> simultaneously and returns the previous setting. If n < 1, it does not
> change the current setting. The number of logical CPUs on the local
> machine can be queried with NumCPU. This call will go away when the
> scheduler improves.
>
> 另外可以参考proc.c里的atomic

>
> // The atomic word in sched is an atomic uint32 that
>
> // holds these fields.
>
> //
>
> // [15 bits] mcpu number of m's executing on cpu
>
> // [15 bits] mcpumax max number of m's allowed on cpu
>
> // [1 bit] waitstop some g is waiting on stopped
>
> // [1 bit] gwaiting gwait != 0
>
> *发件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *代表 *
>
> 洪瑞琦
> *发送时间:*2012年2月3日16:35
> *收件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *主题:*Re: 答复: [gocn:2044] 谈点对goroutine的理解
>
>
> 最大线程数倒是没有注意,这个是系统限制的,还是由go自身限制的?默认是多少
> 呢?谢谢
>
> 在2012年2月3日 下午4:27,Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>写道:

>
> 嗯,谢谢瑞琦,这里说错了,Proc.c里确实是这样做的。
>
> 补充一点,创建新线程不是无限限制的,而有一个上限的,如果当前的线程数达到上限
>
> 那么goroutine就进入等待队列了。
>
> 目前对于网络层的阻塞操作实际上似乎是将goroutine挂起的,将当前thread标志
> 来空闲,然后等待epoll来重新调度的。
>
> 我不知道其他的系统调用是不是有直接阻塞的?
>
> *发件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *代表 *洪瑞琦
> *发送时间:*2012年2月3日16:13
> *收件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *主题:*Re: [gocn:2042] 谈点对goroutine的理解
>
>     一旦goroutine中的某个函数比如网络读写,或者sleep函数阻塞

>     时,goroutine被挂起,
>
>     当前执行goroutine的线程可以再去找一个需要执行的goroutine去执行它
>
> 实际的情况是,当前线程阻塞时,其它的goroutine并不是在当前线程执行的,而
> 是被分配到空闲的线程(阻塞不是空闲),如果没有空闲线程就新建一个。新建线
> 程中的goroutine执行完毕后,线程不会退出,成为空闲线程(一个动态增加的线
> 程池)
>
> --
>
> 来自: Golang-China ~ 中文Go语言技术邮件列表

> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表

> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表

> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表

> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表

> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表

> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表

郭晓峰

unread,
Feb 3, 2012, 7:26:02 PM2/3/12
to golang...@googlegroups.com
其实我的理解,go程跟线程大约是两回事情,跟进程又是另外一件事情。

go程的调度直觉上想来,应该是round-robin的。一个go程阻塞了,另一个go程就起来了。这样一个线程就可以带很多go程了。至于调度的时候有没有优先级,还真的得好好考虑考虑。酱紫的话,go程不能太大,否则占用系统太久的话,响应就会是一个问题了。

另外,对于线程,事实已经证明,线程数量不能超core number太多,否则性能会受比较大影响。而且,thread里面的critical
section,很影响应用的整体性能。利用类CSP的go程,很大程度上可以把一些原来不得不用critical
section描述的东西转化成系统通讯,这是go最大的魅力所在。

当然,具体细化下去的话,问题还多多:
- go程的优化会不会做确定性的线程分配。比如gofunc1一定在线程1上,gofunc2一定在线程2上啥的。
- 有哪些事件可以作为go程阻塞的标志?等待别的go程的结果?I/O?memory access?有具体的列表吗?

只是,这么一种靠系统这么近的类CSP语言的发展,极大的方便了快速开发,真的是个写backend的无敌利器。

有空一定要仔细读读runtime pkg里面的code。

Best Regards,
Xiaofeng

2012/2/3 洪瑞琦 <hong...@gmail.com>:

洪瑞琦

unread,
Feb 3, 2012, 7:34:49 PM2/3/12
to golang...@googlegroups.com
- go程的优化会不会做确定性的线程分配。比如gofunc1一定在线程1上,gofunc2一定在线程2上啥的。
  之前写过代码测试过,貌似不会。。。同一个goroutine在不同时刻可能不同的线程运行(GOMAXPROC>1由于上下文切换引起的性能下降一直没有搞懂,=1的时候不是也会么?)

- 有哪些事件可以作为go程阻塞的标志?等待别的go程的结果?I/O?memory access?有具体的列表吗?
  目前我知道的,通过Syscall(Socketcall)的系统调用都会引发调度(Rawsyscall不会,所以gettid这样的函数不会使其它的goroutine运行),chan的等待也会引发调度

Hoping White

unread,
Feb 3, 2012, 8:58:33 PM2/3/12
to golang...@googlegroups.com
Sorry,用的是outlook客户端,现在改好了。

-----Original Message-----
From: golang...@googlegroups.com [mailto:golang...@googlegroups.com]
On Behalf Of mon...@gmail.com
Sent: Saturday, February 04, 2012 4:55 AM
To: golang...@googlegroups.com
Subject: Re: [gocn:2055] 谈点对goroutine的理解

Hoping White wrote, On 02/03/2012 06:33 AM:
> 多谢,汇编已经看不懂了,许多地方靠猜了,继续再看看runtime
>

OT一下,能否不用"答复",改用Re:或者RE:,方便时间线整理。

> *发件人:*golang...@googlegroups.com
> [mailto:golang...@googlegroups.com] *代表 *洪瑞琦
> *发送时间:*2012年2月3日19:13
> *收件人:*golang...@googlegroups.com
> *主题:*Re: 答复: 答复: 答复: [gocn:2051] 谈点对goroutine的理解
>
> IO相关的Syscall会先执行调度,把可运行的goroutine放到其它线程运行(同时运
> 行的<=GOMAXPROC),然后当前线程阻塞
>
> 其它的Syscall则直接阻塞当前线程
>
> 在2012年2月3日 下午6:54,Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>写道:
>
> 应该确实是最大同时执行的thread数,但是这里有个问题,当执行syscall时,当
> 前的线程是什么状态?它可以转让出去给其他goroutine使用吗?
>
> *发件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *代表 *
>
> 洪瑞琦
> *发送时间:*2012年2月3日17:21
> *收件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *主题:*Re: 答复: 答复: [gocn:2046] 谈点对goroutine的理解
>
> 看了几个地方,没看完整就是了
>
> GOMAXPROC和mcpumax好像都是限制的活动线程数,并非总线程数
>
> 在2012年2月3日 下午5:12,Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>写道:
>
> func GOMAXPROCS(n int) int
>
> GOMAXPROCS sets the maximum number of CPUs that can be executing
> simultaneously and returns the previous setting. If n < 1, it does not
> change the current setting. The number of logical CPUs on the local
> machine can be queried with NumCPU. This call will go away when the
> scheduler improves.
>
> 另外可以参考proc.c里的atomic
>
> // The atomic word in sched is an atomic uint32 that
>
> // holds these fields.
>
> //
>
> // [15 bits] mcpu number of m's executing on cpu
>
> // [15 bits] mcpumax max number of m's allowed on cpu
>
> // [1 bit] waitstop some g is waiting on stopped
>
> // [1 bit] gwaiting gwait != 0
>
> *发件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *代表 *
>
> 洪瑞琦
> *发送时间:*2012年2月3日16:35
> *收件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *主题:*Re: 答复: [gocn:2044] 谈点对goroutine的理解
>
>
> 最大线程数倒是没有注意,这个是系统限制的,还是由go自身限制的?默认是多少
> 呢?谢谢
>
> 在2012年2月3日 下午4:27,Hoping White <baiha...@gmail.com
> <mailto:baiha...@gmail.com>>写道:
>
> 嗯,谢谢瑞琦,这里说错了,Proc.c里确实是这样做的。
>
> 补充一点,创建新线程不是无限限制的,而有一个上限的,如果当前的线程数达到上

>
> 那么goroutine就进入等待队列了。
>
> 目前对于网络层的阻塞操作实际上似乎是将goroutine挂起的,将当前thread标志
> 来空闲,然后等待epoll来重新调度的。
>
> 我不知道其他的系统调用是不是有直接阻塞的?
>
> *发件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> [mailto:golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>] *代表 *洪瑞琦
> *发送时间:*2012年2月3日16:13
> *收件人:*golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> *主题:*Re: [gocn:2042] 谈点对goroutine的理解
>
> 一旦goroutine中的某个函数比如网络读写,或者sleep函数阻塞
> 时,goroutine被挂起,
>
> 当前执行goroutine的线程可以再去找一个需要执行的goroutine去执行它
>
> 实际的情况是,当前线程阻塞时,其它的goroutine并不是在当前线程执行的,而
> 是被分配到空闲的线程(阻塞不是空闲),如果没有空闲线程就新建一个。新建线
> 程中的goroutine执行完毕后,线程不会退出,成为空闲线程(一个动态增加的线
> 程池)
>
> --
>
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>
> 详情: http://groups.google.com/group/golang-china
> 官网: http://golang-china.org/
> 翻译: http://github.com/border/golang-china/
> 论坛: http://bbs.golang-china.org/
> @golangchina
>
> --
> 来自: Golang-China ~ 中文Go语言技术邮件列表
> 发言: golang...@googlegroups.com
> <mailto:golang...@googlegroups.com>

Liigo Zhuang

unread,
Feb 3, 2012, 9:30:50 PM2/3/12
to golang...@googlegroups.com

作为go语言普通使用者,没有必要关注语言底层实现。如果确实有兴趣关注,也对相关的底层系统技术比较熟悉,建议去阅读go语言编译器源代码,一切都不言自明。在各种前提都不具备的情况下,各种猜测性质的讨论都没有实际意义,徒增疑惑而已。

郭晓峰

unread,
Feb 3, 2012, 9:40:06 PM2/3/12
to golang...@googlegroups.com
关于GOMAXPROC > 1上下文切换的性能代价,我的理解是这样:

如果一个go routine一直在一个thread上运行,它性能切换的代价就是换寄存器(一般core都有寄存器cache,直接替换就可以) ,这个代价是很小的。但是如果GOMAXPROC>1的话,它就有可能被换到别的thread上运行,这时候换寄存器不可能用cache,只能在core间对拷,所以代价会大一些。

除了寄存器外,线程间不共享的东西(我也想不起来还有什么了),也需要copy,这也是系统负担。

你有相应的博客文吗?我看看确认一下。

2012/2/3 洪瑞琦 <hong...@gmail.com>:

洪瑞琦

unread,
Feb 4, 2012, 7:11:20 PM2/4/12
to golang...@googlegroups.com
GOMAXPROC=1时,也可能切换到别的thread上,是否切换上下文的概率或者频率在GOMAXPROC>1的时候会增大?

没看过关于这个的博文,抱歉!

wonderfo

unread,
Feb 4, 2012, 10:06:33 PM2/4/12
to golang-china
补充点个人看法:

GOMAXPROC和性能不应是简单的增减对应关系,需综合多种具体因素才好说,例如:

1、单核CPU:
  1)若 goroutine A 和 goroutine B 都是CPU运算密集任务,没有IO,也不互斥,在一个线程依次运算完最好,没有线程切换损耗
  2)若 goroutine A 和 goroutine B 会阻塞在相同资源上(如读同一个chan),那切换到不同线程也徒增损耗
  3)若 goroutine A 和 goroutine B 会阻塞在不同的资源上(如一个文件、一个网络),那两个线程协同最好,因IO损耗大于线程切换损耗
  4)若 goroutine A 和 goroutine B 各自的运行总时间都是30秒,且不互斥,那么线程单个或多个,还能看出多大差别?

2、多核CPU:
  肯定比单核多线程效率高,可是只有一个 GOMAXPROC 可设置,内部对应多核、多线程?情况又有差别了。

3、GOMAXPROC
  该参数本身也是近似值

4、调度算法:
  更智能当然好,不过太重了也未必好,同样需要平衡。

所以,不是 GOMAXPROC=1 或>1就一定会咋样,是实际各种因素共同决定的。

我所知也不多,简单列点,Go开发团队肯定应该会有更多考量,再加上开源的力量,假以时日,Go调度器的不断提升应该是可以期待的。
--------------
wonderfo
Reply all
Reply to author
Forward
0 new messages