Ради удовольствия я написал быстрый сценарий командной строки Racket для анализа старых файлов с предсказаниями Unix. Файлы Fortune - это просто гигантские текстовые файлы с одним %
в пустой строке, разделяющей записи.
В качестве первого взлома я написал следующий код Racket:
(define fortunes
(with-input-from-file "fortunes.txt"
(λ ()
(regexp-split #rx"%" (port->string)))))
Я думал, что он запустится почти мгновенно. Вместо этого на запуск уходит очень много времени - порядка пары минут. Для сравнения, то, что я считаю эквивалентом Python:
with open('fortunes.txt') as f:
fortunes = f.read().split('%')
, выполняется немедленно с результатами, эквивалентными коду Racket.
Что я здесь делаю не так? Да, есть некоторые очевидные низко висящие плоды, например, я уверен, что все было бы лучше, если бы я не проглотил весь файл в ОЗУ с помощью port-> string
, но поведение настолько патологически плохо, я чувствую, что должен делать что-то глупое на гораздо более высоком уровне, чем этот.
Есть ли более похожий на Racket способ сделать это с более высокой производительностью? Действительно ли Racket I / O плохо подходит для некоторых операций? Есть ли способ профилировать мой код немного глубже, чем наивный профилировщик в DrRacket, чтобы я мог выяснить, что в данной строке вызывает проблему?
РЕДАКТИРОВАТЬ : файл удачи I ' m используется FreeBSD, найденная по адресу http://support.cat-v.org/freebsd/ , который весит около 2 МБ. Лучшей средой выполнения для Racket 5.1.3 x64 на OS X Lion было:
real 1m1.479s
user 0m57.400s
sys 0m0.691s
Для Python 2.7.1 x64 это было:
real 0m0.057s
user 0m0.029s
sys 0m0.015s
Эли прав в том, что время почти полностью тратится на regexp-split
(хотя кажется, что целая секунда тратится на порт-> строка
), но мне не ясно, есть ли предпочтительный, но столь же простой метод.