免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9715 | 回复: 16
打印 上一主题 下一主题

Coro如何动态的创建新协程? [复制链接]

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-08-03 22:31 |只看该作者 |倒序浏览
我刚接触Coro和AnyEvent::HTTP。原理方面还不是很懂,故请教:

网上看到很多例子都是直接for(1..1000)这样直接创建运行全部协程,最多用Coro::Semaphore让几个先跑。

现在,我想在for(1..10000)循环里每次创建完一个协程的时候就$coro->ready,这样让出当前的协程给其他跑(比如用AnyEvent::HTTP的WEB请求)。然后等这些IO非阻塞的协程处理完,再回主程序创建剩余协程。

请问,该方案可行吗?底层的细节又是怎样的?

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
2 [报告]
发表于 2013-08-04 08:37 |只看该作者
本帖最后由 laputa73 于 2013-08-04 09:00 编辑

协程可以自动切换cede,也可以手动切换cede to.,可以自动调度shedule,也可以同步等待join
async=new+ready
coro还是要靠自己多写程序测试.
原理可以看py发的中文入门文档
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3759030

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
3 [报告]
发表于 2013-08-04 14:30 |只看该作者
  1. #!/usr/bin/perl
  2. use strict;
  3. use Coro;
  4. use AnyEvent::HTTP;

  5. my @coro;
  6. for (1..10000){
  7.    push @coro, async {
  8.       http_get 'http://www.baidu.com', cb => Coro::rouse_cb;  
  9.       my @res = Coro::rouse_wait;  
  10.    }
  11. }
复制代码
上面的代码一次创建了10000个异步执行块,然后根据Coro的调度机制执行。

我在想有没有不是一次性创建10000个执行块的方法,而是根据当前IO吞吐流量的自动创建足够适量的执行块。

我目前想到的方式是:
  1. #!/usr/bin/perl
  2. use strict;
  3. use Coro;
  4. use AnyEvent::HTTP;

  5. my @coro;
  6. for (1..10000){
  7.    push @coro, async {
  8.       http_get 'http://www.baidu.com', cb => Coro::rouse_cb;  
  9.       my @res = Coro::rouse_wait;  
  10.       cede;#没创建一个异步执行块就将让出当前的CPU资源,等待调度执行完其他程序块,然后继续创建新异步程序块。
  11.    }
  12. }
复制代码
可能这样放上代码能更加清楚的说明我的问题。

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
4 [报告]
发表于 2013-08-04 18:53 |只看该作者
本帖最后由 laputa73 于 2013-08-04 19:02 编辑

不明白的你的想法.
你是觉得一次10000个并发太多吗?
那就限制一下并发不就好了?
  1. use Coro;
  2. use AnyEvent::Ping;

  3. my $cocurrent = 100;    # 并发数
  4. my @todoList = map { "192.168.6." . $_ } (1 .. 254); #

  5. my @coro;
  6. my $ping = AnyEvent::Ping->new;

  7. doit() foreach 1..$cocurrent;
  8. sub doit{
  9.     my $ip = shift @todoList;
  10.     return if not defined $ip;
  11.          push @coro, async {
  12.             $ping->ping($ip, 1, Coro::rouse_cb );
  13.              my @result = Coro::rouse_wait;
  14.              print "Result($ip): ", $result[0][0][0]," in ", $result[0][0][1], " seconds\n";
  15.               doit();
  16.          }     
  17. }


复制代码

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
5 [报告]
发表于 2013-08-04 20:17 |只看该作者
  1. doit() foreach 1..$cocurrent;
复制代码
是这里做了限制吗?那$cocurrent(100)以后的IP怎么去Ping呢?
还有doit()里面调用doit()自己是什么意思?
我感觉用Coro::Semaphore做限制正规点。

我的意思是如何在网络阻塞的时候少创建点并发,在网络状况比较流畅的时候多创点并发。

不知道是否能用Coro的调度机制去实现?

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
6 [报告]
发表于 2013-08-04 20:28 |只看该作者
本帖最后由 laputa73 于 2013-08-04 20:41 编辑

你可以转换一下思路,预先创建好协程,需要时才调度
变为需要时才创建协程

以一定的并发去抓取网页.
网络好就做得快点,网络差就做得慢点
尽量不要自己去干涉协程调度.

协程要做得就是从任务队列里面取任务
my $ip = shift @todoList;
然后再递归创建新的协程


论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
7 [报告]
发表于 2013-08-04 20:32 |只看该作者
laputa73 发表于 2013-08-04 20:28
以一定的并发去抓取网页.
网络好就做得快点,网络差就做得慢点
尽量不要自己去干涉协程调度.


那就是手动控制咯?我就是再自动的方法。

laputa73 发表于 2013-08-04 20:28
协程要做得就是从任务队列里面取任务
my $ip = shift @todoList;
然后再迭代新的协程


那你这样写的话,最后是怎样控制住并发的数量的呢?

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
8 [报告]
发表于 2013-08-04 20:44 |只看该作者
例子都给你了.
你自己把ping的改成http的试试看呗
把你的10000个url放到todolist里面去就ok.

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
9 [报告]
发表于 2013-08-04 21:09 |只看该作者
  1. #!/usr/bin/perl
  2. use Coro;
  3. use AnyEvent::HTTP;

  4. my $cocurrent = 100;
  5. my @todoList = ('http://www.baidu.com') x 1000;

  6. my @coro;
  7. my $i=1;

  8. doit() foreach 1..$cocurrent;
  9. sub doit{
  10.     my $url = shift @todoList;
  11.     return if not defined $url;
  12.     push @coro, async {
  13.         http_get $url, cb => Coro::rouse_cb;
  14.         print "开始并发$i...\n";
  15.         my @res = Coro::rouse_wait;
  16.         print "$i返回结果$res[1]->{Status}\n";
  17.         $i++;
  18.         doit();
  19.     }
  20. }
  21. $_->join foreach @coro;
复制代码
你确认这样写能控制并发?我觉得不能。

无论是用Coro::Semaphore还是for (1..100){while(){async{}}}都比这个好吧。

论坛徽章:
1
白羊座
日期:2013-11-09 20:03:00
10 [报告]
发表于 2013-08-04 22:20 |只看该作者
  1. #!/usr/bin/perl
  2. use Coro;
  3. use AnyEvent::HTTP;

  4. my @coro;

  5. foreach my $i (1..1000){
  6.     push @coro, async{
  7.         http_get 'http://www.baidu.com', cb => Coro::rouse_cb;
  8.         print "开始并发$i...\n";
  9.         my @res = Coro::rouse_wait;
  10.         print "$i返回结果$res[1]->{Status}\n";
  11.     };
  12.     cede;#请问这里跳转了吗?
  13. }
  14. $_->join foreach @coro;
复制代码
请问cede这里跳转了吗?为什么程序还是顺序返回了?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP