2009-11-02 5 views
1

Voici le code d'évaluateur d'expression très simple en utilisant IronRubyIronRuby problème de performances lors de l'utilisation des variables

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); 
    } 
} 

et est ici problème.

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); 

premier est 25 fois plus lent que secondes. Aucune suggestion? String.Replace n'est pas une solution pour moi.

+0

vous pouvez également mettre en cache CompiledCode au lieu de ScriptSource –

Répondre

2

Je ne pense pas que la performance que vous voyez est due au réglage variable; la première exécution de IronRuby dans un programme sera toujours plus lente que la seconde, indépendamment de ce que vous faites, puisque la plupart du compilateur n'est pas chargé tant que le code n'est pas exécuté (pour des raisons de performances au démarrage). Veuillez réessayer cet exemple, en exécutant peut-être chaque boucle de votre code en boucle, et vous verrez que la performance est à peu près équivalente; la version-variable a une certaine surcharge de méthode-dispatch pour obtenir les variables, mais cela devrait être négligeable si vous l'exécutez assez.

De même, dans votre code d'hébergement, comment se fait-il que vous conserviez ScriptScopes dans un dictionnaire? Je tiens à CompiledCode (résultat de engine.CreateScriptSourceFromString (...). Compile()) à la place - car cela aidera beaucoup plus dans les répétitions.

+0

oueah Compile() améliore considérablement les performances. –

0

vous pouvez bien sûr d'abord construire la chaîne quelque chose comme

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

Ou vous pouvez le faire une méthode

si au lieu de votre script vous retournez une méthode alors vous devriez pouvoir l'utiliser comme un objet régulier 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) 

Ceci n'est probablement pas un extrait de travail, mais il montre l'idée générale.

Questions connexes