C# 3.0 使用变量时IronRuby性能问题

C# 3.0 使用变量时IronRuby性能问题,c#-3.0,performance,ironruby,evaluation,C# 3.0,Performance,Ironruby,Evaluation,下面是使用IronRuby的非常简单的表达式计算器的代码 public class BasicRubyExpressionEvaluator { ScriptEngine engine; ScriptScope scope; public Exception LastException { get; set; } private static readonly Dictionary<string, ScriptSource&g

下面是使用IronRuby的非常简单的表达式计算器的代码

public class BasicRubyExpressionEvaluator
{
    ScriptEngine engine;
    ScriptScope scope;
    public Exception LastException
    {
        get; set;
    }
    private static readonly Dictionary<string, ScriptSource> parserCache = new Dictionary<string, ScriptSource>();
    public BasicRubyExpressionEvaluator()
    {
        engine = Ruby.CreateEngine();
        scope = engine.CreateScope();

    }

    public object Evaluate(string expression, DataRow context)
    {
        ScriptSource source;
        parserCache.TryGetValue(expression, out source);
        if (source == null)
        {
            source = engine.CreateScriptSourceFromString(expression, SourceCodeKind.SingleStatement);
            parserCache.Add(expression, source);
        }

        var result = source.Execute(scope);
        return result;
    }
    public void SetVariable(string variableName, object value)
    {
        scope.SetVariable(variableName, value);
    }
}
vs

var evaluator = new BasicRubyExpressionEvaluator();
evaluator.Evaluate("10+1+2", null);

第一个比第二个慢25倍。有什么建议吗?替换对我来说不是一个解决方案。

您当然可以先构建字符串,如下所示

evaluator.Evaluate(string.format(“a={0};b={1};a+b+2”,10,1))

或者你可以把它变成一种方法

如果不是返回脚本,而是返回一个方法,那么应该能够像使用常规C#Func对象一样使用它

var script = @"

def self.addition(a, b)
  a + b + 2
end
"

engine.ExecuteScript(script);
var = func = scope.GetVariable<Func<object,object,object>>("addition");    
func(10,1)
var脚本=@”
def自添加(a、b)
a+b+2
结束
"
engine.ExecuteScript(脚本);
var=func=scope.GetVariable(“加法”);
func(10,1)

这可能不是一个有效的代码片段,但它显示了总体思路。

我不认为您看到的性能是由于变量设置造成的;无论您在做什么,程序中第一次执行IronRuby总是比第二次慢,因为大多数编译器在代码实际运行之前(出于启动性能原因)不会加载。请再试一次,也许在循环中运行每个版本的代码,您将看到性能大致相当;变量版本确实有一些方法调度的开销来获取变量,但是如果运行足够的话,这应该可以忽略不计


另外,在宿主代码中,为什么要在字典中保留脚本作用域?我将保留CompiledCode(engine.CreateScriptSourceFromString(…).Compile())的结果,因为这将在重复运行中帮助更多。

您还可以缓存CompiledCode而不是ScriptSource
var script = @"

def self.addition(a, b)
  a + b + 2
end
"

engine.ExecuteScript(script);
var = func = scope.GetVariable<Func<object,object,object>>("addition");    
func(10,1)