Tornado 中 PyMongo Motor MongoEngine 的性能測試


最近在使用 Tornado 開發 API,數據庫選擇了 MongoDB,因為想使用 Geo 搜索的特性。Python 可供選擇的 MongoDB Drivers 可以在官網查找

在這些 Drivers 中,GitHub 上 Star 數最多的有 3 個:

Motor 和 MongoEngine 都是基於 PyMongo,Motor 的最新版是基於 PyMongo 2.8,Motor 的優勢就在於異步,而 PyMongo 在 2.2 以后的版本,就開始支持 gevent。

MongoEngine 借鑒了 Django 的 ORM,提供了一個 ORM-like layer,官方稱作 Document-Object Mapper,可以像使用 Django 的 ORM 一樣,簡單的操作和處理數據。

面對這么多選擇,就想探究這些選擇都有哪些特點,性能如何,所以有了這篇文章。你可以在這里找到所有的測試代碼和測試數據

https://github.com/restran/tornado-mongodb-performance-test

HTTP 性能測試工具

HTTP 性能測試工具可以選擇:

這里的測試使用 ab,安裝方法

sudo apt-get install apache2-utils

測試配置

測試的配置如下

  • Tornado 程序位於一台 Ubuntu 14.04 x86_64 的虛擬機,2 GB 內存,2 核心 CPU,2.59 GHz。
  • MongoDB 3.06 x86_64 Windows 版,在一台 Windows 2008 R2 的虛擬機,4 GB 內存,2 核心 CPU,2.39 GHz。
  • MongoDB 數據庫中已經預先插入 100W 條數據,以下所有的實驗都是測試從數據庫中讀數據的性能。
  • Tornado 使用最新的 4.2.1 版。

數據庫中的數據是這個樣子的

{
    "_id": {
        "$oid": "5630cd05f7732b28a81f57fa"
    }, 
    "title": "Post title", 
    "created": {
        "$date": "2015-10-28T21:26:29.271+0000"
    }
}

Tornado 中查詢數據的 Handler 是這個樣子的,以 PyMongo 3.0 為例。

class QueryHandler(APIHandler):
    def get(self):
        cursor = self.database.post.find(limit=30)
        json_data = []
        for t in cursor:
            j = {
               '_id': text_type(t['_id']),
               'title': t['title'],
               'created': t['created'].strftime('%Y-%m-%d %H:%M:%S') 
               if t['created'] else None
            }
            json_data.append(j)

        self.success(json_data)

測試說明

在實際測試的時候,發現在 PyMongo 2.8 的環境下,PyMongo 2.8 和 MongoEngine 性能都很差,因此設置了兩組測試。

測試 1

總共 10000 個請求,每次並發 100 個(同時發送 100 個),使用如下命令

ab -n 10000 -c 100 http://127.0.0.1:8500/api/posts/query/

實驗對象:

  • Motor(Mortor 最新版是基於 PyMongo 2.8)
  • PyMongo 3.0
  • PyMongo 3.0 + gevent(PyMongo 支持 gevent)
  • MongoEngine + PyMongo 3.0

PyMongo 開啟 gevent 的方法,可以參考
https://api.mongodb.org/python/current/examples/gevent.html

測試 2

總共 100 個請求,每次並發 10 個(同時發送 10 個),使用如下命令

ab -n 100 -c 10 http://127.0.0.1:8500/api/posts/query/

實驗對象:

  • PyMongo 2.8
  • PyMongo 2.8 + gevent
  • MongoEngine + PyMongo 2.8

Virtualenv

由於要使用不同版本的 PyMongo,因此使用了 Virtualenv 來創建不同的環境。

Windows 環境下的 virtualenv,命令會有些不一樣,這里的命令適用於 Linux。

安裝

sudo pip install virtualenv

創建一個虛擬的 Python 環境

virtualenv env_name

創建測試需要的兩個環境

virtualenv pymongo2.8
virtualenv pymongo3.0

激活虛擬環境,安裝相應的包

cd pymongo2.8
source bin/activate
pip install pymongo==2.8.0 tornado mongoengine motor gevent

對虛擬環境 pymongo3.0 執行相應的操作

cd pymongo3.0
source bin/activate
pip install pymongo==3.0.6 tornado mongoengine gevent

用虛擬環境中的 Python 啟動 Tornado 程序

/path/to/pymongo2.8/bin/python pymongo2.8_app.py

測試結果

先給出兩組測試結果的數據:完成所有請求的耗時,吞吐量(每秒處理的請求數)

從測試的結果來看,Motor 的性能確實很好,gevent 幾乎沒有性能提升,PyMongo 2.8 的性能很差,MongoEngine 是在 PyMongo 的基礎上有封裝了一層,但是兩者性能相差不大。

Tornado 的單線程的,同步的數據庫 Driver 會將 Tornado 阻塞住,導致無法處理其他的請求。

最后給出一組數據,百分比請求的最大響應時間。下面這張圖,左邊坐標的單位是毫秒。例如 Motor 有 50% 的請求是在 376 毫秒內完成的。

PyMongo 2.8,PyMongo 2.8 + gevent,MongoEngine + PyMongo 2.8 三條線重疊在了一起,它們之間的性能相當。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM