注意:这是对this question。
的跟进我有一个“遗留”程序,可以对大块HTML进行数百次字符串匹配。例如,如果HTML匹配20个字符串中的1个,请执行某些操作。如果它与4个其他字符串中的1个匹配,则执行其他操作。这些字符串有50-100组可以匹配这些HTML块(通常是整页)。
我正在努力重构这些混乱的代码并试图找到一个很好的方法来完成所有这些匹配。
此代码的性能要求相当严格。在进行这些匹配时,它不需要等待I / O,因此它们需要在内存中。此过程可能同时运行100多个副本,因此启动时的大I / O可能会导致其他副本的I / O速度变慢。
考虑到这些要求,如果这些字符串中只有一个副本存储在RAM中,那将是最有效的(参见我之前链接的上一个问题)。
此程序目前在Windows上运行Microsoft编译器,但我希望尽可能保持跨平台解决方案,所以我认为我不想使用PE资源文件或其他东西。
映射外部文件可能有效,但后来我遇到了保持程序版本和数据版本同步的问题,没有其他版本通常不会改变。这也需要一些文件“格式”,这增加了我不想拥有的复杂性。
因此,在所有这些前导后,似乎最好的解决方案是拥有一串字符串,然后我可以迭代。这似乎有点混乱,因为我正在大量混合代码和数据,但有上述要求有没有更好的方法来处理这种情况?
答案 0 :(得分:2)
我不确定当前的实施速度有多慢。因此,在不知道需要什么级别的优化的情况下,很难推荐优化。
然而,鉴于此,我可能建议采用两阶段方法。获取字符串列表并将其编译为radix tree,然后将此树保存为某种自定义格式(XML可能足以满足您的需要)。然后你的进程启动应该包括读取基数树和匹配。如果你想/需要优化树的内存存储,那可以作为一个单独的项目来完成,但我觉得改进匹配算法会更有效地利用时间。在某些方面,这是一个“滚动你自己的正则表达式系统”的想法。与使用解析器生成器的建议非常相似。
编辑:我使用了与此类似的东西,作为预编译步骤,自定义脚本生成稍微优化的结构并将其保存到大型char *数组中。 (显然它不能太大,但它是另一种选择)
我们的想法是将列表保留在那里(使维护变得相当容易),但是预编译步骤可以加快运行期间的访问速度。
答案 1 :(得分:1)
如果需要匹配的字符串可以在编译时锁定,则应考虑使用像 lex 这样的标记生成器生成器来扫描输入以进行匹配。如果您不熟悉它, lex 会获取一个源文件,该文件包含一些正则表达式(包括最简单的正则表达式 - 字符串文字)和找到匹配项时要执行的C动作代码。它经常用于构建编译器和类似的程序,还有其他几个类似的程序,你也可以使用(flex和antlr想到)。 lex 构建状态机表,然后生成有效的C代码,用于将输入与状态表所代表的正则表达式进行匹配(默认情况下输入是标准输入,但您可以更改此设置)。使用此方法可能不会导致您担心的程序的不同实例之间的内存中的字符串(或其他数据)重复。您可以轻松地从现有代码中的字符串文字生成正则表达式,但重新编写程序以使用 lex 生成的代码可能需要花费大量工作。
如果你必须匹配的字符串会随着时间的推移而改变,那么有一些正则表达式库可以在运行时编译正则表达式,但是它们会使用大量的RAM,并且根据程序的体系结构,它们可能会在不同的实例中重复。程序
使用正则表达式方法而不是大量strcmp
次调用的好处是,如果你有这些模式:
"string1"
"string2"
"string3"
和输入:
"string2"
对于DFA(确定性有限状态自动机)正则表达式系统(如 lex ),“string”的部分匹配只会执行一次,这可能会加速您的系统。构建这些东西确实需要代表 lex 进行大量工作,但所有的努力工作都是事先完成的。
答案 2 :(得分:0)
这些文字字符串是否存储在文件中?如果是这样,正如您所建议的那样,最佳选择可能是使用内存映射文件在程序的数百个实例中共享文件的副本。此外,您可能希望尝试调整工作集大小以尝试查看是否可以减少页面错误的数量,但鉴于您有这么多实例,它可能会适得其反(除了您的程序需要有配额权限以调整工作集大小。)
您可以尝试其他技巧来优化IO性能,例如分配大页面,但这取决于您的文件大小和授予您的程序的权限。
最重要的是,您需要进行实验以了解最佳效果,并记住在每次更改后进行衡量:)...