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

Car*_*ara 7 php regex pcre

我有一个我为路由组件编写的代码,这里是完整的代码,它基本上构建了许多小的(特定于路由的)大量的任意数量的大正则表达式(取决于配置值)以验证是否注册路由可以或不可以映射给定请求.

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

/path/to/:variable_name
Run Code Online (Sandbox Code Playgroud)

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

/path/to/(?P<R1V1>[^/]+)
Run Code Online (Sandbox Code Playgroud)

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

对于"正常"使用,比如说有500个占位符的路由,它运行得很好.不过,虽然基准它,我注意到了一个非常大的数量的占位符AND和路线非常大的量(目前11个占位符和50000个路由)我的代码在找到最后的注册路由失败.

我无法弄清楚为什么.据我所知,事情应该大致以相同的方式表现,采取(可能?我的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);
Run Code Online (Sandbox Code Playgroud)

任何指针都会很棒.

eye*_*hUp 2

一些限制。从手册中:

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

另外,还有PCRE的递归限制回溯限制

如果模式中有超过 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。配置#ini.pcre.backtrack-limit