02 Python 基礎教學03 Python 爬蟲教學10 所有文章

【Python教學】淺談 Concurrency Programming

Concurrency_Programming

一. 為什麼需要 Concurrency ?

簡單來說 Concurrency Programming 就是能在同一時刻做兩件以上事情的能力,例如使用不同 CPU 分別運行程式來提高效率 ,或是當程式在等待執行結果時 (如等待 request 請求),先執行其他程式函式 (Coroutine),把浪費的 CPU 週期充分利用!

我們來看看 Golang 開發者之一 Rob Pike 對 Concurrency 的定義:

Concurrency is about dealing with lots of things at once.
Parallelism is about doing lots of things at once.

Concurrency is not Parallelism – Rob Pike
  1. Concurrency 併發:Concurrency 的定義是指有同時處理多個任務的能力,也是廣義的並行。
  2. Parallelism 並行:在同一時間執行多個操作,而 Multi-processing 是一種實現並行性的方法。

了解了 Concurrency 與 Parallelism 的差異後,我們來看看 Python 是如何實現 Concurrency 的方法

二. Python 中實現 Concurrency 的方法

而在 Python 中實現 Concurrency 的方法有以下幾種:

  1. Multi-threading:
    【Python教學】淺談 Multi-processing & Multi-threading 使用方法
  2. Multi-processing:
    【Python教學】淺談 Multi-processing pool 使用方法
  3. Async IO:
    【Python教學】淺談 Coroutine 協程使用方法
Concurrency_vs_ Parallelism

三. 面對 I/O Bound 爬蟲問題選擇:

接下來我們會將爬取蝦皮商品頁共 54,870 頁,來執行 I/O Bound 的問題進行 Multi-threading、Multi-processing 和 Async IO 在執行時間上、記憶體和 CPU 負載進行比較。

▍執行程序時間比較

此次共爬取 54,870 頁面,關於 Coroutine 的 number 我們設定的是 Semaphore 信號來限制 Coroutine 的併發量,而關於 Multi-threading 和 Multi-processing 的 number 則是 pool 內的數量。

Multi-threading vs Multi-processing vs Async IO 詳細數字

可以看到 Coroutine 在 Semaphore 設定為 30 時,每秒爬取 1310 頁,總共花費 41 秒爬完設定的 54,870 頁。

而 Multi-threading pool 在設定為 90 時,增加 pool 數量來提升執行效率已接近趨緩,故測試 pool 數量最終停留在 90,成績為每秒爬取頁面 132 頁,總共花費 413 秒爬完 54,870 頁。

最後 Multi-processing pool 在設定為 90 時,增加 pool 數量來提升執行效率已接近趨緩,故測試 pool 數量最終停留在 90,成績為每秒爬取頁面 129 頁,共花費 423 秒爬完 54,870 頁。

Multi-threading vs Multi-processing vs Async IO 折線圖

在時間上相較下來 Coroutine (41秒) > Multi-threading pool (413秒)> Multi-processing pool (423秒),在比較執行時間這個環節上由 Coroutine 大勝。

▍記憶體和 Load average 負載比較

我們使用 htop 來進行這次的記憶體和 CPU 使用情況分析:


以上圖為例:
右邊區塊的 Load average 3.49 22.15 33.31 的三個數字分別代表了系統 1 分鐘、5 分鐘和 10 分鐘平均負載的情況。
而左邊區塊的 1 2 3 4 則顯示了目前 CPU 使用的百分比、Mem 代表記憶體和 Swp 為記憶體交換空間。

1.Multi-processing-pool (多處理程序池/多進程池)

當 Processing Pool 設定為 90 時,執行程式時可以看到:

  • Load average 近一分鐘平均負載為 129.71
  • Memory 記憶體為 4.76 G

2.Multi-threading-pool (多線池/多執行緒池)

當 Threading Pool 設定為 90 時,執行程式時可以看到:

  • Load average 近一分鐘平均負載為 21.66
  • Memory 記憶體為 4.40 G

3.Coroutine (協程/微線程)

當 Semaphore 設定為 30 時,執行程式時可以看到:

  • Load average 近一分鐘平均負載為 2.17
  • Memory 記憶體為 4.53 G

在 Load average 近一分鐘平均負載相較之下,Coroutine (2.17) < Multi-threading-pool (21.66) < Multi-processing-pool (129.71)

面對 I/O Bound 的爬蟲問題時,無疑的 Coroutine 相較其他兩者尤佳。

▍而關於更多有關 Coroutine 的操作可以參考以下文章:

最後~

▍回顧本篇我們介紹了的內容:

  • 為什麼需要 Concurrency
  • Python 中實現 Concurrency 的方法
  • 面對 I/O Bound 爬蟲問題選擇
    • 執行程序時間比較
    • 記憶體和 Load average 負載比較
      1. Multi-processing-pool (多處理程序池/多進程池)
      2. Multi-threading-pool (多線池/多執行緒池)
      3. Coroutine (協程/微線程)

▍關於與 Concurrency Programming 相關其他文章,可以參考:

那麼有關於【Python教學】淺談 Concurrency Programming 的介紹就到這邊告一個段落囉!有任何問題可以在以下留言~

有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!

在〈【Python教學】淺談 Concurrency Programming〉中有 1 則留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *