有没有方法调用cgo时不开线程

703 views
Skip to first unread message

guagua

unread,
Sep 15, 2015, 12:26:46 PM9/15/15
to Golang-China
rt

minux

unread,
Sep 15, 2015, 2:31:13 PM9/15/15
to Golang-China

啥意思?

Phil Yang

unread,
Sep 16, 2015, 6:35:16 AM9/16/15
to golang...@googlegroups.com
估计是指 https://golang.org/pkg/runtime/debug/#SetMaxThreads 这里提到的thread吧

在 2015年9月16日 上午2:31,minux <mi...@golang.org>写道:

啥意思?

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛上的“Golang-China”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到golang-china...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/CAFK4q9ytF871OgMg3QmzDUL8QMRcfAV%2B2pvFnX6s24E12DFOOg%40mail.gmail.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Thanks,
Phil Yang

guagua

unread,
Sep 16, 2015, 10:04:05 AM9/16/15
to Golang-China
是的,cgo调用C函数不是简单的压栈call,而是它将当前的goroutine附加到一个操作系统线程来运行,这样的话,如果这个C函数是正则表达式等cpu密集型(且调用时间很短)的函数,那么启新的线程的做法就得不偿失了。我有没有说错?

在 2015年9月16日星期三 UTC+8下午6:35:16,Phil Yang写道:
估计是指 https://golang.org/pkg/runtime/debug/#SetMaxThreads 这里提到的thread吧

在 2015年9月16日 上午2:31,minux <mi...@golang.org>写道:

啥意思?

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛上的“Golang-China”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到golang-china+unsubscribe@googlegroups.com



--
Thanks,
Phil Yang

Phil Yang

unread,
Sep 16, 2015, 11:29:29 PM9/16/15
to golang...@googlegroups.com
个人感觉其实还好?因为系统调用也是这样干的,网络读写啥的也都会这样。反而是如果调用cgo函数执行的时间很长&&开的goroutine很多,会导致thread很多甚至crash

在 2015年9月16日 下午10:04,guagua <bette...@gmail.com>写道:
是的,cgo调用C函数不是简单的压栈call,而是它将当前的goroutine附加到一个操作系统线程来运行,这样的话,如果这个C函数是正则表达式等cpu密集型(且调用时间很短)的函数,那么启新的线程的做法就得不偿失了。我有没有说错?

在 2015年9月16日星期三 UTC+8下午6:35:16,Phil Yang写道:
估计是指 https://golang.org/pkg/runtime/debug/#SetMaxThreads 这里提到的thread吧

在 2015年9月16日 上午2:31,minux <mi...@golang.org>写道:

啥意思?

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛上的“Golang-China”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到golang-china...@googlegroups.com



--
Thanks,
Phil Yang

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛上的“Golang-China”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到golang-china...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/9b635b3f-1ada-4ce4-a956-2132ac70ea1d%40googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
Thanks,
Phil Yang

minux

unread,
Sep 17, 2015, 12:45:27 AM9/17/15
to Golang-China
2015-09-16 10:04 GMT-04:00 guagua <bette...@gmail.com>:
是的,cgo调用C函数不是简单的压栈call,而是它将当前的goroutine附加到一个操作系统线程来运行,这样的话,如果这个C函数是正则表达式等cpu密集型(且调用时间很短)的函数,那么启新的线程的做法就得不偿失了。我有没有说错?

这个理解是错的。goroutine 只要在运行,就一定是在某一个操作系统线程上。不存在说
goroutine 可以独立于操作系统线程而运行。所以进行 cgo 调用的时候没有所谓”将当前
goroutine 附加到一个操作系统来运行“ 这么一个步骤。

cgo 调用就是用当前 goroutine 所在的操作系统线程上运行的,不会涉及到切换到别的线
程上运行的问题的。

但是,类似阻塞的系统调用,cgo 调用会占用一个操作系统线程,可能使得用于运行 goroutine
的可用线程数量少于 GOMAXPROCS,此时 runtime 会创建一个新的操作系统线程来运行
已有的 goroutine,来满足运行 Go 代码的可用系统线程是 GOMAXPROCS 个。

