Я надеялся использовать 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 для обработки текстовых файлов или есть другой язык, который лучше подходит для работы?
Как ни странно, я наткнулся на очень похожей ситуации всего несколько дней назад - я переписал текстовый парсер в Julia, а исходная версия Python - в 3 раза быстрее. – TigerhawkT3
Ваша программа Rust не использует буферную запись. Попробуйте заменить свои 'File :: create (...). Unwrap()' вызовы с помощью 'io :: BufWriter :: new (File :: create (...). Unwrap())'. – BurntSushi5
@ BurntSushi5 yup, спасибо! У меня было ощущение, что у меня что-то не хватает. – ostrokach