假设事件循环里有一百万个可等待对象,其中一万个可以继续进行了,其他的仍然在等待。那么如何让这一万对象按照优先级顺序顺序执行?
我猜测要从 asyncio 源码下手,有没有读过源码的大佬给个大概的可入手的地方,比如事件循环是在哪里遍历对象判断可执行的?或者有现成的仓库?(谷歌、必应、百度过,没搜到,所以我猜大概率没有,就算有,也是藏得很深的)
1
wellsc 2020-12-09 15:19:55 +08:00
|
2
abersheeran OP @wellsc 我想问的是优先级,而不是命名。
|
3
ruanimal 2020-12-09 15:29:51 +08:00
@abersheeran 把任务放优先队列里就行了
|
4
BBrother 2020-12-09 15:32:00 +08:00
可不可以全局维护一个优先级表,每个 task 执行前先查询优先级,如果不是最高的,就再把自己加入到事件循环中?
|
5
geebos 2020-12-09 15:34:29 +08:00
自定义一个 eventloop,在 task 类上添加一个优先级,在 select 的时候把准备好的任务添加到优先队列里再执行,但是感觉性能不太好。我建议分几个优先级,不同优先级有执行顺序,相同优先级的按到达顺序执行,这样在选取的时候遍历一遍就可以。
|
6
wellsc 2020-12-09 15:40:31 +08:00 via iPhone
@abersheeran 按照命名排序不就好了
|
7
abersheeran OP 不回复以上回复,是因为我不想开口骂人。
有没有真正 hack 过 asyncio 事件循环的大佬能给点具体的建议? |
8
BBCCBB 2020-12-09 16:27:38 +08:00
每个对象加一个 condition?
然后后一个对象等待前一个对象的 condition signal. 看看这样可不可行 |
9
BBCCBB 2020-12-09 16:28:28 +08:00
或者楼上说的放优先队列里一个一个拿出来跑也没问题呀.
|
10
abersheeran OP @BBCCBB 问题里我觉得我问的很明确了,我想要的是具体的入手点或者现有的库,而不是思路。优先级队列这种入门级的思路,我也能想到啊,关键是这个队列放在哪?在哪里把元素放进去?事件循环里哪个 API 可以用来 hack 这种操作?我想要的是这些。
|
11
BBCCBB 2020-12-09 16:58:56 +08:00
当我没说.
假设事件循环里有一百万个可等待对象,其中一万个可以继续进行了,其他的仍然在等待。那么如何让这一万对象按照优先级顺序顺序执行? 大家回答的你第一个问题. |
12
hgrx 2020-12-09 16:59:21 +08:00
不想骂人可还行,在论坛发了这个帖子这个帖子就是你家了?别人不能进来谈一下看法?你只是发起了一个讨论,你没有拥有这个帖子,你也没资格指责别人怎么不如你意了
|
13
abersheeran OP |
15
se77en 2020-12-09 20:23:16 +08:00
asyncio.wait 有个 return_when 参数,可以参考一下这个 https://stackoverflow.com/a/48567863/2050626
|
16
abersheeran OP @se77en 谢谢,这个我也搜到了。不过它这个并没有真的实现一个按照优先级执行的事件循环。
这个问题我打算给它沉掉,有一个看过源码的大佬说这个搞不定,没有对应的 API 。符合我最开始的推断,只能像 trio 一样重写一套,成本太高了。唉。不过还是谢谢你花时间帮我搜答案。 |
17
linw1995 2020-12-10 11:27:55 +08:00 2
1. 让各个 asyncio.Task 带上优先级
可以通过 loop.set_task_factory 让各个 coroutines 有优先级,可以不修改 Task 对象,优先级存在 context 里就好了。这样其产生的新 task 可以继承这个优先级 2. 修改 loop._run_once 使其按优先级执行(不行) _run_once 是在跑一个个 callbacks,所以没法用来使 asyncio.Task 按优先级执行 所以就只能在 asyncio.Task.__step 这里搞幺蛾子了,维持一个全局的优先级堆,执行 __step 先检查一下自己的优先级在不在堆顶,看该不该继续执行,不该就重新 call_soon 。 按这个思路应该可以搞起来 |
18
abersheeran OP @linw1995 这样就是在 asyncio 里,手动创建一个由 Task 作为基本单位的带优先级的事件循环。看起来可行!感谢!
这个思路我是真没想到,不需要去走 loop 的接口,只要调整 Task,保证每个可等待对象都被 Task 包装起来就行了。太有意思了。是我之前的想法钻牛角尖了😭 |
19
joApioVVx4M4X6Rf 2021-07-21 19:12:19 +08:00
请问后来解决了吗?怎么解决的?
|