grep -f 的性能问题

2024-02-09

我正在使用 grep 在单个文件中搜索多个正则表达式。 特别是,我正在考虑100 MB 文件,带英文字幕 https://drive.google.com/open?id=0B3oOQ14-tellNzhlU0tKT2xFSW8并运行存储在文件中的以下正则表达式模式.txt:

Cas.*eharden
acr.*otic
syn.*thesizing
sub.*abbot
iss.*acharite
bot.*onne
dis.*similatory
ove.*rmantel
isa.*tin
ado.*nijah
sol.*ution
zei.*st
fam.*ousness
inq.*uisitress
aor.*tography
via.*duct
ama.*sa
der.*ive
pie.*tas
kit.*chenette

在这样做时,我观察到 grep 所需的时间并不随着正则表达式的数量线性增长。的确,它似乎呈指数级增长.

实验

System:英特尔(R) 酷睿(TM) i5-5200U CPU @ 2.20GHz; 4 核; 8GB 内存

案例 1:20 个正则表达式

Command grep -c -f patterns.txt subtitles.txt统计 2214 次出现并采取
2,19s 用户 0,00s 系统 99% cpu 总计 2,192。

案例 2:30 个正则表达式

如果我添加以下表达式模式.txt

ort.*hros
ove.*ridentify
mis.*tiest
pay.*ne
int.*erchasing
jej.*uneness
sta.*lactiform
und.*ertrain
cob.*bles
Sub.*category

Command grep -c -f patterns.txt subtitles.txt统计了 2894 次出现,总共需要 71,35 秒用户 0,06 秒系统 99% cpu 1:11,42。

案例 3:35 个正则表达式

添加另外五个表达式:

dis.*embosom
imp.*ortunateness
ema.*thion
rho.*mb
haz.*elwood

Command grep -c -f patterns.txt subtitles.txt计数 2904 次出现,需要 211,18 秒用户 0,22 秒系统 99% cpu 3:31,58 总计

为什么 grep -f 表现出这样的行为?它在内部做什么?

我一直在使用的整套正则表达式都可以找到here https://drive.google.com/open?id=0B3oOQ14-tellOG5WcXBlRmFWY00


从阅读grep源代码中,您文件中的正则表达式似乎没有一次执行一个。相反,它们会被一次性读入一个大的正则表达式中:

case 'f':
  fp = STREQ (optarg, "-") ? stdin : fopen (optarg, O_TEXT ? "rt" : "r");
  if (!fp)
    error (EXIT_TROUBLE, errno, "%s", optarg);
  for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2)
    ;
  keys = xrealloc (keys, keyalloc);
  oldcc = keycc;
  while ((cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) != 0)
    {
      keycc += cc;
      if (keycc == keyalloc - 1)
        keys = x2nrealloc (keys, &keyalloc, sizeof *keys);
    }

这是通过观看证实的stracegrep 在您的命令上运行:

open("testreg", O_RDONLY)               = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=124, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd8912fe000
read(3, "ort.*hros\nove.*ridentify\nmis.*ti"..., 4096) = 124

回溯正则表达式实现(允许反向引用)不会在 O(n) 时间内运行,而是在 O(2^m) 时间内运行,这可能会导致灾难性的 https://stackoverflow.com/questions/5892115/whats-the-time-complexity-of-average-regex-algorithms运行时。

你的假设grep只是依次循环每个正则表达式,将每个正则表达式编译成 DFA,然后执行它,这是完全合理的。然而,似乎grep作者假设,通过同时运行所有正则表达式,在某些情况下他们可能可以更有效地执行此操作。结果是,通过将正则表达式添加到文件中,您将陷入 O(2^m) 运行时间,从而导致运行时间呈指数增长。

事实证明,简单地循环每个正则表达式一次执行一个,强制 grep 线性运行可能会更有效。在我的笔记本电脑上,运行 grep 版本 2.20,我仅使用您提供的文件中的最后 29 个正则表达式得到以下结果:

[Downloads]$ wc -l patterns.txt 
29 patterns.txt

