SQL x 1, new object x N
從本機的資料庫取出大量資料 (>1m筆), 然後將結果寫入 /dev/null, 資料型別為 utf-8。結果如下:method | time (min / sec) | memory (G) |
---|---|---|
MySQL client | 0'08 | 0.54 |
python client | 1'02 | 1.4 |
django client without using iterator | 17'39 | 5.x |
django client using iterator | 3'16 | 1.7 |
django client using raw sql | 1'02 | 1.5 |
實驗細節說明:
- Django 1.2, MySQL 5.0。
- 用 time 測時間。
- memory 是我用眼睛注意 htop 的數據。django client without using iterator 跑太久了, 只好邊玩猴子守城四代邊跑實驗, 最大值就沒抓準了。
(2012-02-02 更新) 只需定時執行grep VmPeak /proc/PID/status | awk '{print $2}'
就不用「辛苦」地邊玩遊戲邊抓數據了。年輕時不懂事, 了解一些系統知識差異真大。 - MySQL client 的用法: mysql < my_select.sql > /dev/null。沒做 encoding 轉換。
- python client 的操作內容只有從 utf-8 轉成 unicode (MySQLdb 做的) 再轉回 utf-8, 補個換行字元, 就寫入檔案。
- django 會自動把 utf-8 轉成 unicode。django client 的操作和 python client 幾乎一樣。
至於 python 花了 mysql client 8 倍的時間, 只好當作用 python 的必要成本。不知其它語言 (C++、Java、Ruby、PHP) 這方面的額外負擔有多大。
為了弄清楚時間花在那裡, 另外試了 java client 和不轉 utf-8 的情況:
method | time (min / sec) | memory (G) |
---|---|---|
python client | 1'02 | 1.4 |
python client without encoding and decoding | 0'43 | |
java client (using mysql connector) | 0'51 | 1.1 |
看來轉換 utf-8 花了不少時間, 到是用 Java 也沒省下多少時間。有可能 python client 已幾乎都是 native code 了。
SQL x N, new object x N
我用 primary key (id = 1 ~ 100,000) 分別做 100,000 次操作取出 100,000 筆資料, 結果如下:method | time (min / sec) |
---|---|
django client | 1'26 |
django client using raw sql | 0'20 |
實驗細節說明:
- django client 用 get(id=ID)。
- raw sql 用 where id = ID。
相關討論
這篇提到取出「大量」資料時的解法, 可以拆成多個 SQL 分次用 primary key 取出。留言裡有提到不要用 slicing (即 MySQL 的 offset + limit), DBMS 會取出大量資料再丟掉 limit 量之外的資料, 效率很差。我以為 offset 會一次取到對的資料, 一開始跑實驗時用 offset 沒用 primary key, 結果瓶頸變 IO, 反而沒測出 ORM 的額外負擔。 上面提的作法可以解掉 memory 的問題。但若資料量更大, 要跑得更快時, 還是得用 raw SQL。不過這也不表示資料量大就要用 raw SQL, 得看應用場合。若瓶頸在其它地方, 用 raw SQL 只會省掉整體的 1/10 時間, 用 ORM 也不壞, 方便日後維護。
1. "至於 python 花了 mysql client 8 倍的時間, 只好當作用 python 的必要成本。
回覆刪除If this is CPU bound, installing debug packages and using a profiler like 'oprofile' will give more insight.
If CPU time is mostly spent on:
utf8 -> UCS4 -> utf8
it should be fairly apparent from the profiler call chain output.
2. "memory 是我用眼睛注意 htop 的數據。"
... orz
And people wonder why userspace system programming skills is useful?
On a Linux desktop machine with the Gnome desktop environment, do this:
yum -y install gnome-python2-libgtop2
ipython
In [1]: import subprocess
In [2]: import gtop
In [3]: p = subprocess.Popen(['my-test-program'])
In [4]: gtop.proc_mem(p.pid)
Out[4]: Struct { .resident = 557056, .rss = 557056, .rss_rlim = 1844674407370955
1615, .share = 483328, .size = 103231488, .vsize = 103231488 }
How to run 'strace' on the above ipython session and learn that gtop.proc_mem() is reading /proc/PID-XXX/statm is left as an exercise for the reader.
Thanks! I'll try them tomorrow.
回覆刪除Btw, I remember that system engineers have higher average salary than software engineers in USA. System engineers probably have higher values or are hard to be found. :)
不錯不錯, 現在可以直接看懂 Scott 的留言了。以前覺得很難懂的世界, 跨過來的感覺真好
回覆刪除