Как я могу определить, почему мой код Racket работает так медленно?

Ради удовольствия я написал быстрый сценарий командной строки 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 (хотя кажется, что целая секунда тратится на порт-> строка ), но мне не ясно, есть ли предпочтительный, но столь же простой метод.

6
задан Benjamin Pollack 17 August 2011 в 03:12
поделиться