惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
S
Secure Thoughts
月光博客
月光博客
美团技术团队
雷峰网
雷峰网
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Forbes - Security
Forbes - Security
W
WeLiveSecurity
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
罗磊的独立博客
The Register - Security
The Register - Security
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Engineering at Meta
Engineering at Meta
Latest news
Latest news
IT之家
IT之家
D
DataBreaches.Net
博客园 - 司徒正美
N
Netflix TechBlog - Medium
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - 拖鞋不脱

【原】Silverlight内存泄漏原因、检测及解决(Memory Leak of Silverlight:Reason、Detection and Solving) 【随】不好用的Ria Services 【原】StreamInsight 浅入浅出(六)—— Debugger 【原】StreamInsight 浅入浅出(五)—— LINQ 语法 【原】StreamInsight 浅入浅出(四)—— 例子 【原】StreamInsight 浅入浅出(三)—— 适配器 【原】StreamInsight 浅入浅出(二)—— 流与事件 【原】Silverlight 自定义控件模板管理 【原】StreamInsight 浅入浅出(一)—— 基本概念 【原】小软件开发心得(二)——推广、测试 【原】小软件开发心得(一)——需求、开发 【原】豆瓣电台桌面版插件开发——搜索插件 【原】豆瓣电台桌面版——Win7任务栏支持+托盘+快捷键+历史记录 【原】Sql Server性能优化——Slide Window 【原】Sql Server性能优化——Partition(管理分区) 【随】Silverlight请求服务的缓存文件问题 【原】Sql Server性能优化——Partition(创建分区) 【原】Sql Server性能优化——Compression 【译】VS2010中C#的增强
【原】检测是否包含特定字符串的几种方法以及性能比较
拖鞋不脱 · 2011-03-02 · via 博客园 - 拖鞋不脱

【原】检测是否包含特定字符串的几种方法以及性能比较

2011-03-02 16:21  拖鞋不脱  阅读(5408)  评论()    收藏  举报

对于一串字符串"abfeuiowqjiqopeuwqiopewq",检测其中是否包含特定字符串"oweu",我常用的方法如下:

if (row.IndexOf(pattern) > -1)

以前从来没有想过这样有什么问题,但最近需要处理较大数据量的字符串,需要从各个方面考虑如何提高处理的效率,其中“检测是否包含特定字符串”也是重要的一环。

几种方法

在.Net 2.0之后,其实有更简洁的方法 row.Contains(pattern),直接返回布尔值。看起来这种方法更原生态一些,可能效率更高。

此外,从正则表达式的角度来想,检测是否包含特定字符串其实是正则表达式最简单的一种应用,所以利用 Regex.IsMatch(row,pattern) 也是一种选择。

事实上,继续细分,会有如下几种方式:

1、Contains 方法

直接调用 row.Contains(pattern); 那么 Contains 方法到底是怎么实现的呢?这里有童鞋告诉我们 http://stackoverflow.com/questions/498686/net-is-string-contains-faster-than-string-indexof ,Contains 实际是调用了 IndexOf 方法。

public bool Contains(string value)
{
    return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
注意,这里的 IndexOf 方法还包含了第二个参数 StringComparison.Ordinal,而不带参数的 IndexOf 方法,其实应用的是默认的 StringComparison.CurrentCulture 参数。
至于这两种参数在性能上有什么区别,我们可以猜测默认的参数由于和系统的 Culture 相关,所以可能会有额外的性能开销。

2、IndexOf 方法

如在 Contains方法里讨论的,即使是同样调用 IndexOf 方法,也可能由于 StringComparison 参数的不同而有不同的效率,所以实际上 IndexOf 方法可以再细分为

row.IndexOf(pattern) > –1;

row.IndexOf(pattern,StringComparison.Ordinal) > –1;

3、Regex

使用正则表达式,也可以分为两种情况:

1) 直接调用 Regex 的静态方法。Regex.IsMatch(row,pattern);

