2016-12-30 3 views
3

Я надеялся использовать Rust для ускорения некоторых скриптов обработки текста, которые в настоящее время написаны на Python.Ржавчина медленнее, чем Python при анализе файлов

Для того, чтобы проверить эффективность двух языков, я решил проверить их на очень простую задачу:

  • Читайте в файле с STDIN, строка за строкой.
  • Если строка начинается с >, сохраните строку в файле headers.txt.
  • В противном случае сохраните строку в файле sequences.txt.

Для этого теста я использую Fasta файл с 10 миллионов строк, который выглядит следующим образом:

$ 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) 

и мой Rust сценарий (который я компилирую в 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 

Так что Rust ~ 3 раза медленнее, чем PyPy, и даже медленнее, чем Python 3.

Может ли кто-нибудь осветить этот свет? Я допустил ошибку в коде Rust? Если нет, должен ли я придерживаться Python/PyPy для обработки текстовых файлов или есть другой язык, который лучше подходит для работы?

+1

Как ни странно, я наткнулся на очень похожей ситуации всего несколько дней назад - я переписал текстовый парсер в Julia, а исходная версия Python - в 3 раза быстрее. – TigerhawkT3

+5

Ваша программа Rust не использует буферную запись. Попробуйте заменить свои 'File :: create (...). Unwrap()' вызовы с помощью 'io :: BufWriter :: new (File :: create (...). Unwrap())'. – BurntSushi5

+0

@ BurntSushi5 yup, спасибо! У меня было ощущение, что у меня что-то не хватает. – ostrokach

ответ

6

Как было предложено @ BurntSushi5, заменив

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

с

let mut headers = io::BufWriter::new(File::create("headers.txt").unwrap()); 
let mut sequences = io::BufWriter::new(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 
Смежные вопросы