返回信息流Python慢那是有名的,我没少[黑它](https://bbs.byr.cn/#!article/Python/68)。计算型的任务可以比C和Java的程序[慢20倍以上](https://bbs.byr.cn/#!article/Python/68)!慢20倍以上!慢20倍以上!重要的事情要说三遍!
可这个Go程序竟然比Python还要慢!比Python还要慢!比Python还要慢!重要的事要说三遍!
Python: `gen.py`
```python
def adder():
sum = 0
while True:
v = (yield)
if v == -1:
break
sum += v
return sum
def main():
g = adder()
g.send(None) # Let it reach its first "yield"
for i in range(10000000):
g.send(i)
try:
g.send(-1)
except StopIteration as e:
sum = e.value
print("Sum is {}".format(sum))
if __name__=='__main__':
main()
```
Go: `goro.go`
```go
package main
import (
"fmt"
)
func adder(toAdder chan int64, fromAdder chan int64) {
var sum int64 = 0
for {
v := <-toAdder
if v == -1 {
break
}
sum += v
}
fromAdder <- sum
}
func main() {
toAdder := make(chan int64)
fromAdder := make(chan int64)
go adder(toAdder, fromAdder)
var i int64
for i = 0; i < 10000000; i++ {
toAdder <- i
}
toAdder <- -1
sum := <-fromAdder
fmt.Printf("Sum is %d\n", sum)
}
// vim: ts=8 sw=8 noet
```
运行:
```bash
$ time python gen.py
Sum is 49999995000000
python gen.py 2.32s user 0.00s system 99% cpu 2.330 total
$ go build goro.go
$ time ./goro
Sum is 49999995000000
./goro 3.22s user 0.06s system 103% cpu 3.160 total
```
额外信息:
```
$ go version
go version go1.6.2 linux/amd64
$ python --version
Python 3.5.1
$ cat /proc/cpuinfo | grep 'model name'
model name : Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
model name : Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
model name : Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
model name : Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
```
这是一条镜像帖。来源:北邮人论坛 / golang / #371同步于 2016/6/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Golang机器人发帖
「黑黑更健康」goroutine:这个程序比Python慢38%
nuanyangyang
2016/6/25镜像同步30 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
【 在 nuanyangyang 的大作中提到: 】
: 发现为什么这个go程序慢了吗?
chan的长度为1,导致这个执行是顺序的。只有adder取出来了,main才能接着往里写。
这算Go的一个坑吧
我验证一下
【 在 qyz0123321 的大作中提到: 】
: chan的长度为1,导致这个执行是顺序的。只有adder取出来了,main才能接着往里写。
: 这算Go的一个坑吧
: 我验证一下
是的。如果没有指定chan的buffer大小,默认是0,也就是不管是先发送还是先接收,先做的一定会阻塞,直到另一方也到来。
可是Python的程序也是顺序执行的啊。
【 在 nuanyangyang 的大作中提到: 】
:
: 是的。如果没有指定chan的buffer大小,默认是0,也就是不管是先发送还是先接收,先做的一定会阻塞,直到另一方也到来。
: 可是Python的程序也是顺序执行的啊。
测试了一下,可以断定是channel长度的问题,
```bash
$ time python3 gen.py
Sum is 49999995000000
python3 gen.py 2.21s user 0.02s system 98% cpu 2.255 total
$ go build goro.go
$ time ./goro
Sum is 49999995000000
./goro 2.38s user 0.10s system 103% cpu 2.389 total
```
给channel加上buffer之后就好很多了,这个是给channel加上200的长度之后,时间已经和python差不多。长度增大到500和1000的时候,只要0.8s就搞定了。感觉上是Golang的线程在进行线程调度的时候有问题。
奇怪的是,增大buffer长度之后,执行时间反而下来了。。难道是分配buffer占用了过多的时间。
------
额,不是线程。。写错了。。
【 在 asm 的大作中提到: 】
: 1. go程序中channel没有使用buffered channel
嗯。这是一个问题。如果buffer大小大一些,比如100,就会比python快了。但是,也快不了多少。Python要2.5秒的,Go最快也要1秒。Python对计算型任务可是比C慢20倍的哦,Go比Python快2.5倍一点也算不上出色。
: 2. go的channel是线程安全的,python的yield不是线程安全的吧
python的yield根本不是多线程的。它是coroutine,也就是同一个线程在两个作业之间来回切换。
是的,所以python的yield不是线程安全的吧,但是channel是线程安全的,可以跑在多核多线程上。我猜是因为有锁的资源消耗吧。
【 在 nuanyangyang 的大作中提到: 】
:
: 嗯。这是一个问题。如果buffer大小大一些,比如100,就会比python快了。但是,也快不了多少。Python要2.5秒的,Go最快也要1秒。Python对计算型任务可是比C慢20倍的哦,Go比Python快2.5倍一点也算不上出色。
:
: ...................
go的运行效率测试可以参考这里:
http://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=go&lang2=gcc
这个里的测试更加全面些