簡體   English   中英

asyncio 的事件循環使用什么調度算法?

[英]What scheduling algorithm does asyncio's event loop use?

我查看了所有文檔,但找不到它。

假設完成了多個await調用,並且它們的協程都准備好恢復,那么asyncio的事件循環使用什么算法來決定恢復哪個協程?

1) 文檔向我們展示了事件循環以run_forever / run_until_complete開始。 我們需要找到函數的源代碼,看看接下來會發生什么。

2)最快的方法(我知道)是在github上搜索相關名稱。 轉到github.com/python/cpython ,使用左上角的搜索表單:

在此處輸入圖像描述

Github 將向您顯示項目中的所有事件。 確保在代碼中搜索:

在此處輸入圖像描述

3)我們需要實現,找到了其中的兩個: 一個在 ProactorEventLoop 內部,沒有發生任何有趣的事情,因為它部分地重新實現了父事件循環; BaseEventLoop 里面的一個,它似乎是我們要搜索的。

4)讓我們檢查一下代碼。 很快我們就會看到,一切都在while True循環中調用_run_once

try:
    events._set_running_loop(self)
    while True:
        self._run_once()
        if self._stopping:
            break

5)讓我們_run_once (我們可以在頁面上搜索def _run_once )。 這是恢復計划的事情的地方。 通過源代碼,您會看到兩個有趣的地方:

  • 符合event_list = self._selector.select(timeout) -這是 asyncio 休眠的地方,直到套接字上的活動。 您可以進一步閱讀文檔來研究此機制。 但是這個地方本身並沒有恢復協程。
  • 我們讀到的那一This is the only place where callbacks are actually *called*. All other places just add them to ready. This is the only place where callbacks are actually *called*. All other places just add them to ready.

正是我們搜索的內容。 您可以在那里閱讀源代碼(通常在_run_once函數內部)以查看回調是如何執行的,以及它們是如何添加到self._ready以執行的。 回調包括直接添加的回調和 asyncio 在內部用於恢復協程的回調。

您還可以重新實現事件循環來使用它。 看看這里的代碼,它包含事件循環重新實現的示例。


幾點注意事項:

  • 除非文檔中另有說明,否則具體算法是實現的細節,可以在 asyncio 版本之間更改。 你不應該依賴它。
  • 不同的事件循環可以實現不同的算法。 雖然所有 asyncio 的循環似乎都在BaseEventLoop中使用一個,但其他事件循環(如自定義uvloop)可能會做一些不同的事情。
  • 通常為了找到我在 PyCharm 中使用ctrl+click的東西的源代碼。 它比在 github 上搜索要快得多,也方便得多,但由於某種原因不能與 asyncio 一起使用。

如果您使用默認事件循環,python 3.10 中的 TLDR 准備恢復最長的協程將繼續。 但是,每次執行事件循環時只會檢查一次計時器(可能還有 io 事件)。


在內部BaseEventLoop保持一個雙端隊列self._ready包含所有准備好被調用的句柄。

句柄並不完全是協程,但與之相關。 實際上,asyncio.run 將協程包裝在任務中,任務基本上將協程拆分為多個步驟,其中一個步驟是需要執行的所有內容,以到達協程中的下一個點,將控制權交還給事件循環(這可能晚於下一個等待語句,因為並非所有等待語句都將控制權交還給事件循環)。 句柄只是 asyncio 引用需要執行的步驟的內部方式。

句柄的執行順序與它們放在_ready雙端隊列上的順序相同。 此順序取決於您的系統,並且在 Unix 上每次事件循環的迭代如下:

第一個。 自事件循環的上一次迭代以來,所有非 io、非基於計時器的句柄都按照這些准備就緒的順序准備就緒。

第二。 所有基於 io 的句柄都按照它們在上一次迭代准備就緒后由 Unix select 系統調用返回的順序排列。

第三。 所有基於計時器的句柄,其計時器已按順序用完。

我沒有檢查,但我相信在 Windows 上使用基於前攝器的事件循環時,您會發現上面的第 1 點和第 2 點將按照它們准備好的順序交錯。


Mikhail Gerasimov已經給出的詳細答案解釋了如何找出標准事件循環在任何給定 python 版本中所做的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM