❤️ 从125ms到11ms,记一次关键字检测过滤服务的优化 -python and Pythonnet
接上文:《高效的的关键字查找和检测(哈希表和Trie前缀树和FastCheck)在实际使用中的性能》
动态语言是很慢的,它更多的是为了提高开发效率,这里的关键字过滤算法在生产环境中用原生python达到125ms 2千万字/每秒已经够用了。那么是不是可以适当的优化再快一点?
Cython,没事cython一下,带你飞
cython能把大部分python代码改为静态的c实现,甚至你可以混合c和python一起写。不过现实是大部分的pythoner如果碰到性能问题要么用go要么就是用csharp,很少去写cython。下面是用cython编译后的测试结果:

提升39%,马马虎虎,也可能跟Tool.Good源码的实现有关。此时文本的处理量已经到了3400万/每秒,用是够用了,那么能不能更快一点?
C# 是时候展现你的实力了
Tool.Good作者明显是一位纯粹的csharpner, 既然已经实现了3亿效率的代码为什么不拿来用呢。这里作为对比,我先写了一个参照的测试程序,测试环境与前文相同。代码如下
using System;
using ToolGood.Words;
namespace KeywordTest
{
class Program
{
static void Main(string[] args)
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
string post = System.IO.File.ReadAllText(@"D:\Projects\Opensource\ToolGood.Words\csharp\KeywordTest\sample_post");
string[] spams = System.IO.File.ReadAllLines(@"D:\Projects\Opensource\ToolGood.Words\csharp\KeywordTest\SpamWordsCN.min.txt");
StringSearch iwords = new StringSearch();
iwords.SetKeywords(spams);
stopwatch.Start();
for (var i = 0; i < 500; i++)
{ var f = iwords.FindFirst(post); }
stopwatch.Stop();
var s = stopwatch.ElapsedMilliseconds;
Console.WriteLine("测试用时(ms):" + s);
}
}
}

Csharp性能都这样了更别说C了,那么为什么能比cython快那么多呢。这里分两部分原因,一部分性能浪费在python和c的交互上,另一部分在cython编译时的类型推断和生成的代码优化不够,大量使用的还是pure python。咱不纠结这个,手头有这么快的csharp不用简直浪费,一脚踢走cython,黏上csharp,让它飞的更高~

Pythonnet 闪亮登场
这可是个好东西,.net基金会项目,官方身份,神秘可靠。有了它使得python和.net交互变得简单。这里需要一提的是目前稳定版2.5.2还只支持.net 4.0,至于.net core 3和.net5需要手动安装master分支上的3.0.0dev,实现方式 也有所不同,下面是代码:
def test2():
from clr_loader import get_coreclr
from pythonnet import set_runtime
rt = get_coreclr("./runtimeconfig.json")
set_runtime(rt)
import clr
clr.AddReference('ToolGood.Words')
import clr
from System import String
from ToolGood.Words import StringSearch
stringSearch=StringSearch()
with open('./sample_post',encoding='utf-8') as f:
test_post = f.read()
from System.Collections.Generic import List
spam_words=List[String]()
with open('././SpamWordsCN.min.txt',encoding='utf-8') as f:
for line in [line.rstrip() for line in f]:
spam_words.Add(String(line))
stringSearch.SetKeywords(spam_words)
import time
start = time.time()
times = 500
while times > 0:
f = stringSearch.FindFirst(test_post)
times -= 1
end = time.time()
print('程序运行时间:%s毫秒' % ((end - start) * 1000))
{
"runtimeOptions": {
"tfm": "net5.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "5.0.2"
}
}
}

事实上如果增加压力还能提高性能,因为交互部分压力越大性价比越高。此时的处理速度已经到了2.5亿/每秒。那么能不能再快点?烦不烦,其实也不烦,生产中怎么可能不并行呢,动不动八核十几核的,线程再来double一下,妥妥的几十亿。
作者:today4king
出处:https://www.cnblogs.com/jinzhao/p/14788910.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2009-05-20 动网PDO
2007-05-20 精品收藏!
2007-05-20 IntelliSense
2007-05-20 比赛