This project has moved. For the latest updates, please go here.

Performance...

Jul 31, 2014 at 2:19 PM
Edited Jul 31, 2014 at 3:01 PM
Hi - First off: great job on this ClearScript!

I have a question about performance when invoking many small script blocks in a web application - short explanation:
  • I have a proprietary language that utilizes JavaScript as it's scripting language. It is an interpreted language written in .net (so its an interpreted, interpreted language!).
  • It is a web based application and a 'scripting' context is created per request.
  • At run-time, all conditions/logic etc are all evaluated with calls to the scripting engine.
  • My current scripting engine is an older Rhino port (https://code.google.com/p/ecmascript-net/) that is all managed (good performance) but not sure how well maintained/documented.
I was reading that with ClearScriptV8, as it is high performing with no thread affinity - this would be a great replacement!
I have implemented a ClearScriptV8 version and tested with performance about 10x slower than what I have now.
The implementation is very simple - essentially a new ClearScriptV8Scripting instance is created per request, and during that call many requests to evaluateScript are called.
    public class ClearScriptV8Scripting : IScriptEngine
    {
        private V8ScriptEngine engine;

        public ClearScriptV8Scripting()
        {
            engine = new V8ScriptEngine();
        }

        public String evaluateScript(String script)
        {
            Object result = engine.Evaluate(script);
            return (result == null || result is Microsoft.ClearScript.Undefined) ? string.Empty : result.ToString();
        }

        public String callFunction(String function, String[] parameters)
        {
            Object result = engine.InvokeFunction(function, parameters);
            return result == null ? string.Empty : result.ToString();
        }

        public String[] convertToArray(String strArr) 
        {
            dynamic arr = engine.Evaluate(strArr);
            String[] result = new String[arr.length];

            for (int i = 0; i < arr.length; i++)
            {
                result[i] = arr[i].ToString();
            }
            return result;
        }
    }

//extension for calling a function directly from c#
 public static class ClearScriptEngineExtensions
    {
        public static object InvokeFunction(this Microsoft.ClearScript.ScriptEngine engine, string name, object[] args)
        {
            var host = new HostFunctions();
            ((IScriptableObject)host).OnExposedToScriptCode(engine);
            var del = (Delegate)host.func<object>(args.Length, engine.Script[name]);
            return del.DynamicInvoke(args);
        }
    }
I'm just curious if anyone has any ideas on how I can improve my performance evaluating javascript snippets?

Thanks,

Jules
Coordinator
Jul 31, 2014 at 6:32 PM
Hi Jules,

Thanks for giving ClearScript a try. A few questions:

  1. How are you measuring performance? For example, are you looking at the average time to process a request, average time within evaluateScript(), etc.?
  2. What do the scripts you're running look like, in general? How large are they? Are they static, or generated on the spot? How many different ones are there?
  3. Do your scripts access host objects and/or types?
  4. Does your application process multiple requests simultaneously? If so, what is your concurrency model?
  5. The ClearScriptV8Scripting class above seems to provide no facility for disposing its internal V8ScriptEngine instance. Is that something you left out, or are you actually not disposing those instances?
Thanks!
Jul 31, 2014 at 7:29 PM
Hi ClearScript
Answers below:

ClearScript wrote:
How are you measuring performance? For example, are you looking at the average time to process a request, average time within evaluateScript(), etc.?
We are testing, with average time taken to call evaluateScript() (scenarios: string operations, numeric, array, ternary & conditional etc....)
What do the scripts you're running look like, in general? How large are they? Are they static, or generated on the spot? How many different ones are there?
Our scripts are generated on the fly, so we call the evaluateScript method above for each script block.
the majority of our script blocks would be some sort of conditional expression (ie "xx" !=null && 1 > 0) something that would be in an 'if' expression.
Do your scripts access host objects and/or types?
No they do not.
Does your application process multiple requests simultaneously? If so, what is your concurrency model?
It is a web application running in IIS7/8, so it handles multiple requests via the worker processes. At an application level - it would be single threaded synchronous requests.
The ClearScriptV8Scripting class above seems to provide no facility for disposing its internal V8ScriptEngine instance. Is that something you left out, or are you actually not disposing those instances?
Nope i am not Disposing it! The entire request will be disposed when completed, that in-turn should dispose the V8Engine. But I can explicitly dispose it.


Thanks,

Jules
Coordinator
Aug 1, 2014 at 11:47 AM
Hi Jules,

Thanks for your responses.

So you're timing only the execution of very small scripts that are generated on the fly and don't access host resources. If that's correct, then it's likely that what you're measuring is mostly the overhead of invoking V8 via ClearScript, which is relatively high because of the transition from managed to native code. A 100% managed interpreter such as Jint might be a better fit for you.

If you choose to stick with ClearScript and would like to improve your overall request processing throughput, consider using a pool of V8 engine instances instead of creating a new one for each request. Also, we strongly recommend that you dispose V8 instances explicitly; each instance reserves a very large block of address space, so it's important not to let them pile up until garbage collection takes place.

Good luck!
Aug 1, 2014 at 1:54 PM
Hi,

Thanks for the response, I assumed this would be the overhead.

Yes I am timing the overhead of invoking the 'evaluate' method repeatedly. Not the overhead of the creating the engine.

Thanks for the suggestion.
I have used jint ( as well as others - jurassic, ironjs, etc.. ) in the past and found they didn't preform as well as well to current managed version ecmascript-net library that i am using. I'm not sure what ecma level the library adheres to, but might be due to the performance gain.

I will have a look again at Jint

thank you for the help,

Jules
Aug 2, 2014 at 6:19 PM
Edited Aug 3, 2014 at 5:35 AM
In my own tests I found that the JScript engine of ClearScript is way faster than the V8 engine in ClearScript.

I've did some looping with lots of creations of interpreters, here are some results:
ClearScript JScript one interpreter per loop : 00:00:00.7287686.
ClearScript JScript two interpreters per loop: 00:00:01.0320185.
ClearScript JScript one interpreter          : 00:00:00.1482462.

ClearScript V8 one interpreter per loop      : 00:00:54.8219984.
ClearScript V8 two interpreters per loop     : 00:01:45.7223841.
ClearScript V8 one interpreter               : 00:00:00.6268418.
So you can see that the creation of engines is expensive but also with just one engine at all, JScript is still more than 4 times faster than V8.

(I'm no performance expert, that are just tests I've documented here on Pastebin)
Coordinator
Aug 4, 2014 at 1:13 AM
Hello!

There's no question that V8 is heavier and more complex than JScript, and for some use cases the latter is a better choice. V8 pays off when given larger, more complicated scripts to execute. For example, ClearScriptBenchmarks runs SunSpider about 15 times faster with V8 (option 3) than with JScript (option 1).

Cheers!
Aug 5, 2014 at 4:40 PM
Hi,

I have also seen that the JScript version of ClearScript works quite well in my environment as well.
Better for micro benchmarks over v8 and jint.

I am considering moving to this over my old engine.
Is this version of JScripting fully managed? And what ECMA level does it adhere to?

Thanks,

Jules
Aug 6, 2014 at 5:44 AM
Jules, the JScript is "unmanaged" in terms of that it is part of the "Active Scripting" technologies of Microsoft which includes VBScript and JScript.

See this Wikipedia article for the ECMA version compatibility of the different JScript versions.
Coordinator
Aug 6, 2014 at 1:36 PM
Thanks for posting that, UweKeim! Just to clarify, ClearScript's JScriptEngine class defaults to the JScript 5.7 feature set. Specifying WindowsScriptEngineFlags.EnableStandardsMode selects the JScript 5.8 feature set, which includes the JSON object.
Aug 6, 2014 at 2:03 PM
UweKeim/ClearScript -

Thank you for the detailed information. This will really help!

Jules