写一个高性能的敏感词检测组件

最近写了一个高性能的敏感词检测组件【ToolGood.Words】。

一、高性能,它的效率到底有多快?

如果将正则表达式的算法效率设为1,高性能可达到正则表达式的1.5万倍。

 

二、选一个巧妙的算法:

AC自动机Aho-Corasick Automation)算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一;一个常见的例子就是给定N个单词,给定包含M个字符的文章,要求确定多少个给定的单词在文章中出现过;AC自动机在匹配文本时不需要回溯,处理时间复杂度与pattern无关,仅是target的长度O(N);构建AC自动机的时间复杂度。

AC自动机的构建主要由三个步骤:

2.1、针对所有模式串构建Trie树。

2.2、针对所有Trie树上的接点构建Fail指针:Fail指针指向的是如果当前节点匹配失败,则从通过Fail指针指向的新的节点开始匹配,但新的节点必须满足所在在新节点模式串的前缀必须是转移前的节点所在模式串的子串,也就是已经匹配成功的部分。

2.3、正式匹配过程:
a)从Trie树root节点开始,每次根据读入的字符沿着自动机向下移动。
b)当读入的字符,在分支中不存在时,递归走Fail指针路径。如果走Fail指针路径走到了root节点,则跳过该字符,处理下一个字符。
c)因为AC自动机是沿着文本移动的,所以在读取完所有输入文本后,最后递归走失败路径,直到到达根节点,这样可以检测出所有的模式。

 

三、优化AC自动机算法

细看AC自动算法匹配过程,在(b)步骤我们会发现节点匹配失败后会顺Fail指针继续执行,这个步骤可以优化,优化Fail指针,将相同的节点合并成一个同一个节点。

 

四、填平性能低洼地

优化AC自动机算法后,测试代码后会发现代码性能没有太大提升。

经测试发现,TrieNode获取下一节点的方法(TryGetValue)占用了90%的计算量。

分析Trie树有两个特点:1root节点下有大量子节点,2、中间节点的子节点数量很少。

优化TryGetValue方法:

1、root的子节点转成数组类型

2、修改TryGetValue方法内:

 

public  class  TrieNode
{
     public  bool  End {  get set ; }
     public  List< string > Results {  get set ; }
     private  Dictionary< char , TrieNode> m_values;
     private  uint  minflag =  uint .MaxValue;
     private  uint  maxflag =  uint .MinValue;
     //....
     public  bool  TryGetValue( char  c,  out  TrieNode node)
     {
         if  (minflag <= ( uint )c && maxflag >= ( uint )c) {
             return  m_values.TryGetValue(c,  out  node);
         }
         node =  null ;
         return  false ;
     }
}

 

五、优化后的代码段

 

public  class  StringSearch
{
         TrieNode _root =  new  TrieNode();
         TrieNode[] _first =  new  TrieNode[ char .MaxValue + 1];
         //.....
         public  bool  ContainsAny( string  text)
         {
             TrieNode ptr =  null ;
             for  ( int  i = 0; i < text.Length; i++) {
                 TrieNode tn;
                 if  (ptr ==  null ) {
                     tn = _first[text[i]];
                 else  {
                     if  (ptr.TryGetValue(text[i],  out  tn) ==  false ) {
                         tn = _first[text[i]];
                     }
                 }
                 if  (tn !=  null ) {
                     if  (tn.End) {
                         return  true ;
                     }
                 }
                 ptr = tn;
             }
             return  false ;
         }
}

 

