是否存在正则表达式匹配的硬限制?

时间:2014-05-04 18:48:15

标签: php regex pcre

我有一个我为路由组件here is the full code编写的代码,它基本上构建了许多小的(特定于路由的)规则中的任意数量的大型正则表达式(取决于配置值)验证给定请求是否可以由注册路由映射。

一般过程包括首先装饰每条路线,以便使用占位符的路线如

/path/to/:variable_name

变成像这样的正则表达式:

/path/to/(?P<R1V1>[^/]+)

在验证时,这条路线会在每批任意大小的单个正则表达式中粘合在一起。

对于'正常'用法,例如,有1-4个占位符的500条路线,它的效果非常好。但是在对它进行基准测试时,我注意到对于极大数量的占位符 AND 和极大量的路径(目前有11个占位符和50000个路由),我找不到最后一个注册路径的代码。< / p>

我无法弄明白为什么。据我所知,事情应该大致以相同的方式表现,采取(可能?我的O符号生锈)每个数量级的O(n * m)次(n是批量,m是多少)正则表达式是批量存在的)。

也许这是我正在测试的方式?如果不是,请你指点我正在做的任何有问题的事情?

如果有任何用处,我使用的基准测试就是这里的基准

<?php
require dirname(__FILE__).'/../vendor/autoload.php';
$router = new \CFV\Router();
$dispatcher = new \CFV\Dispatcher();

$dispatcher::$ROUTES_PER_LOT = 20;
// $dispatcher::$THROW_ON_FAIL = true;

$callback = function (){};
$num_args = 11;
$routes_amount = 50000;
$matches_amount = 1;
$args = implode('/', array_map(function($i){ return ':arg' . $i; }, range(1, $num_args)));
$params = implode('/', array_map(function($i){ return '_arg' . $i; }, range(1, $num_args)));
$last_tried = '';

$load_start = microtime(true);
for ($i = 0, $str = 'a'; $i < $routes_amount; $i++, $str++) {
    $router->connect("/$str/$args", $callback);
    $last_tried = "/$str/$params";
}
printf("Took: %fs to load all\n", microtime(true) - $load_start);

$dispatcher->setRouter($router);
$search_start = microtime(true);

$found = $dispatcher->dispatch($last_tried);

printf("Took: %fs searching all\n", microtime(true) - $search_start);

任何指针都会很棒。

1 个答案:

答案 0 :(得分:2)

有些限制。来自the manual

  

主题字符串的最大长度是最大的正数   整数变量可以容纳。但是,PCRE使用递归   处理子模式和无限重复。这意味着   可用的堆栈空间可能会限制主题字符串的大小   由某些模式处理。

此外,还有PCRE recursion limitbacktrack limit

  

如果模式中有超过15个捕获括号,则PCRE具有   在递归过程中获得额外的内存来存储数据   通过使用pcre_malloc,之后通过pcre_free释放它。如果不   可以获得内存,它为前15次捕获保存数据   仅括号,因为没有办法给出内存不足的错误   从递归中。

价:
http://php.net/manual/en/regexp.reference.recursive.php
http://php.net/pcre.configuration#ini.pcre.recursion-limit
http://php.net/pcre.configuration#ini.pcre.backtrack-limit

相关问题