![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
AppendicesBoost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 43. Boost.Xpressive
|
static xpressive | dynamic xpressive | Boost | Text | Expression |
---|---|---|---|---|
1(8.79e & #8209;07s) | 1.08(9.54e & #8209;07s) | 2.51(2.2e‑06s) | 100 - это строка ftp-ответа, содержащая строку сообщения | <^([0-9]+)(\-| |$)(.*)$ > |
1.06(1.07e & #8209;06s) | 1(1.01e & #8209;06s) | 4.01(4.06e & #8209;06s) | 1234-5678-1234-456 | <([[:digit:]]{4}[- ]){3}[[:digit:]]{3,4} > |
1(1.4e‑06s) | 1.13(1.58e & #8209;06s) | 2.89(4.05e‑06s) | john_maddock@compuserve.com | <^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ > |
1(1.28e‑06s) | 1.16(1.49e & #8209;06s) | 3.07(3.94e & #8209;06s) | foo12@foo.edu | <^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ > |
1(1.22e & #8209;06s) | 1.2(1.46e & #8209;06s) | 3.22(3.93e & #8209;06s) | bob.smith@foo.tv | <^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ > |
1.04(8.64e & #8209;07s) | 1(8.34e & #8209;07s) | 2.5(2.09e‑06s) | EH10 2QQ | <^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$ > |
1.11(9.09e & #8209;07s) | 1(8.19e & #8209;07s) | 2.47(2.03e & #8209;06s) | G1 1AA | <^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$ > |
1.12(9.38e & #8209;07s) | 1(8.34e & #8209;07s) | 2.5(2.08e & #8209;06s) | SW1 1ZZ | <^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$ > |
1(7.9e‑07s) | 1.06(8.34e & #8209;07s) | 2.49(1.96e & #8209;06s) | 4/1/2001 | <^[[:digit:]]{1,2}/[[:digit:]]{1,2}/[[:digit:]]{4}$ > |
1(8.19e & #8209;07s) | 1.04(8.49e & #8209;07s) | 2.4(1.97e & #8209;06s) | 12/12/2001 | <^[[:digit:]]{1,2}/[[:digit:]]{1,2}/[[:digit:]]{4}$ > |
1.09(8.95e & #8209;07s) | 1(8.19e & #8209;07s) | 2.4(1.96e‑06s) | 123 | <^[-+]?[[:digit:]]*\.?[[:digit:]]*$ > |
1.11(8.79e & #8209;07s) | 1(7.9e‑07s) | 2.57(2.03e & #8209;06s) | +3.14159 | <^[-+]?[[:digit:]]*\.?[[:digit:]]*$ > |
1.09(8.94e & #8209;07s) | 1(8.19e & #8209;07s) | 2.47(2.03e & #8209;06s) | - 3.14159 | <^[-+]?[[:digit:]]*\.?[[:digit:]]*$ > |
Следующий тест измеряет время, чтобы найтивсесовпадения в длинном английском тексте. Текст представляет собойзаконченные работы Марка Твенаизпроекта Гутенберга. Текст длиной 19 Мб. Как указано выше, верхнее число - это нормированное время, а нижнее - фактическое время. Лучшее время – зеленое.
static xpressive | dynamic xpressive | Boost | Expression |
---|---|---|---|
1(0,0263s) | 1(0,0263s) | 1.78(0.0469) | <Twain > |
1(0,0234s) | 1(0,0234s) | 1.79(0.042s) | <Huck[[:alpha:]]+ > |
1.84(1.26) | 2.21(1.51) | 1(0,687s) | <[[:alpha:]]+ing > |
1.09(0.192s) | 2(0,351) | 1(0.176s) | <^[^
]*?Twain > |
1.41(0.08s) | 1.21(0.0684s) | 1(0,0566s) | <Tom|Sawyer|Huckleberry|Finn > |
1.56(0.195s) | 1.12(0.141) | 1(0.125s) | <(Tom|Sawyer|Huckleberry|Finn).{0,30}river|river.{0,30}(Tom|Sawyer|Huckleberry|Finn) > |
Ниже приведены результаты сравнения производительности между:
Test Specifications
гиперпоточность 3 ГГц Xeon с 1 Гб оперативной памяти
Windows XP Pro Pro
Visual C++ .NET 2003 (7.1)
Dinkumware, версия 313
1.33+, BOOST_REGEX_USE_CPP_LOCALE, BOOST_REGEX_RECURSIVE
0.9.6a
Следующие тесты оценивают время, необходимое для соответствия выражения входной строке. Для каждого результата верхнее число было нормализовано относительно самого быстрого времени, поэтому 1,0 так же хорош, как и получает. Нижнее число (в скобках) — фактическое время в секундах. Лучшее время было отмечено зеленым.
static xpressive | dynamic xpressive | Boost | Text | Expression |
---|---|---|---|---|
1(3.2e‑007s) | 1.37(4.4e‑007s) | 2.38(7.6e & #8209;007s) | 100 - это строка ftp-ответа, содержащая строку сообщения | <^([0-9]+)(\-| |$)(.*)$ > |
1(6.4e‑007s) | 1.12(7.15e & #8209;007s) | 1.72(1.1e‑006s) | 1234-5678-1234-456 | <([[:digit:]]{4}[- ]){3}[[:digit:]]{3,4} > |
1(9.82e & #8209;007s) | 1.3(1.28e‑006s) | 1.61(1.58e & #8209;006s) | john_maddock@compuserve.com | <^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ > |
1(8.94e & #8209;007s) | 1.3(1.16e & #8209;006s) | 1.7(1.52e & #8209;006s) | foo12@foo.edu | <^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ > |
1(9.09e & #8209;007s) | 1.28(1.16e & #8209;006s) | 1.67(1.52e & #8209;006s) | bob.smith@foo.tv | <^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ > |
1(3.06e & #8209;007s) | 1.07(3.28e & #8209;007s) | 1.95(5.96e & #8209;007s) | EH10 2QQ | <^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$ > |
1(3.13e & #8209;007s) | 1.09(3.42e & #8209;007s) | 1.86(5.81e & #8209;007s) | G1 1AA | <^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$ > |
1(3.2e‑007s) | 1.09(3.5e‑007s) | 1.86(5.96e & #8209;007s) | SW1 1ZZ | <^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$ > |
1(2.68e & #8209;007s) | 1.22(3.28e & #8209;007s) | 2(5.36e & #8209;007s) | 4/1/2001 | <^[[:digit:]]{1,2}/[[:digit:]]{1,2}/[[:digit:]]{4}$ > |
1(2.76e‑007s) | 1.16(3.2e‑007s) | 1.94(5.36e & #8209;007s) | 12/12/2001 | <^[[:digit:]]{1,2}/[[:digit:]]{1,2}/[[:digit:]]{4}$ > |
1(2.98e & #8209;007s) | 1.03(3.06e & #8209;007s) | 1.85(5.51e & #8209;007s) | 123 | <^[-+]?[[:digit:]]*\.?[[:digit:]]*$ > |
1(3.2e‑007s) | 1.12(3.58e & #8209;007s) | 1.81(5.81e & #8209;007s) | +3.14159 | <^[-+]?[[:digit:]]*\.?[[:digit:]]*$ > |
1(3.28e & #8209;007s) | 1.11(3.65e & #8209;007s) | 1.77(5.81e & #8209;007s) | - 3.14159 | <^[-+]?[[:digit:]]*\.?[[:digit:]]*$ > |
Следующий тест измеряет время, чтобы найтивсесовпадения в длинном английском тексте. Текст представляет собойзаконченные работы Марка Твенаизпроекта Гутенберга. Текст длиной 19 Мб. Как указано выше, верхнее число - это нормированное время, а нижнее - фактическое время. Лучшее время – зеленое.
static xpressive | dynamic xpressive | Boost | Expression |
---|---|---|---|
1(0,019) | 1(0,019) | 2.98(0.0566s) | <Twain > |
1(0,0176s) | 1(0,0176s) | 3.17(0.0556s) | <Huck[[:alpha:]]+ > |
3.62(1.78) | 3.97(1.95) | 1(0,492) | <[[:alpha:]]+ing > |
2.32(0.344) | 3.06(0.453s) | 1(0,148) | <^[^
]*?Twain > |
1(0,0576s) | 1.05(0.0606s) | 1.15(0.0664s) | <Tom|Sawyer|Huckleberry|Finn > |
1.24(0.164s) | 1.44(0.191s) | 1(0,133) | <(Tom|Sawyer|Huckleberry|Finn).{0,30}river|river.{0,30}(Tom|Sawyer|Huckleberry|Finn) > |
В xpressive объекты регекса могут относиться друг к другу и к себе по значению или по ссылке. Кроме того, они пересчитывают свои упомянутые регексы, чтобы сохранить их живыми. Это создает возможность циклического подсчета ссылок и повышает вероятность утечки памяти. Xpressive позволяет избежать утечек, используя тип, называемый<tracking_ptr<>
>. Этот документ описывает на высоком уровне, как<tracking_ptr<>
>работает.
Наше решение должно соответствовать следующим дизайнерским ограничениям:
Чтобы использовать<tracking_ptr<>
>, вы должны разделить свой тип на ручку и тело. В случае депрессии тип рукоятки называется<basic_regex<>
>, а тело называется<regex_impl<>
>. При этом он будет иметь 511 очков.
Тип тела должен наследоваться от<enable_reference_tracking<>
>. Это дает организму структуры бухгалтерских данных, которые<tracking_ptr<>
>будут использовать. В частности, он дает организму:
std::set<shared_ptr<body>
>refs_
>: совокупность тел, к которым относится это тело, иstd::set<weak_ptr<body>
>deps_
>: совокупность тел, относящихся к этому телу.Мы называем (1) выше «ссылками» и (2) «зависимостями». Для понимания<tracking_ptr<>
>важно признать, что набор ссылок включает как те объекты, которые упоминаются непосредственно, так и те, которые упоминаются косвенно (то есть через другую ссылку). То же самое можно сказать и о множестве зависимостей. Другими словами, каждое тело имеет счет обратной связи непосредственно с каждым другим телом, в котором оно нуждается.
Почему это важно? Потому что это означает, что когда тело больше не имеет ручки, относящейся к нему, все его ссылки могут быть немедленно выпущены, не опасаясь создания болтающихся ссылок.
Ссылки и зависимости пересекаются. Вот как это работает:
Рассмотрим следующий код:
sregex expr; { sregex group = '(' >> by_ref(expr) >> ')'; // (1) sregex fact = +_d | group; // (2) sregex term = fact >> *(('*' >> fact) | ('/' >> fact)); // (3) expr = term >> *(('+' >> term) | ('-' >> term)); // (4) } // (5)
Вот как распространяются ссылки и зависимости, строка за строкой:
выражение |
последствия |
---|---|
1]< |
< |
2]< |
< |
3]< |
< |
4]< |
< |
5]< |
< |
Это показывает, как распространяются ссылки и зависимости при создании циклов объектов. После линии (4), которая замыкает цикл, каждый объект имеет счет на каждый другой объект, даже на себя. Так как же это не утечка? Читайте дальше.
Теперь, когда тела имеют свои наборы ссылок и зависимостей, трудная часть сделана. Остается только решить, когда и где разорвать цикл. Это и есть работа<tracking_ptr<>
>, которая является частью ручки.<tracking_ptr<>
>содержит 2<shared_ptr
>с. Первым, очевидно, является<shared_ptr<body>
>— ссылка на тело, к которому относится эта рукоятка. Другой<shared_ptr
>используется для разрыва цикла. Это гарантирует, что, когда все ручки тела выходят из сферы действия, набор ссылок на тело очищается.
Это говорит о том, что более одной ручки может относиться к телу. На самом деле<tracking_ptr<>
>дает вам семантику копирования на записи — когда вы копируете ручку, тело делится. Это делает копии очень эффективными. В конце концов, все ручки для конкретного тела выходят из-под контроля. Когда это происходит, количество реф-счета в теле все еще может быть больше 0, потому что какое-то другое тело (или само это тело!) может ссылаться на него. Тем не менее, мы уверены, что обратный счет велосипедиста равен 0, потому что велосипедист живет только в ручках. Больше никаких ручек, больше никаких велосипедистов.
Что делает велосипедист? Напомним, что корпус имеет набор отсылок типа<std::set<shared_ptr<body>>
>. Назовем этот тип «references_type». Цикл-брейкер — это<shared_ptr<references_type>
>. Он использует пользовательский удалятель, который определяется следующим образом:
template<typename DerivedT> struct reference_deleter { void operator ()(std::set<shared_ptr<DerivedT> > *refs) const { refs->clear(); } };
Задача выключателя цикла состоит в том, чтобы гарантировать, что, когда последняя ручка тела уходит, набор ссылок на тело очищается. Вот так.
Мы ясно видим, как это гарантирует, что все тела в конечном итоге будут очищены. Как только каждая рукоятка выйдет из-под контроля, все наборы ссылок тел будут очищены, не оставляя ни одного с ненулевым счетом пересчета. Никаких утечек, гарантировано.
Немного сложнее понять, как это гарантирует отсутствие висячих ссылок. Представьте, что существует 3 тела: A, B и C. A относится к B, который относится к C. Теперь все ручки к B выходят из сферы действия, поэтому набор ссылок B очищен. Не означает ли это, что C удаляется, даже если он используется (косвенно) A? Это не так. Эта ситуация никогда не может произойти, потому что мы распространили ссылки и зависимости выше так, что A будет держать ссылку непосредственно на C в дополнение к B. Когда набор ссылок B очищается, никакие тела не удаляются, потому что они все еще используются A.
Все эти<std::set
>с и<shared_ptr
>с и<weak_ptr
>с! Очень неэффективно. Я использовал их, потому что они были удобны. Я мог бы сделать лучше.
Кроме того, некоторые объекты остаются дольше, чем нужно. Подумайте:
sregex b; { sregex a = _; b = by_ref(a); b = _; } // a is still alive here!
Из-за распространения ссылок и зависимостей<std::set
>ссылок может только расти. Он никогда не уменьшается, даже когда некоторые ссылки больше не нужны. Для кспрессионистов это не проблема. Графики ссылочных объектов обычно остаются небольшими и изолированными. Если бы кто-то попытался использовать<tracking_ptr<>
>в качестве общего механизма сбора обратного счета-цикла, эта проблема должна была бы быть решена.
Статья Appendices раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 43. Boost.Xpressive может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Chapter 43. Boost.Xpressive ::
реклама |