 六、性能对比图,10W次对比

ToolGood.Words内的非法词(敏感词)检测类:StringSearchWordsSearchIllegalWordsSearchIllegalWordsQuickSearch;

注:C#自带正则很慢,StringSearch.ContainsAnyRegex.IsMatch效率的1.5万倍。

Regex.Matches的运行方式跟IQueryable的类似,只返回MatchCollection,还没有计算。

TrieFilter,FastFilter来源: http://www.cnblogs.com/yeerh/archive/2011/10/20/2219035.html

 

七、开源项目

码云: https://git.oschina.net/toolgood/ToolGood.Words

GitHub: https://github.com/toolgood/ToolGood.Words

原文地址:http://www.cnblogs.com/toolgood/p/6284718.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win10系统excel2019单元格显示完整的年月日时分秒设置方法

https://www.pianshen.com/article/88671983757/ win10系统excel2019单元格显示完整的年月日时分秒设置方法 技术标签&#xff1a; Windows excel显示年月日时分秒 excel显示完整的详细时间 excel2019显示完整时间 excel2019显示具体时间 excel显示具体的时间 描述&#…

Visual Studio现可使用EditorConfig

Visual Studio 2017的首个候选发布版&#xff08;VS2017RC&#xff09;中提供了支持EditorConfig标准的特性。秉承该标准可使开发人员一次性地定义一种编码风格&#xff0c;即可轻易地在不同的编辑器中使用该风格。另一显著优点是对于在EditorConfig文件中定义的风格&#xff0…

分库分表的事务处理机制

转载自 分库分表的事务处理机制 分布式事务 由于我们将单表的数据切片后存储在多个数据库甚至多个数据库实例中&#xff0c;所以依靠数据库本身的事务机制不能满足所有场景的需要。但是&#xff0c;我们推荐在一个数据库实例中的操作尽可能使用本地事务来保证一致性&#xff0…

如何优雅的使用RabbitMQ

RabbitMQ无疑是目前最流行的消息队列之一&#xff0c;对各种语言环境的支持也很丰富&#xff0c;作为一个.NET developer有必要学习和了解这一工具。消息队列的使用场景大概有3种&#xff1a; 1、系统集成&#xff0c;分布式系统的设计。各种子系统通过消息来对接&#xff0c;这…

hutool中身份证工具-IdcardUtil

JAVA工具例大全--根据身份编号获取户籍省份 发布于 2020-10-10 | 后端技术 | 浏览&#xff08;61&#xff09; | 评论&#xff08;0&#xff09;开场语(刷新后不一样):人生若只如初见&#xff0c;何事秋风悲画扇。作为一名IT人&#xff0c;你当然也想有自己一片天地&…

[Asp.Net Core轻量级Aop解决方案]AspectCore Project 介绍

AspectCore Project 介绍 什么是AspectCore Project ? AspectCore Project 是适用于Asp.Net Core 平台的轻量级 Aop(Aspect-oriented programming) 解决方案&#xff0c;它更好的遵循Asp.Net Core的模块化开发理念&#xff0c;使用AspectCore可以更容易构建低耦合、易扩展的We…

放松眼球的网站

http://www.spielzeugz.de/html5/liquid-particles-3D/

异步广度优先搜索算法

为什么要异步&#xff1f; CPU的工艺越来越小&#xff0c;Cannon Lake架构的Intel CPU已经达到10nm技术&#xff0c;因此在面积不变的情况下&#xff0c;核心数可以明显提升。单纯的提升主频将造成发热量大、需要的电压大、功耗大的问题。而传统的算法与数据结构是针对单核心单…

开箱即用 - jwt 无状态分布式授权

基于JWT(Json Web Token)的授权方式 JWT 是JSON风格轻量级的授权和身份认证规范&#xff0c;可实现无状态、分布式的Web应用授权&#xff1b; 从客户端请求服务器获取token&#xff0c; 用该token 去访问实现了jwt认证的web服务器。 token 可保存自定义信息&#xff0c;如用户基…

Java类加载器总结

转载自 Java类加载器总结 1.类的加载过程 JVM将类加载过程分为三个步骤&#xff1a;装载&#xff08;Load&#xff09;&#xff0c;链接&#xff08;Link&#xff09;和初始化(Initialize)链接又分为三个步骤&#xff0c;如下图所示&#xff1a; 1) 装载&#xff1a;查找并…

MyBatis-Plus EntityWrapper的使用 wrapper le ge

https://blog.csdn.net/shujuelin/article/details/99568651 MyBatis-Plus EntityWrapper的使用 脚丫先生 2019-08-14 14:43:43 2660 收藏 分类专栏&#xff1a; javaee 版权 调度Airflow 本专刊主要以调度系统Airflow详细讲解(会把工作中对于调度系统的docker容器化部署、…

又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)

之前在将 Memcached 客户端 EnyimMemcached 迁移 .NET Core 时被这个“坑”坑的刻骨铭心&#xff08;详见以下链接&#xff09;&#xff0c;当时以为只是在构造函数中调用异步方法&#xff08;注&#xff1a;这里的异步方法都是指基于Task的&#xff09;才会出线死锁&#xff0…

jvm类加载器以及双亲委派

转载自 jvm类加载器以及双亲委派 首先来了解几个概念&#xff1a; 类加载&#xff1a; 概念&#xff1a;虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验--转换解析--初始化&#xff0c;最终形成能被java虚拟机直接使用的java类型&#xff0c;就是jvm…

分布式系统搭建:服务发现揭秘

CAP理论 加州大学终身教授与著名计算机科学家Eric Allen Brewer在90年代末提出了CAP理论&#xff0c;理论断言任一个基于网络的分布式系统&#xff0c;最多只能满足“数据一致性”、“可用性”、“分区容错性”三要素中的两个要素。 该理论后被MIT证明可行&#xff0c;故架构师…

SSL / TLS 协议运行机制详解

转载自 SSL / TLS 协议运行机制详解 互联网的通信安全&#xff0c;建立在SSL/TLS协议之上。 本文简要介绍SSL/TLS协议的运行机制。文章的重点是设计思想和运行过程&#xff0c;不涉及具体的实现细节。如果想了解这方面的内容&#xff0c;请参阅RFC文档。 一、作用 不使用SS…

在ASP.NET Core Web API上使用Swagger提供API文档

我在开发自己的博客系统&#xff08;http://daxnet.me&#xff09;时&#xff0c;给自己的RESTful服务增加了基于Swagger的API文档功能。当设置IISExpress的默认启动路由到Swagger的API文档页面后&#xff0c;在IISExpress启动Web API站点后&#xff0c;会自动重定向到API文档页…

一文告诉你 Java RMI 和 RPC 的区别

转载自 一文告诉你 Java RMI 和 RPC 的区别 RPC 远程过程调用 RPC&#xff08;Remote Procedure Call Protocol&#xff09;远程过程调用协议&#xff0c;通过网络从远程计算机上请求调用某种服务。一次RPC调用的过程大概有10步&#xff1a; 1.执行客户端调用语句&#xff…

Java架构师必须知道的 6 大设计原则

转载自 Java架构师必须知道的 6 大设计原则 在软件开发中&#xff0c;前人对软件系统的设计和开发总结了一些原则和模式&#xff0c; 不管用什么语言做开发&#xff0c;都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则&#xff0c;和具体阐述意义。 开发…