2016-12-30 84 views
3

我曾希望使用Rust來加速當前用Python編寫的一些文本處理腳本。在解析文件時比解析Python的速度更慢

爲了測試這兩種語言的表現,我決定測試他們在一個非常簡單的任務:通過線從STDIN

  • 讀取一個文件,一行。
  • 如果行以>開頭,請將該行保存爲headers.txt文件。
  • 否則,將行保存到sequences.txt文件。

對於這個測試,我使用了10萬線FASTA文件,如下所示:

$ head uniparc_active-head.fasta 
>UPI0000000001 status=active 
MGAAASIQTTVNTLSERISSKLEQEANASAQTKCDIEIGNFYIRQNHGCNLTVKNMCSAD 
ADAQLDAVLSAATETYSGLTPEQKAYVPAMFTAALNIQTSVNTVVRDFENYVKQTCNSSA 
VVDNKLKIQNVIIDECYGAPGSPTNLEFINTGSSKGNCAIKALMQLTTKATTQIAPKQVA 
GTGVQFYMIVIGVIILAALFMYYAKRMLFTSTNDKIKLILANKENVHWTTYMDTFFRTSP 
MVIATTDMQN 
>UPI0000000002 status=active 
MMTPENDEEQTSVFSATVYGDKIQGKNKRKRVIGLCIRISMVISLLSMITMSAFLIVRLN 
QCMSANEAAITDAAVAVAAASSTHRKVASSTTQYDHKESCNGLYYQGSCYILHSDYQLFS 
DAKANCTAESSTLPNKSDVLITWLIDYVEDTWGSDGNPITKTTSDYQDSDVSQEVRKYFC 

這裏是我的Python腳本:

import fileinput 

with open('headers.txt', 'w') as hof, \ 
     open('sequences.txt', 'w') as sof: 
    for line in fileinput.input(): 
     if line[0] == '>': 
      hof.write(line) 
     else: 
      sof.write(line) 

和我的鏽腳本(我在cargo build --release編譯):

use std::io; 
use std::fs::File; 
use std::io::Write; 
use std::io::BufRead; 

fn main() { 
    let stdin = io::stdin(); 
    let mut headers = File::create("headers.txt").unwrap(); 
    let mut sequences = File::create("sequences.txt").unwrap(); 

    for line in stdin.lock().lines() { 
     let line = line.unwrap(); 
     match &line[..1] { 
      ">" => writeln!(headers, "{}", line).unwrap(), 
      _ => writeln!(sequences, "{}", line).unwrap(), 
     } 
    } 
} 

個運行一些基準:

的Python 2.7

$ time bash -c 'cat uniparc_active-head.fasta | python2 src/main.py' 
real 0m11.704s 
user 0m6.996s 
sys  0m1.100s 

的Python 3.5

$ time bash -c 'cat uniparc_active-head.fasta | python3 src/main.py' 
real 0m16.788s 
user 0m12.508s 
sys  0m1.576s 

PyPy 5.3.1

$ time bash -c 'cat uniparc_active-head.fasta | pypy src/main.py' 
real 0m6.526s 
user 0m1.536s 
sys  0m0.884s 

鏽1.14.0

$ cargo build --release 
$ time bash -c 'cat uniparc_active-head.fasta | target/release/parse_text' 
real 0m17.493s 
user 0m2.728s 
sys  0m15.408s 

So Rust比PyPy慢3倍,甚至比Python 3慢。

任何人都可以對此有所瞭解嗎?我在Rust代碼中犯了錯誤嗎?如果沒有,我應該堅持Python/PyPy來處理文本文件,還是有另一種語言對工作更好?

+1

奇怪的是,我偶然發現一個類似的情況就在幾天前 - 我重寫了Julia中的文本解析器,原始Python版本速度提高了3倍。 – TigerhawkT3

+5

您的Rust程序未使用緩衝作家。嘗試用'io :: BufWriter :: new(File :: create(...)。unwrap())'替換你的'File :: create(...)。unwrap()'調用。 – BurntSushi5

+0

@ BurntSushi5喲,謝謝!我有一種感覺,我錯過了一些基本的東西。 – ostrokach

回答

6

至於建議由@ BurntSushi5,與

let mut headers = io::BufWriter::new(File::create("headers.txt").unwrap()); 
let mut sequences = io::BufWriter::new(File::create("sequences.txt").unwrap()); 

更換

let mut headers = File::create("headers.txt").unwrap(); 
let mut sequences = File::create("sequences.txt").unwrap(); 

帶來的速度達到我的預期:

$ time bash -c 'cat uniparc_active-head.fasta | target/release/parse_text' 
real 0m5.645s 
user 0m1.396s 
sys  0m0.804s