簡體   English   中英

為什么Python3在執行任務時比Python2慢得多?

[英]Why is Python3 much slower than Python2 on my task?

我很驚訝地知道Python 3.5.2Python 2.7.12慢得多。 我編寫了一個簡單的命令行命令,該命令可計算巨大的CSV文件中的行數。

$ cat huge.csv | python -c "import sys; print(sum(1 for _ in sys.stdin))"
101253515
# it took 15 seconds

$ cat huge.csv | python3 -c "import sys; print(sum(1 for _ in sys.stdin))"
101253515
# it took 66 seconds

Python 2.7.12花了15秒,Python 3.5.2花了66秒。 我期望可能會發生差異,但是為什么會有如此之大呢? Python 3的新功能使執行此類任務的速度大大降低了? 有沒有一種更快的方法來計算Python 3中的行數?

我的CPU是Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz

huge.csv的大小為18.1 Gb,包含101253515行。

問這個問題,我不需要不惜一切代價找到一個大文件的行數。 我只是寫了一個Python 3慢得多的特殊情況。 實際上,我正在用Python 3開發一個處理大型CSV文件的腳本,某些操作不要求使用csv庫。 我知道,我可以用Python 2編寫腳本,並且在速度上可以接受。 但是我想知道一種用Python 3編寫類似腳本的方法。這就是為什么我對在示例中使Python 3變慢的原因以及如何通過“誠實的” python方法加以改進的原因感到感興趣。

sys.stdin對象在Python3中要比在Python2中復雜一些。 例如,通過默認從讀取sys.stdin在Python3將輸入成unicode,因而它無法在非unicode字節:

$ echo -e "\xf8" | python3 -c "import sys; print(sum(1 for _ in sys.stdin))"

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <genexpr>
  File "/usr/lib/python3.5/codecs.py", line 321, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf8 in position 0: invalid start byte

請注意,Python2對該輸入沒有任何問題。 因此,如您所見,Python3的sys.stdinsys.stdin執行了更多操作。 我不確定這是否是造成性能下降的原因,但是您可以通過在sys.stdin.buffer下嘗試sys.stdin.buffer來進一步調查:

import sys
print(sum(1 for _ in sys.stdin.buffer))

請注意, .buffer在Python2中不存在。 我已經做過一些測試,但沒有看到Python2的sys.stdin和Python3的sys.stdin.buffer之間的真正性能差異,但是YMMV。

編輯這是我機器上的一些隨機結果:ubuntu 16.04,i7 cpu,8GiB RAM。 首先是一些C代碼(作為比較的基礎):

#include <unistd.h>

int main() {
    char buffer[4096];
    size_t total = 0;
    while (true) {
        int result = ::read(STDIN_FILENO, buffer, sizeof(buffer));
        total += result;
        if (result == 0) {
            break;
        }
    }
    return 0;
};

現在文件大小:

$ ls -s --block-size=M | grep huge2.txt 
10898M huge2.txt

和測試:

// a.out is a simple C equivalent code (except for the final print)
$ time cat huge2.txt | ./a.out

real    0m20.607s
user    0m0.236s
sys     0m10.600s


$ time cat huge2.txt | python -c "import sys; print(sum(1 for _ in sys.stdin))"
898773889

real    1m24.268s
user    1m20.216s
sys     0m8.724s


$ time cat huge2.txt | python3 -c "import sys; print(sum(1 for _ in sys.stdin.buffer))"
898773889

real    1m19.734s
user    1m14.432s
sys     0m11.940s


$ time cat huge2.txt | python3 -c "import sys; print(sum(1 for _ in sys.stdin))"
898773889

real    2m0.326s
user    1m56.148s
sys     0m9.876s

因此,我使用的文件較小,時間也更長(似乎您有一台更好的機器,而我對較大的文件:D則沒有耐心)。 無論如何,Python2和Python3的sys.stdin.buffer在我的測試中非常相似。 Python3的sys.stdin慢一些。 而且所有這些都在C代碼后面(幾乎有0個用戶時間)。

暫無
暫無

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

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