Проблема с производительностью IronRuby при использовании переменных

StackOverflow https://stackoverflow.com/questions/1660887

Вопрос

Вот код очень простого средства вычисления выражений, использующего 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);

Во-первых, это в 25 раз медленнее чем второй.Есть какие-нибудь предложения?Струна.Замена - это не решение для меня.

Это было полезно?

Решение

Я не думаю, что производительность, которую вы видите, связана с настройкой переменной;первое выполнение IronRuby в программе всегда будет медленнее второго, независимо от того, что вы делаете, поскольку большая часть компилятора не загружается до тех пор, пока код фактически не будет запущен (из соображений производительности при запуске).Пожалуйста, попробуйте этот пример еще раз, возможно, запуская каждую версию вашего кода в цикле, и вы увидите, что производительность примерно эквивалентна;переменная-version действительно имеет некоторые накладные расходы на отправку метода для получения переменных, но это должно быть незначительным, если вы запустите его достаточно.

Кроме того, как получилось, что в вашем коде хостинга вы используете ScriptScopes в словаре?Я бы придерживался скомпилированного кода (результат работы движка.CreateScriptSourceFromString(...).Compile()) вместо этого - поскольку это намного больше поможет при повторных запусках.

Другие советы

конечно, вы можете сначала создать строку примерно так

оценщик.Оценить(string.format("a={0};b={1};a + b + 2", 10, 1))

Или вы можете сделать это методом

если вместо вашего скрипта вы возвращаете метод, то вы должны иметь возможность использовать его как обычный функциональный объект C #.

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)

Вероятно, это не рабочий фрагмент, но он показывает общую идею.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top