什么是处理大量用户定义的正则表达式的最佳方法

时间:2013-07-30 11:38:58

标签: regex performance algorithm

我有一个解析数据流的系统,并且基于许多用户的订阅,它需要对其进行过滤。但是,这些过滤器可以包含正则表达式,我需要使其足够安全,以便恶意用户无法插入有目的的CPU昂贵的正则表达式来破坏服务。

我想知道最好的方法应该是什么,

在我制作的另一个程序中,我通过生成执行正则表达式搜索的新线程来处理此问题,如果此线程的运行时间超过限制,则会被终止并且条目被阻止。

然而,这个系统可能每分钟处理数千条记录,我无法想象我会为每一条记录生成一个新线程(实际上我需要为每个条目循环所有订阅,因此它可能有数十万个线程每一分钟。

有没有更好的方法来处理这个问题?创建订阅后,我应该使用一些测试数据来测试正则表达式吗?或者可能为每个在不同线程中解析的用户使用单独的队列?

另外一种不同的方法是收集每个过滤器占用多少CPU时间的统计信息,并禁用过多吃掉的那些,但这并不能真正处理可能需要的“非常糟糕”的正则表达式完成CPU时间的分钟

如果有人感兴趣,我会用c#编写,但这个问题相当通用,适用于任何语言

4 个答案:

答案 0 :(得分:4)

由于您使用的是C#,因此无需剥离新线程。 Regex构造函数有一个overload,可让您设置超时。如果正则表达式花费的时间太长,它将中止并抛出RegexMatchTimeoutException

对于没有内置超时的正则表达式引擎,您可能只能通过生成一个线程并重用它来管理,或者让线程池为您分配线程

如果正则表达式不仅仅是一次性使用,那么值得做的另一件事是编译正则表达式。 C#中的正则表达式支持预编译以加速未来的匹配。

答案 1 :(得分:1)

如果您愿意实施自己的正则表达式引擎(或查找库),请使用Thompson的NFA构造方法并限制每个自动机中的状态数(或者,为了更好地理解用户,正则表达式的长度,高度相关)。匹配算法的性能比回溯算法更可预测。

答案 2 :(得分:1)

我认为,如果您在用户添加新过滤器时评估运行此正则表达式的成本会更好。例如:

  • 用户希望使用正则表达式添加过滤器X.
  • 应用程序应在预定义的数据集上运行此过滤器。
  • 如果此运行时间超过Y毫秒,则不允许添加。
  • 排名较高的用户(付费服务,忠诚用户......)可以获得更积极的过滤器(更多处理毫秒数)。

答案 3 :(得分:1)

你真的不需要为每个正则表达式生成一个线程...而是创建工作线程,通过循环中的剩余正则表达式工作,在每次迭代时记录循环的开始。然后,使用您以前的解决方案来杀死花费太长时间的工作线程,禁用正则表达式并重新生成工作线程。

这样,你没有一直开始新线程的开销,但是仍然可以杀掉那些花费太长时间的线程。