[Downloads]$ time grep -c -f ~/Downloads/patterns.txt /usr/share/dict/linux.words 
117

real    0m3.092s
user    0m3.027s
sys     0m0.047s

[csd@alcazar Downloads]$ time for regex in `cat ~/Downloads/patterns.txt`; do grep -c $regex /usr/share/dict/linux.words > /dev/null; done
real    0m0.474s
user    0m0.312s
sys     0m0.158s
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

grep -f 的性能问题 的相关文章

  • 正则表达式删除字符串中的双/三逗号

    我需要解析一个字符串 因此结果应该像这样输出 abc def ghi klm nop 但我收到的字符串可能看起来更像这样 abc def ghi klm nop 关键是 我事先不知道单词之间有多少个逗号 我可以在 C 中使用正则表达式来帮助
  • php exec 返回的结果比直接进入命令行要少

    我有一个 exec 命令 它的行为与通过 Penguinet 给 linux 的相同命令不同 res exec cd mnt mydirectory zcat log file gz echo res 当将命令直接放入命令行时 我在日志文件
  • REGEX:如何用空格和双引号分割字符串

    我有一个带有空格和双引号的字符串输入 如下所示 Input 18 17 16 Arc 10 12 11 13 Segment 10 23 33 32 12 23 76 21 预期输出 18 17 16 Arc 10 12 11 13 Seg
  • 多少个 div 标签太多了?

    在一个 HTML 文档中需要多少个 div 标签才会影响性能 在这种情况下 标签不嵌套 并且每个标签内的内容最少 背景颜色 图像 这个问题是上一个问题的后续问题 使用 JavaScript 绘制带有可点击点的线条 https stackov
  • 编写此代码片段的有效方法是什么? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 更有效和 或更短地重写此代码以节省字节并显得不那么冗长的方法 if N 2 0 N 6 N 8 N 10 N 12 N 14 N 16 N
  • 如何改变HTML5视频的播放速度?

    如何更改 HTML5 中的视频播放速度 我查过视频标签的属性 https www w3schools com html html5 video asp在 w3school 但无法做到这一点 根据这个网站 http www chipwreck
  • 重复命名捕获组

    我有一个带有如下字段的字符串 id ID 120 1 ID 141 5 ID 92 5 N A 我只想捕获命名捕获组的 ID 即没有 N A 或其他可能潜入的项目 我认为这可能有效 但没有运气 bid
  • 我可以定义自定义字符类简写吗?

    Java 提供了一些有用的字符类 例如 d and w 我可以定义自己的角色类别吗 例如 能够为字符类定义简写 例如 A Za z 我可以定义自己的角色类别吗 不 你不能 就个人而言 当我有一个 稍微 复杂的正则表达式时 我将正则表达式分解
  • 从字符串中提取电子邮件地址

    我有一个像这样的字符串 Francesco Renga lt email protected cdn cgi l email protection gt 我只需要提取电子邮件 即 电子邮件受保护 cdn cgi l email protec
  • 快速检查网络速度

    我想从我的 swift 应用程序检查网络速度 我发现很多帖子描述了Reachability特别是查找连接是否可达以及是 WIFI 连接还是 WWAN 连接的方法 我的问题 是否可以检测 WWAN 的类型 2G 3G 4G 你可以用以下命令检
  • 节省页面加载时间的提示[重复]

    这个问题在这里已经有答案了 我的问题 削减那些不必要的 kb 并使页面加载速度更快的最佳方法是什么 全部是什么优化实践 编码实践 在js php中 如果执行可以使您的页面更轻 为什么我问这个 我读了这篇关于 jquery js 与 jque
  • 在内连接中重用 mysql 子查询

    我正在尝试优化查询 试图避免重复用 指示的查询 复杂查询 使用两次 结果相同 原始查询 SELECT news FROM news INNER JOIN SELECT myposter FROM SELECT COMPLEX QUERY U
  • SQL Azure 和 READ_COMMITTED_SNAPSHOT

    我想在 SQL Azure 数据库上将 READ COMMITTED SNAPSHOT 设置为 ON 但 Azure 不支持以下适用于其他版本的 SQL Server 的代码 ALTER DATABASE database name SET
  • IN 运算符对 SQL 查询性能的影响有多大?

    我的 SQL 查询需要 9 个小时才能执行 见下文 Select Field1 Field2 From A Where Field3 IN 45 unique values here 当我将此查询拆分为 3 个完全相同的查询 仅每个 IN
  • Mono 实现 CLR 吗?或者至少有一些非托管的内部调用?或无?

    我们知道 C 使用非托管代码 如 P Invoke 或 CLR 实现的代码 如 InternalCall 我想知道的是 mono 它自己实现了一个完整的 CLR 还是只是一些非托管代码或者什么都没有 我可以使用 Net Reflactor或
  • 在python中将数据库表写入文件的最快方法

    我正在尝试从数据库中提取大量数据并将其写入 csv 文件 我正在尝试找出最快的方法来做到这一点 我发现在 fetchall 的结果上运行 writerows 比下面的代码慢 40 with open filename a as f writ
  • 索引在 NOT IN 或 <> 子句中起作用吗?

    我读过 至少 Oracle 数据库中的普通索引基本上是 B 树结构 因此存储处理适当根节点的记录 小于 根的记录被迭代地存储在树的左侧部分 而 大于 根的记录被存储在右侧部分 正是这种存储方法有助于通过树遍历实现更快的扫描 因为深度和广度都
  • 匹配没有周围字符列表的单词列表

    我有这个正则表达式 one common word or another 除非这两个单词相邻 否则它匹配得很好 One one s more word word common word or another word more anothe
  • 为什么python+sqlite3特别慢?

    我尝试使用 Python 2 7 4 sqlite3 和 Firefox SQLite Manager 0 8 0 处理对同一数据库的相同请求 在小型数据库 8000 条记录 上 Python 和 Firefox 都运行得很快并且给出了相同
  • 记录类名、方法名和行号的性能影响

    我正在我的 java 应用程序中实现日志记录 以便我可以调试应用程序投入生产后可能出现的潜在问题 考虑到在这种情况下 人们不会奢侈地使用 IDE 开发工具 以调试模式运行事物或单步执行完整代码 因此在每条消息中记录类名 方法名和行号将非常有

