bri*_*foy 8 multithreading perl6 promise
这是一个有点滑稽的标题,但在玩Promises时,我想看看我能在多大程度上延伸这个想法.在这个程序中,我这样做,所以我可以指定我想要做多少个承诺.
我有两个问题,真的.
程序如何知道它可以创建多少个线程?这比承诺的数量略多,因为这是值得的.
我怎么知道我应该允许多少线程,即使我可以赚更多?
这是我小小的Macbook Air上的Rakudo 2017.01,有4个核心:
my $threads = @*ARGS[0] // %*ENV<RAKUDO_MAX_THREADS> // 1;
put "There are $threads threads";
my $channel = Channel.new;
# start some promises
my @promises;
for 1 .. $threads {
@promises.push: start {
react {
whenever $channel -> $i {
say "Thread {$*THREAD.id} got $i";
}
}
}
}
put "Done making threads";
for ^100 { $channel.send( $_ ) }
put "Done sending";
$channel.close;
await |@promises;
put "Done!";
Run Code Online (Sandbox Code Playgroud)
Jon*_*ton 11
这实际上不是关于Promise
本身,而是关于线程池调度程序.一个Promise
本身只是一个同步结构.该start
构造实际上做了两件事:
$_
,$/
以及$!
该块的内Promise.start
用该块调用还有Promise.start
两件事:
Promise
Promise
和异常中断Promise
.拥有Promise
不受线程池上代码支持的对象不仅可能,而且相对常见.Promise.in
,Promise.anyof
和Promise.allof
工厂不马上安排任何事情,并且有各种的用途Promise
,涉及做Promise.new
,然后调用keep
或break
以后.所以我可以轻松创建并await
在1000 Promise
秒:
my @p = Promise.new xx 1000;
start { sleep 1; .keep for @p };
await @p;
say 'done' # completes, no trouble
Run Code Online (Sandbox Code Playgroud)
同样,a Promise
不是唯一可以在其上安排代码的东西ThreadPoolScheduler
.返回的许多东西Supply
(如间隔,文件监视,异步套接字,异步进程)都在那里安排它们的回调.通过执行可以将代码抛到那里,$*SCHEDULER.cue: { ... }
即使你知道结果或任何错误,所以它并不是特别常见.
当前的Perl 6线程池调度程序具有可配置但强制执行的上限,默认为16个线程.如果您创建了一个所有16个都被占用但无法取得进展的情况,并且唯一可以取得进展的事情就是卡在工作队列中,那么就会发生死锁.这对于Perl 6线程池来说并不是唯一的.任何有界池都将容易受到攻击(并且任何无界池都将容易耗尽所有资源并使进程死亡:-)).
正如另一篇文章所述,Perl 6.d将制作await
和react
非阻塞结构; 这一直是计划,但没有足够的开发资源及时实现Perl 6.c. 该use v6.d.PREVIEW
pragma提供了对此功能的早期访问.(另外,公平警告,这是一项正在进行中的工作.)这样做的结果是线程池拥有的一个await
或react
一个线程将暂停执行预定代码(对于那些好奇的,通过继续)并允许进一步工作的线索.当等待的事情完成或react
块得到时,将安排恢复代码done
.请注意,这意味着你可以在不同的操作系统线程前后await
或react
在6.d. (大多数Perl 6用户不需要关心这一点.它主要与那些编写C语言绑定或处理系统的东西相关.而且一个好的C库绑定将使得绑定的用户没有照顾.)
即将到来的6.d更改并没有消除耗尽线程池的可能性,但这意味着你可以在6.c中做的一系列方法将不再受到关注(注意,编写递归征服/划分事物)该await
分开的部分,或具有数以千计的活性的结果与反应推出块start react { ... }
).
展望未来,线程池调度程序本身也将变得更加智能.接下来是猜测,虽然我可能会实施这些变化,但这可能是最好的推测.:-)线程池将在进行进度后开始,并使用它来动态调整池大小.这将包括注意到没有进展,并结合工作队列包含项目的观察,添加线程以尝试解决死锁 - 以增加线程的内存开销为代价.今天线程池保守地倾向于产生最大尺寸,即使这不是一个特别理想的选择; 最有可能使用某种爬山算法来尝试确定最佳数量.一旦发生这种情况,可以大大提高默认的max_threads,这样就可以完成更多的程序 - 以一堆内存开销为代价 - 但大多数程序只运行一些线程.
快速修复,添加use v6.d.PREVIEW;
第一行.
这解决了许多线程耗尽问题.
我添加了一些其他更改$*SCHEDULER.max_threads
,并添加了Promise"id",以便很容易看出Thread ID不一定与给定的Promise相关联.
#! /usr/bin/env perl6
use v6.d.PREVIEW; # <--
my $threads = @*ARGS[0] // $*SCHEDULER.max_threads;
put "There are $threads threads";
my $channel = Channel.new;
# start some promises
my @promises;
for 1 .. $threads {
@promises.push: start {
react {
whenever $channel -> $i {
say "Thread $*THREAD.id() ($_) got $i";
}
}
}
}
put "Done making threads";
for ^100 { $channel.send( $_ ) }
put "Done sending";
$channel.close;
await @promises;
put "Done!";
Run Code Online (Sandbox Code Playgroud)
There are 16 threads
Done making threads
Thread 4 (14) got 0
Thread 4 (14) got 1
Thread 8 (8) got 3
Thread 10 (6) got 4
Thread 6 (1) got 5
Thread 16 (5) got 2
Thread 3 (16) got 7
Thread 7 (8) got 8
Thread 7 (9) got 9
Thread 5 (3) got 6
Thread 3 (6) got 10
Thread 11 (2) got 11
Thread 14 (5) got 12
Thread 4 (16) got 13
Thread 16 (15) got 14 # <<
Thread 13 (11) got 15
Thread 4 (15) got 16 # <<
Thread 4 (15) got 17 # <<
Thread 4 (15) got 18 # <<
Thread 11 (15) got 19 # <<
Thread 13 (15) got 20 # <<
Thread 3 (15) got 21 # <<
Thread 9 (13) got 22
Thread 18 (15) got 23 # <<
Thread 18 (15) got 24 # <<
Thread 8 (13) got 25
Thread 7 (15) got 26 # <<
Thread 3 (15) got 27 # <<
Thread 7 (15) got 28 # <<
Thread 8 (15) got 29 # <<
Thread 13 (13) got 30
Thread 14 (13) got 31
Thread 8 (13) got 32
Thread 6 (13) got 33
Thread 9 (15) got 34 # <<
Thread 13 (15) got 35 # <<
Thread 9 (15) got 36 # <<
Thread 16 (15) got 37 # <<
Thread 3 (15) got 38 # <<
Thread 18 (13) got 39
Thread 3 (15) got 40 # <<
Thread 7 (14) got 41
Thread 12 (15) got 42 # <<
Thread 15 (15) got 43 # <<
Thread 4 (1) got 44
Thread 11 (1) got 45
Thread 7 (15) got 46 # <<
Thread 8 (15) got 47 # <<
Thread 7 (15) got 48 # <<
Thread 17 (15) got 49 # <<
Thread 10 (10) got 50
Thread 10 (15) got 51 # <<
Thread 11 (14) got 52
Thread 6 (8) got 53
Thread 5 (13) got 54
Thread 11 (15) got 55 # <<
Thread 11 (13) got 56
Thread 3 (13) got 57
Thread 7 (13) got 58
Thread 16 (16) got 59
Thread 5 (15) got 60 # <<
Thread 5 (15) got 61 # <<
Thread 6 (15) got 62 # <<
Thread 5 (15) got 63 # <<
Thread 5 (15) got 64 # <<
Thread 17 (11) got 65
Thread 15 (15) got 66 # <<
Thread 17 (15) got 67 # <<
Thread 11 (13) got 68
Thread 10 (15) got 69 # <<
Thread 3 (15) got 70 # <<
Thread 11 (15) got 71 # <<
Thread 6 (15) got 72 # <<
Thread 16 (13) got 73
Thread 6 (13) got 74
Thread 17 (15) got 75 # <<
Thread 4 (13) got 76
Thread 8 (13) got 77
Thread 12 (15) got 78 # <<
Thread 6 (11) got 79
Thread 3 (15) got 80 # <<
Thread 11 (13) got 81
Thread 7 (13) got 82
Thread 4 (15) got 83 # <<
Thread 7 (15) got 84 # <<
Thread 7 (15) got 85 # <<
Thread 10 (15) got 86 # <<
Thread 7 (15) got 87 # <<
Thread 12 (13) got 88
Thread 3 (13) got 89
Thread 18 (13) got 90
Thread 6 (13) got 91
Thread 18 (13) got 92
Thread 15 (15) got 93 # <<
Thread 16 (15) got 94 # <<
Thread 12 (15) got 95 # <<
Thread 17 (15) got 96 # <<
Thread 11 (13) got 97
Thread 15 (16) got 98
Thread 18 (7) got 99
Done sending
Done!
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
682 次 |
最近记录: |