2) 构造一个 Regex 类型的实例,然后用实例的方法来检测。这样的好处是在初始化的时候就设好正则规则,而不需要每次动态设置。

而构建一个 Regex 类型的实例也会有多种方法,最简单的当然是直接 var regex = new Regex(pattern); 也可以在构建时增加 RegexOptions.Compiled 参数,将正则规则编译到内存中,还可以更麻烦一点,利用 Regex.CompileToAssembly 方法,将正则规则编译到 Dll 里,然后引用 Dll,这样节省了每次编译的消耗。具体如何使用 Regex.CompileToAssembly 方法,请参考 http://topic.csdn.net/u/20100510/10/c140542a-5624-4c5c-8e52-587b50315d05.html

效率比较

在做测试之前,我们可以先根据上述几种方法的特点做个预测:

  1. IndexOf 方法中,带 StringComparison.Ordinal 参数的应该比不带的效率高,而 Contains 方法可能效率稍弱于带 StringComparison.Ordinal 参数的 IndexOf 方法,因为毕竟多了一层方法的调用,同时效率应该高于不带参数的 IndexOf 方法。
  2. Regex 方法中,构造实例应该比静态方法的效率高,而使用 CompileToAssembly 的效率应该高于使用 RegexOptions.Compiled 参数,而使用 RegexOptions.Compiled 参数的效率应该高于不使用参数。
  3. Regex 的方式和 IndexOf 的方式本质不同,无法单凭猜测作出比较。

下面就做一个性能测试。测试数据是一个1G的文件,大概有一百万行的数据,每行进行一次比较。每种方法运行十次,取后九次的平均运行时间(避免第一次有 .Net 冷启的差异)。共测试了8种方法:

  1. row.Contains(pattern)
  2. row.IndexOf(pattern) >= 0
  3. row.IndexOf(pattern) > –1
  4. row.IndexOf(pattern, StringComparison.Ordinal) >= 0
  5. var regex = new Regex(pattern, RegexOptions.Compiled);
    regex.IsMatch(row)
  6. var regex = new Regex(pattern);
    regex.IsMatch(row)
  7. Regex.IsMatch(row, pattern)
  8. var regex = new CompiledRegex.GVD(); //编译到Dll里面的正则表达式
    regex.IsMatch(row)

测试结果如下:

image

可以看到,这里 Contains 方法和带 StringComparison.Ordinal 参数的方法以及非静态的 Regex方法效率类似,Regex 方法似乎性能略优,但很不明显;静态的 Regex 方法属于第二梯队,而直接调用无参的 IndexOf 方法效率垫底。基本符合我们之前的猜测。

结论

  1. 一般情况下直接使用 Contains 方法,因为该方法最简洁明了,而且效率也很高。
  2. 如果对性能比较偏执,而要处理的数据量并不是特别大的情况,使用 row.IndexOf(pattern, StringComparison.Ordinal) >= 0 方法。不用 Regex 的原因是,在构造 Regex 实例的时候也要消耗一定性能,如果要处理的数据又不是特别大,使用 Regex 带来的好处无法抵消这一消耗,总的性能是降低的。
  3. 在 Regex 的使用中,编译到 Dll 中性能最好,但也最麻烦,除非非常复杂的正则,否则没必要;使用 RegexOptions.Compiled 编译到内存中在每次处理时性能会提升,但最初编译的性能消耗也很可观,所以要视需要处理的数据量而定。Regex 的静态方法虽然方便,但只推荐在不需要重复使用正则时使用。
  4. 在这里看起来使用 > –1 和 >= 0,虽然结果相同,但性能似乎有所不同,不知道 >= 0是否因为包含了一个“或”的原因,导致性能略有下降,这点存疑。

此外,这里还有一篇研究 IndexOf 的性能的文章 http://www.dotnetperls.com/indexof。其中比较有意思的一点是,对于单独一个字母 a,使用 IndexOf('a') 的性能比 IndexOf("a") 的性能高很多