Я бы структурировал парсер вокруг разбора одной записи журнала. Это выполняет 2 вещи:
- разбивает проблему на легко распараллеливаемые куски
- позиционирует ваш синтаксический анализатор для обработки добавочной обработки журнала после того, как начальная задержка данных журнала была обработана
В таком случае размер распараллеливающегося куска представляет собой красиво упакованный отдельный элемент, и каждый процесс может анализировать элемент отдельно (при условии, что вам не нужно переносить информацию о состоянии или истекшем времени из одного сообщения журнала в другое). 1009 *
РЕДАКТИРОВАТЬ (этот вопрос превратился в еще одну тему о настройке pyparsing ...)
Я обнаружил, что лучше определять низкоуровневые примитивы, которые построены с использованием Combine(lots+of+expressions+here)
, используя выражение регулярного выражения Pyparsing. Обычно это относится к выражениям, таким как действительные числа или временные метки, например:
# 2010-01-25 grammar
yearly_day_bnf = Combine(year + "-" + month + "-" + day)
yearly_day_bnf = Regex(r"\d{4}-\d{2}-\d{2}")
# 06:55:00. grammar
clock24h_bnf = Combine(Word(nums, max=2) + ":" +
Word(nums, max=2) + ":" +
Word(nums, max=2) + Suppress("."))
clock24h_bnf = Regex(r"\d{2}:\d{2}:\d{2}\.")
clock24h_bnf.setParseAction(lambda tokens:tokens[0][:-1])
timestamp_bnf = Combine(yearly_day_bnf + White(' ') + clock24h_bnf)
timestamp_bnf = Regex(r"\d{4}-\d{2}-\d{2}\s+\d{1,2}:\d{2}:\d{2}")
Не нужно переусердствовать. Такие вещи, как integer=Word(nums)
, уже генерируют RE под прикрытием.
Обратите внимание, что я также удалил имя результатов из timestamp_bnf. Обычно я исключаю имена результатов из определений примитивов и добавляю их по мере того, как собираю их в выражения более высокого уровня, чтобы я мог использовать один и тот же примитив несколько раз с разными именами, например:
summary = ("Started:" + timestamp_bnf("startTime") +
"Ended:" + timestamp_bnf("endTime"))
Я считаю, что это также помогает мне организовать мои проанализированные структуры.
Перемещение имени результатов в более высокое выражение также побуждает меня дать полю более информативное имя:
report_bnf = report_id + Suppress("Report at ") + timestamp_bnf("reportTime")
Глядя на свою грамматику, вы на самом деле не взламываете всю информацию этого отчета, просто извлекаете время отчета из этой строки:
# XX_MAIN (23143) Report at 2011-08-30 20:00:00.003
и 2 целых поля из этой строки:
Services succ. terminations | 12736 12736 100 | 16311566 16314222 99 |
Попробуйте вместо этого:
report_bnf = report_id + Suppress("Report at") + timestamp_bnf("reportTime")
succ_term_bnf = (Suppress("Services succ. terminations") + Suppress("|") +
integer("succTerms") + integer("totalTerms"))
log_data_sources_bnf = report_bnf | succ_term_bnf
extractLogData = lambda logentry : sum(log_data_sources_bnf.searchString(logentry))
print extractLogData(log_slice).dump()
Pyparsing всегда будет медленнее чем RE, и может случиться так, что анализатор pyparsing в вашем случае - просто ступенька для прототипирования. Я уверен, что не смогу добиться производительности в 500 раз с помощью синтаксического анализатора, и вам, возможно, просто придется использовать решение на основе RE для обработки файлов журналов в мегабайтах.