原文
大家好,我重构和优化
了一下jin.go
这里:
我去掉了vibe.d
依赖,因为它又慢又大
,而且我无法与2版本
交朋友.当仅运行1000
个vibe
纤程时,不仅应用崩溃
,甚至图形系统驱动
也崩溃一次,这需要重启笔记本电脑.
当前,我用小栈大小
的本地流(4kb
)解决.
我真很期待photon
的稳定性,以恢复支持纤程
.如果在标准库
中看到它,那真是太棒了.
我不得不丢弃移动语义
,因为我无法用闭包
.当前,由复制构造器
控制队列的引用数
.
好消息!经过所有优化
后,通道
在上述基准测试
中显示出令人印象深刻的速度
,来在两个流
间泵送消息
.
import std.datetime.stopwatch;
import std.range;
import std.stdio;
import jin.go;
const long n = 100_000_000;
auto threadProducer() {
return n.iota;
}
void main() {
auto queue = go!threadProducer;
StopWatch sw;
sw.start();
long sum = 0;
foreach (p; queue) {
sum += p;
}
sw.stop();
writefln("received %d messages in %d msec sum=%d speed=%d msg/msec", n,
sw.peek.total!"msecs", sum, n / sw.peek.total!"msecs");
assert(sum == (n * (n - 1) / 2));
}
在718
毫秒内收到100000000
条消息sum=4999999950000000,speed=139275msg/msec
我几乎在goroutines
基准测试中赶上了Go
:
> go run app.go -release
工作者结果时间
849995000000109.7644
毫秒
> dub -quiet -build=release
工作者结果时间
049995000000124
毫秒
坏消息.有时结果错误
,我不知道为什么.
> dub -quiet -build=release
工作者结果时间
049945005000176
毫秒
我使用了原子获取
和释放
操作,尽管它们在x86
上不必,但我希望编译器考虑它们
且不要重排指令
.但即使有更严格的内存栅
,我也没有得到非常稳定的结果
.
如果有人能告诉我这里可能原因,我将不胜感激.
这里
并发的put
和popFront
不能避免队列
中的竞争.
单独访问_offset
是原子
的,但它在put
和popFront
中的使用点
都不是原子的
.
这两个函数
都如下:
1,原子读偏移
2,干活
3,原子写偏移
如果一个函数
完成了1
,然后另一个函数
完成了1+2+3
,则你就会得到一个竞争
.
链接两个原子对象
并不会按整体原子化这两个
,这是典型的互斥错误
.