.NET Flee 字符串表达式动态解析,怎么性能优化!!

2024-04-23 19:44:40 浏览数 (2)

Flee

使用介绍

Flee (支持 Net6.0, Net5.0, Netstandard2.1, Netstandard2.0) 动态解析的框架是有几个的,个人先使用了DynamicExpresso,但是需求中是需要支持IF/ELSE的,DynamicExpresso中支持三目运算,可以代替IF/ELSE,需要对字符串表达式进行IF/ELSE到三目运算的转换才能使用,之后发现了Flee直接支持。 DynamicExpresso和Flee相比较,个人感觉Flee的性能更好,支持的功能也比较多。Flee支持自定函数,可以进行类的导入,其他变量等各个框架都有的功能就不详细说了。大家可以体验自行对比下。

DynamicExpresso Flee

在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

Flee的用法都可以参照官网的demo进行使用,还是比较详细的。

性能优化

在我项目中的场景是需要对表达式相同,但其中变量不同的表达式进行多次运算。 我这里大概需要循环2w次左右,有2w条数据需要计算

第一种 直接循环
代码语言:javascript复制
                for (int i = 0; i < scurveFormulasSource.Count; i  )
                {
                 	ExpressionContext context = new ExpressionContext();
                	context.Imports.AddType(typeof(Math));
                	 //赋值变量
                    foreach (var item in scurveFormulasSource[i])
                    {
                        context.Variables[item.Key.Replace("*", "")] = item.Value;
                    }
                	IGenericExpression<double> exp = context.CompileGeneric<double>(input.Text);
 
                    double result = Math.Round(exp.Evaluate(), 2);
                }

这样计算大概需要4s

第二种 共用表达式

因为我每次的表达式是相同的,所以我想着可以用一个表达式,也就是IGenericExpression<double> exp = context.CompileGeneric<double>(input.Text);这段代码提取出来,不参与循环,循环中只进行赋值。如下代码

代码语言:javascript复制
                ExpressionContext context = new ExpressionContext();
                context.Imports.AddType(typeof(Math));
                IGenericExpression<double> exp = context.CompileGeneric<double>(input.Text);
                for (int i = 0; i < scurveFormulasSource.Count; i  )
                {
                	 //赋值变量
                    foreach (var item in scurveFormulasSource[i])
                    {
                        context.Variables[item.Key.Replace("*", "")] = item.Value;
                    }

                    double result = Math.Round(exp.Evaluate(), 2);
                }

这样的代码运行后会报错,提示找不到我定义的变量,在GenericExpression<double> exp = context.CompileGeneric<double>(input.Text); 构建表达式的时候就会进行变量检查,如果没有表达式里的变量就会抛出异常。

我们可以做如下处理,在构建表达式之前先对变量进行赋值定义,之后再修改值 这样就不会抛出异常了。如下

代码语言:javascript复制
                ExpressionContext context = new ExpressionContext();
                context.Imports.AddType(typeof(Math));
                 //赋值变量
                foreach (var item in scurveFormulasSource[i])
                {
                	context.Variables[item.Key.Replace("*", "")] = item.Value;
                }
                IGenericExpression<double> exp = context.CompileGeneric<double>(input.Text);
                for (int i = 0; i < scurveFormulasSource.Count; i  )
                {
                	 //赋值变量
                    foreach (var item in scurveFormulasSource[i])
                    {
                        context.Variables[item.Key.Replace("*", "")] = item.Value;
                    }

                    double result = Math.Round(exp.Evaluate(), 2);
                }

在获取表达式之前先定义出变量,之后修改值,这样修改后本次的运行时间为20毫秒左右。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3f60ifl542yok

0 人点赞