所以,cgo 调用造成系统线程数过多的本质原因是并发的 cgo 调用过多。解决的办法并不
是找什么”调用cgo时不开线程“的办法,而是限制并发的 cgo 调用数。至于怎么限制,则
具体情况具体分析。一般来说,batching 是一个办法,也就是把多个 cgo 调用集中在一起
调用。比如 OpenGL 的 binding 基本都用这个办法,同时也能均摊 cgo 调用的开销。

minux

unread,
Sep 17, 2015, 1:41:40 AM9/17/15
to Golang-China


2015-09-16 23:29 GMT-04:00 Phil Yang <ud1...@gmail.com>:
> 个人感觉其实还好?因为系统调用也是这样干的,网络读写啥的也都会这样。反而是如果调用cgo函数执行的时间很长&&开的goroutine很多,会导致thread很多甚至crash

非阻塞模式(默认情况)的网络读写不会造成浪费操作系统线程,因为 runtime 会自动用 epoll 来等待网络 I/O 就绪。

Shell Xu

unread,
Sep 17, 2015, 2:25:44 AM9/17/15
to golang...@googlegroups.com
在我们这里,主要的调用线程开销在文件IO上。因为文件IO量很大,最后就很容易因为抖动而阻塞,进而引发load升高。
其实这也没有办法,并发式IO似乎只有aio和多上下文两个办法,而前者谁和我说过有个什么大坑来着。

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛上的“Golang-China”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到golang-china...@googlegroups.com



--
彼節者有間,而刀刃者無厚;以無厚入有間,恢恢乎其於游刃必有餘地矣。
blog: http://shell909090.org/blog/

minux

unread,
Sep 17, 2015, 2:37:14 AM9/17/15
to Golang-China
2015-09-17 2:25 GMT-04:00 Shell Xu <shell...@gmail.com>:
在我们这里,主要的调用线程开销在文件IO上。因为文件IO量很大,最后就很容易因为抖动而阻塞,进而引发load升高。
其实这也没有办法,并发式IO似乎只有aio和多上下文两个办法,而前者谁和我说过有个什么大坑来着。

Linux 没有真正的 aio(确切地说,O_DIRECT 打开的块设备文件支持真正的
异步 I/O,但是大多数文件系统都不支持)。又由于文件 I/O 也不能用 epoll
等机制。唯一的办法就是限制并发(实际上,限制并发对于文件系统也好的,
除了特地支持超高并发的文件系统[XFS],你适当限制并发也可以提高系统性
能)。

Shell Xu

unread,
Sep 17, 2015, 2:59:14 AM9/17/15
to golang...@googlegroups.com
其实有。linux在内核中导出了很多aio函数,但是libc没封装。
但是坑很多,不要用。。。

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛上的“Golang-China”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到golang-china...@googlegroups.com

minux

unread,
Sep 17, 2015, 3:07:32 AM9/17/15
to Golang-China
2015-09-17 2:58 GMT-04:00 Shell Xu <shell...@gmail.com>:
其实有。linux在内核中导出了很多aio函数,但是libc没封装。
但是坑很多,不要用。。。

aio_* syscalls 是有呀,不在 libc 里,在 libaio 里。文件系统不支持就是最大的坑啊。
Message has been deleted

guagua

unread,
Sep 17, 2015, 12:18:07 PM9/17/15
to Golang-China
你的意思是 cgo调用会占用一个操作系统线程,但如果当前可用系统线程等于GOMAXPROCS,runtime也不会创建新的线程?

在 2015年9月17日星期四 UTC+8下午12:45:27,minux写道:

minux

unread,
Sep 17, 2015, 2:45:59 PM9/17/15
to Golang-China


On Sep 17, 2015 11:46 AM, "guagua" <bette...@gmail.com> wrote:
> 正如你所说的,“cgo 调用会占用一个操作系统线程,此时 runtime 会创建一个新的操作系统线程来运行
> 已有的 goroutine” 也就是说cgo的调用始终会创建一个新的操作系统线程,那么频繁调用cgo岂不是很耗费系统资源?
> 对于一些短暂的cgo调用,是否可以像普通函数调用一样呢?

唉,写那么多白写了。

我说的是,如果可用(来运行goroutine的)线程不够GOMAXPROCS了,才创建新线程。不一定每次cgo调用都创建新线程的。

你要限制__并发__的cgo调用的数量,就能保证总线程数不上升。

另外,短暂的 cgo 调用极不划算,要么用 Go 重写要么 batching。

Reply all
Reply to author
Forward
0 new messages