随机推荐

  • 如何在 Ruby 中输出前导零?

    我正在从 Ruby 脚本输出一组编号的文件 这些数字来自递增计数器 但为了使它们在目录中很好地排序 我想在文件名中使用前导零 换句话说 文件 001 代替 file 1 有没有simple将数字转换为字符串时添加前导零的方法 我知道我可以做
  • 使用泛型和 jpa EntityManager 方法

    我可以同时使用泛型和 JPA 吗 我正在尝试将四个类的对象持久保存到我的数据库中 这是我的 PersistService 类 public class PersistService
  • 从 erlang 插入 cassandra

    我正在尝试从 Erlang R14B02 通过 thrift 0 6 1 将一些内容插入到 cassandra 0 7 6 中 我正在做以下事情 读取记录定义 rr cassandra types 连接到卡桑德拉 ok C thrift c
  • TopMost = true 的 WinForms 对话框

    我在 WinForms 中实现了一个对话框 该对话框在屏幕右下角显示为通知对话框 问题是 无论何时显示 它都会获得焦点 并且只有当 TopMost true 时才会发生这种情况 我该如何解决这个问题 您需要继承 Form 并覆盖几个属性 F
  • 每个 Docker 容器一个或多个数据库

    假设我有几个不同的容器 每个容器都使用自己的数据库 在这种情况下 关于性能的最佳实践是什么 运行一个容器 比如一台 MySQL 服务器 其中包含所有数据库 还是每个数据库运行一个数据库服务器容器 除了表演之外 任何其他评论都将受到欢迎 由于
  • Android Studio 3.1.1中Aapt2错误

    我将 android studio 从 2 2 更新到 3 1 它总是给我aapt2 error并且构建失败 我添加了android enableAapt2 false在 gradle properties 中 我的项目成功构建 但出现警告
  • Laravel 中的长轮询(sleep() 函数使应用程序冻结)

    我正在尝试在 Laravel 中编写长轮询功能 但是当我使用 sleep 函数时 整个应用程序会冻结 阻塞 直到 sleep 函数完成 有谁知道如何解决这个问题 我的 JavaScript 看起来像这样 function startRefr
  • 自托管 MVC 5 项目

    嘿 您知道如何在桌面上没有本地 IIS 或 IIS Express 的情况下运行 MVC 5 项目吗 在 ASP NET vNext 中 有一个 WebListener 使这成为可能 但我无法将我的项目重新组织为 ASP NET vNext
  • “GridView1”触发了未处理的事件 PageIndexChanging

    我正在使用 gridview 我想使用分页 我已经将允许分页设置为 true 并将页面大小设置为 5 我可以看到 gridview 底部的数字 但是当我单击数字移动到相应页面时 它会抛出错误 The GridView GridView1 f
  • Windows Batch 中嵌套循环中的“继续”等效命令

    我有一个批处理文件 其中包含嵌套循环continue类似命令 for i in 1 2 4 8 16 32 64 128 256 do for j in 1 2 4 8 16 32 64 128 256 do if i gtr j goto
  • jdk1.7/jre/lib/rt.jar的访问限制

    大家好 我在创建 JAXB 解析器时遇到了一个非常奇怪的问题 当我尝试从 eclipse 生成 JAXB 类时 在一个类中它显示了一个非常奇怪的错误 即 Access restriction The type QName is not ac
  • 无法解析 org.tensorflow:tensorflow-lite:0.0.0-nightly

    我下载了最新的tensorflow lite demo 展示一下 Unable to resolve dependency for app debug compileClasspath Could not resolve org tenso
  • 可以阻止 Django 截断长表名吗?

    我将 Django 与现有的 Oracle 数据库 即表不是由 Django 创建的数据库 一起使用 因此 在我的模型中 我必须通过在 Meta 类中指定 db table 的值来指示表名称 我遇到了问题 因为我希望访问的表属于与我拥有凭据
  • 使用多个模板显示页面内容 - WordPress

    是否可以有这样的页面 www site com page 并使用以下命令显示不同的模板版本 www site com page template default www site com page template archive 因此它检
  • C++ 联合体、结构体、成员类型

    如果我有课 class Odp int i int b union long f struct WCHAR pwszFoo HRESULT hr 联合意味着 在列出的所有值中 它一次只能采用其中一个值 就访问这些变量而言 它是如何工作的 我
  • 如何在Python中的图像上打印印地语句子(unicode)?

    我有一个名为 hindi txt 的文件 其内容如下 我使用的是Python3 5 9 59000 Cr 36 WhatsApp Allo 10 150
  • 在 Cython 中分配中间多维数组而不获取 GIL

    我正在尝试使用 Cython 并行化涉及生成中间多维数组的昂贵操作 以下非常简化的代码说明了我正在尝试做的事情 import numpy as np cimport cython cimport numpy as np from cytho
  • 从 Windows NT 设备路径转换为驱动器号路径

    如何解析设备路径中带有驱动器号的路径 例如 转换 Device HarddiskVolume4 Windows System32 RuntimeBroker exe into C Windows System32 RuntimeBroker
  • 在 xml 文件中搜索数据的最佳方法?

    在我们的新项目中 我们必须提供搜索功能来从数百个 xml 文件中检索数据 下面我简要介绍了我们目前的计划 我想知道您对此的建议 改进 这些 xml 文件包含个人信息 搜索基于其中的 10 个元素 例如姓氏 名字 电子邮件等 我们当前的计划是
  • grep -f 的性能问题

    我正在使用 grep 在单个文件中搜索多个正则表达式 特别是 我正在考虑100 MB 文件 带英文字幕 https drive google com open id 0B3oOQ14 tellNzhlU0tKT2xFSW8并运行存储在文件中