Domanda

Ecco il codice di molto semplice di espressioni utilizzando 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);
    }
}

e qui è problema.

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

vs

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

In primo luogo è 25 volte più lento di secondo. Eventuali suggerimenti? String.Replace non è una soluzione per me.

È stato utile?

Soluzione

Non credo che le prestazioni che state vedendo è dovuto la regolazione variabile; la prima esecuzione di IronRuby in un programma sta andando sempre essere più lento rispetto al secondo, indipendentemente da quello che stai facendo, dal momento che la maggior parte del compilatore non è caricato fino a quando il codice viene effettivamente eseguito (per motivi di prestazioni di avvio). Si prega di provare questo esempio di nuovo, forse in esecuzione ogni versione del codice in un ciclo, e vedrete la prestazione è più o meno equivalente; la variabile versione ha un certo overhead di metodo-spedizione per ottenere le variabili, ma che dovrebbe essere trascurabile se si esegue abbastanza.

Inoltre, nel codice di hosting, come mai si sta svolgendo su ScriptScopes in un dizionario? Vorrei tenere su CompiledCode invece (risultato di engine.CreateScriptSourceFromString (...) Compilare ().) -. Come che vi aiuterà molto di più nei funzionamenti di ripetizione

Altri suggerimenti

è possibile, naturalmente, prima costruire la stringa di qualcosa come

evaluator.Evaluate (String.Format ( "a = {0}; b = {1}, a + b + 2", 10, 1))

In alternativa si può rendere un metodo

se al posto dello script ritorni un metodo allora si dovrebbe essere in grado di usarlo come un normale oggetto C # Funz.

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)

Questa non è probabilmente un frammento di lavoro ma dimostra l'idea generale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top