Slow .Eval Performance

Oct 4, 2009 at 9:42 PM

Hi,

i created an application that uses alot of .Eval calls to evaluate scheme expressions. As it turned its, alot of calls are pretty slow (~ 4 ms per call). 
As i found it (with dotTrace), the problem is the ScriptModule Microsoft.Scripting.ScriptDomainManager.CreateModule(String, ScriptCode []) call that is made for every eval call. 

Is there a way to speed up the .Eval calls (especially when always the same expression is used)?

Greetings

 

Coordinator
Oct 4, 2009 at 10:27 PM

Hi

Your observations are understandable.

Can you provide a few examples of how you use it?

I can probably tell you how to make it faster.

Cheers

leppie

Oct 5, 2009 at 8:48 AM

Hi,

i cannot provide the code i use (way too big), but i made an tiny example to demostrate the problem:

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using IronScheme;
using IronScheme.Hosting;
using Microsoft.Scripting;

namespace IronSchemePerformance
{
  class Program
  {
    static void Main(string[] args)
    {
      var prov =
        ScriptDomainManager.CurrentManager.GetLanguageProvider(typeof(IronSchemeLanguageProvider)) as
        IronSchemeLanguageProvider;
      var engine = prov.GetEngine();

      engine.Execute("(define (simple a b) (+ a b))");

      var watch = new Stopwatch(); watch.Start();
      int i = 0;
      for (i = 0; i < 1000; i++)
      {
        var result = "(simple 10 {0})".Eval(i);

      }
      Console.WriteLine("evaluation of {0} functions took: {1} ms", i, watch.ElapsedMilliseconds);
    }
  }
}

it takes ~ 4500 ms to make 1000 eval calls. 

Greetings

 

 

 

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using IronScheme;
using IronScheme.Hosting;
using Microsoft.Scripting;
namespace IronSchemePerformance
{
  class Program
  {
    static void Main(string[] args)
    {
      var prov =
        ScriptDomainManager.CurrentManager.GetLanguageProvider(typeof(IronSchemeLanguageProvider)) as
        IronSchemeLanguageProvider;
      var engine = prov.GetEngine();
      engine.Execute("(define (simple a b) (+ a b))");
      var watch = new Stopwatch(); watch.Start();
      int i = 0;
      for (i = 0; i < 1000; i++)
      {
        var result = "(simple 10 {0})".Eval(i);
      }
      Console.WriteLine("evaluation of {0} functions took: {1} ms", i, watch.ElapsedMilliseconds);
    }
  }
}

 

 

Coordinator
Oct 5, 2009 at 8:57 AM

Thanks

That's good enough to explain how  :)

Will post something in a little while.

Cheers

leppie

Coordinator
Oct 5, 2009 at 9:04 AM
Edited Oct 5, 2009 at 9:09 AM

This is what I get with the addition below:

evaluation of 1000 functions took: 2884 ms ; your way
evaluation of 100000 functions took: 29 ms ; my way

29ms is good?  ;)

 

var simple = "simple".Eval<Callable>();

watch = Stopwatch.StartNew();

for (i = 0; i < 100000; i++)
{
  var result = simple.Call(10, i);
}

Console.WriteLine("evaluation of {0} functions took: {1} ms", i, watch.ElapsedMilliseconds);

 

Note the increase in iterations, 100 times more, 1000 gave me a 0ms result.

I would think that is pretty acceptable!

Cheers

leppie

PS: 10 000 000 still only take 2 seconds. You could speed it up even more if you know it will always be fixnums. IOW use fx+. This gives you another 25% boost on my example.

Oct 5, 2009 at 9:06 AM

Thanks alot. Thats excatly what i've been looking for.

Coordinator
Oct 5, 2009 at 9:10 AM

No problem :)

Eval does quite a lot more as you can see, but once you can get hold of a Callable, you can make it go fast!