【问题标题】:IronRuby performance issue while using VariablesIronRuby 使用变量时的性能问题
【发布时间】:2009-11-02 12:00:17
【问题描述】:

这是使用 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);
    }
}

这是个问题。

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

对比

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

First 比 second 慢 25 倍。有什么建议么? String.Replace 不是我的解决方案。

【问题讨论】:

  • 你也可以缓存 CompiledCode 而不是 ScriptSource

标签: c#-3.0 performance ironruby evaluation


【解决方案1】:

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

另外,在您的托管代码中,您为什么要在字典中保留 ScriptScopes?我会保留 CompiledCode(engine.CreateScriptSourceFromString(...).Compile() 的结果)——因为这将在重复运行中帮助更多。

【讨论】:

    【解决方案2】:

    你当然可以先构建类似的字符串

    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)
    

    这可能不是一个有效的 sn-p,但它显示了总体思路。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      • 2011-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多