【问题标题】:Cerberus/regex bottlenecking - Performant validation practicesCerberus/正则表达式瓶颈 - 性能验证实践
【发布时间】:2020-03-09 18:35:46
【问题描述】:

我正在将 AIOHTTP 用于 Web 应用程序。我正在使用 Cerberus 来验证用户输入。我用 wrk 基准工具运行了一些测试,发现以下 Cerberus 验证器:

"uri": {
        "type": "string",
        "coerce": str,
        "required": True,
        "minlength": 1,
        "maxlength": 255,
        "regex": "^[a-zA-Z0-9/_]+$"
    }

为网页增加大约 10-15% 的加载时间。这是我无法接受的临界点。如何解决这个问题?它只是正则表达式引擎吗?是否有已知更快的模块?我知道字符串解析函数通常比正则表达式更快。是否有不使用正则表达式的验证引擎?将正则表达式转换为字符串解析的工具会很有趣。

编辑:我运行了一个分析器:

from cerberus import Validator
from speed_profiler import SpeedProfiler
from pprint import pprint

def referer_validator(value):
    if len(value) < 1 or len(value) > 256:
        return False
    if not any(not l.isalnum() and l not in ['_', '/'] for l in value):
        return False
    return True


v = Validator()
v.schema = {
    "path": {
        "type": "string",
        "coerce": str,
        "required": True,
        "minlength": 1,
        "maxlength": 255,
        "regex": "^[a-zA-Z0-9/_]+$"
    }
}

sp = SpeedProfiler('Cerberus')

v.validate({'path': '/some/path_foo'})

sp.mark('Parser Function')

referer_validator('/some/path_foo')

profile = sp.stop()
pprint(profile)

这证实了 Cerberus 很慢:

[{'duration': 0.00029901403468102217,
  'identifier': 'Cerberus',
  'line_num': 27,
  'percent_time': 98.26},
 {'duration': 5.29497629031539e-06,
  'identifier': 'Parser Function',
  'line_num': 31,
  'percent_time': 1.74}]

这证实了 Cerberus 很慢。目前,我正在使用它来提高速度:

def path_valid(value):
    if len(value) < 1 or len(value) > 256:
        return False
    if not any(not l.isalnum() and l not in ['_', '/'] for l in value):
        return False
    return True

【问题讨论】:

  • 我已尝试关注documentation,请尝试关注pastebin.com/c1YNk4yr。测试here
  • 谢谢。我用check_with 模式尝试了这个功能,但仍然遇到了减速。我认为 Cerberus 会导致任何模式的额外滞后。这是一个很好的尝试,我更喜欢使用它而不是正则表达式。我将运行分析器并用更详细的发现更新问题。
  • 问题已更新配置文件和可能的解决方案(您的功能)@WiktorStribiżew
  • 刚想到应该是len(value) &gt; 255

标签: python regex python-3.x performance validation


【解决方案1】:

如果您更喜欢使用非正则表达式解决方案,您可以使用

def path_valid(value):
    if len(value) < 1 or len(value) > 255:
        return False
    if not any(not l.isalnum() and l not in ['_', '/'] for l in value):
        return False
    return True

如果值的长度小于 1 或大于 255(由于if len(value) &lt; 1 or len(value) &gt; 255 检查),则此方法验证失败,如果存在不是字母数字且不是 _ 的 char 或/(使用 if not any(not l.isalnum() and l not in ['_', '/'] for l in value) 完成检查)。

查看Python test here

【讨论】:

    猜你喜欢
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多