Quantcast
Channel: ClearScript
Viewing all 2297 articles
Browse latest View live

New Post: Problem Calling VBScript Function

$
0
0
That's great news. I was beginning to think there may be a problem with my system or I was going crazy.

Any time
frame on getting the fix sent out?

New Post: Strong Name

$
0
0
If you don't release official binaries, who's responsible for the ClearScript packages on NuGet?

New Post: Strong Name

$
0
0
All NuGet packages are provided and maintained by their owners. Please see the package page for owner information.

New Post: Problem Calling VBScript Function

$
0
0
We're currently on track to post the ClearScript 5.3.11 source code later this week.

New Post: Benchmarks

$
0
0
What is GlobalMembers support?

When I ran the test below, I only see a small performance increase after disabling global members. Also, I compared it with Javascript.NET and the differences is huge. But if I compiled the script before running it, it is almost 2~3X of Javascript.NET. (Our application needs to update hundreds if not thousands of items when a property is modified, so measuring performance like this is very important)

Script is "Math.random();"

Clearscript in 942
Clearscript with DisableGlobalMembers in 930
Javascript.NET in 21

//After compiled
Clearscript in 57
Clearscript with DisableGlobalMembers in 53
Javascript.NET in 27
public static void TestClear(string script, bool disableGlobal)
{
    var engine = new V8ScriptEngine(disableGlobal ? V8ScriptEngineFlags.DisableGlobalMembers : V8ScriptEngineFlags.None);
    
    var sw = new Stopwatch();
    sw.Start();

    //var compiled = engine.Compile(script);

    for (int i = 0; i < 10000; i++)
    {
        //engine.Evaluate(compiled);
        engine.Evaluate(script);
    }

    sw.Stop();
    Console.WriteLine("Clearscript" + (disableGlobal ? " with DisableGlobalMembers" : "") + " in " + sw.ElapsedMilliseconds);
}

New Post: Benchmarks

$
0
0
I notice the bottleneck is here
var uniqueName = documentNameManager.GetUniqueName(documentName, "Script Document");
It is generating a new name even the same script is being executed twice. If I changed it to
uniqueName = code.GetHashCode().ToString() // Just an example to create a unique code based on the script
If the same script is being executed twice, it will run extremely fast and efficient (Should have the same performance as compiling the script).

I think Javascript.NET has similar optimization because the first code below runs almost 8~10x slower than the second one
for (int i = 0; i < 10000; i++)
{
      engine.Run("Math.random() + " + i);
}

for (int i = 0; i < 10000; i++)
{
      engine.Run("Math.random()");
}

New Post: Benchmarks

$
0
0
Hi ravetam!

GlobalMembers is an old Windows script engine feature that we added to V8ScriptEngine for API compatibility. It allows you to expose a host object so that its members (rather than the object itself) appear as global properties within the script environment. Support for this feature is expensive on V8 even when it remains unused, so the only way to avoid the performance hit is to disable it completely.

Now, as for your performance numbers...

V8 executes "Math.random()" extremely quickly; if you move the loop into script code, you'll see that it can run 10,000 iterations in just a couple of milliseconds. In fact, compiling such a script probably makes little or no difference in terms of execution speed. What you're really measuring there is the overhead of invoking V8 via ClearScript vs. JavaScript.NET.

We took a look and were surprised to find that generating a unique script name represents most of ClearScript's overhead. When you compile the script you do this once as opposed to 10,000 times, and that explains the improvement over raw script execution. We'll definitely take a closer look at this.

The remaining difference - approximately twice the invocation overhead for ClearScript vs. JavaScript.NET - is likely due to differences in library design. JavaScript.NET is definitely lighter, and its single-assembly design is an advantage.

Thanks for bringing this to our attention!

New Post: Benchmarks

$
0
0
Thanks for the explanation on GlobalMembers.

I just realize that the script still works even no unique name is generated (Using a same document name). Is there any pitfall or anything that I should be aware of if i plan on using that?

New Post: Benchmarks

$
0
0
Heh, it looks like we were investigating simultaneously :)

It is generating a new name even the same script is being executed twice.

Right. When you call a method that takes the code as a string, ClearScript considers it a new script. It doesn't cache the code for subsequent lookup, deferring to the underlying script engine for that sort of optimization. It might benefit from doing what you suggest, but the code cache could also explode under some usage patterns.

By the way, the unique script name is just metadata that shows up in script debuggers; it doesn't affect script execution. JavaScript.NET doesn't bother with script names at all, probably because it doesn't support script debugging.

If the same script is being executed twice, it will run extremely fast and efficient (Should have the same performance as compiling the script).

If that's how it works, then V8 does it all under the covers. Neither ClearScript nor JavaScript.NET look up previously compiled scripts. When given a code string to execute, they both call V8's compilation method and then its execution method.

I think Javascript.NET has similar optimization because the first code below runs almost 8~10x slower than the second one

It's possible that V8 does what you suggest behind the scenes, but it could also be that V8 optimizes "Math.random()" completely away when it detects that your script doesn't use the return value.

Cheers!

New Post: Benchmarks

$
0
0
I just realize that the script still works even no unique name is generated (Using a same document name). Is there any pitfall or anything that I should be aware of if i plan on using that?

Only that you might confuse script debuggers. Come to think of it, we've never tested debugging support without unique script names.

New Post: Benchmarks

$
0
0
Heh, it looks like we were investigating simultaneously :)
Yeah, love the extension method and ability to add host type (enum, static class) in Clearscript. Just trying to make it work.
Only that you might confuse script debuggers. Come to think of it, we've never tested debugging support without unique script names.
Good point but maybe you can consider only turning on unique script name generation when this flag is present? V8ScriptEngineFlags.EnableDebugging

New Post: Benchmarks

$
0
0
Good point but maybe you can consider only turning on unique script name generation when this flag is present? V8ScriptEngineFlags.EnableDebugging

We'd prefer to keep the unique names for now, as they also show up in script error stack traces, which V8 makes available even when debugging is disabled. With some improvements we're making in the next release, generating a unique name takes approximately 600 nanoseconds on an old Core i7 920 PC; this is unlikely to affect real-world script execution times significantly. Besides, if you're executing a script many times, you can compile it to eliminate the overhead.

New Post: Passing javascript objects to c# native code

$
0
0
I'm trying to create a command-prompt with a functionality like the console.log in my engine.
    public class Konsoll
    {
        public void log(dynamic o)
        {
            Console.WriteLine("Type:" + o.GetType());
            Console.WriteLine(o.ToString());
            // var p = (Microsoft.ClearScript.V8.V8ScriptItem)o;

            // foreach (o.GetType().)
        }

    }
used like this
            using (var engine = new V8ScriptEngine())
            {

                engine.AddHostObject("console", new Konsoll());
                string str;
                while ((str = Console.ReadLine()) != "end")
                {
                    engine.Execute(str);
                }
            }
            Console.ReadLine();
        }
How would you recommend to do this? It would be a very nice start if you made V8ScriptItem public. Maybe this object should rather be of type ExpandoObject?

New Post: Passing javascript objects to c# native code

$
0
0
I found a solution. The V8ScriptItem is a DynamicObject - so this works:
    public class Konsoll
    {
        private void logg(int indent, dynamic o)
        {
            foreach (string egenskap in o.GetDynamicMemberNames())
            {
                Console.Write(new String(' ', indent));
                Console.Write(egenskap);
                Console.Write(':');
                
                if (o[egenskap] is System.Dynamic.DynamicObject)
                {
                    Console.WriteLine();
                    logg(indent + 1, o[egenskap]);
                }
                else
                {
                    Console.WriteLine(o[egenskap].ToString());
                }
            }
        }
        public void log(dynamic o)
        {
            logg(0, o);
        }

    }
so
engine.Execute("console.log({v1:4,v2:['a','bc', 'de', {f:'g'}],h:1,i:2,j:3,k:4});");
will output
v1:4
v2:
 0:a
 1:bc
 2:de
 3:
  f:g
h:1
i:2
j:3
k:4
Clearscript is really cool stuff.

New Post: Passing javascript objects to c# native code

$
0
0
Glad that you found a solution!

V8ScriptItem is just a concrete implementation of DynamicObject. It doesn't have any additional members that would be useful to the host. The idea is that you either use its DynamicObject members, or you use it via the dynamic keyword.

By the way, it would probably be best to minimize your use of the dynamic machinery. Declaring a variable as dynamic causes the compiler to emit a dynamic callsite everywhere that variable is used, and that could get very expensive, especially when combined with the overhead of invoking V8. Consider rewriting your class something like this:
publicclass Konsoll {
    privatevoid logg(int indent, DynamicObject od) {
        foreach (string egenskap in od.GetDynamicMemberNames()) {
            Console.Write(new String(' ', indent) + egenskap + ':');
            object m = ((dynamic)od)[egenskap]; // this is the only dynamic callsitevar md = m as DynamicObject;
            if (md != null) {
                Console.WriteLine();
                logg(indent + 1, md);
            }
            else {
                Console.WriteLine(m);
            }
        }
    }
    publicvoid log(DynamicObject od) {
        logg(0, od);
    }
}
Another option might be to expose only System.Console and implement console entirely in script code.

Good luck!

New Post: using JSON.parse in a script

$
0
0
Hi again!

ClearScript 5.3.11 will support JScript 5.8 language enhancements, including the JSON object, but you'll have to enable them explicitly via a new flag. That's because these enhancements come with their own bugs and backward compatibility issues - part of the reason why websites back in the IE8 days had to opt-in to "Standards Mode" :)

Cheers!

New Post: Passing javascript objects to c# native code

$
0
0
Thanks for the warning. I wanted to know just how expensive the dynamic statement was - so I ran a test. The Console.Write was 3-4 times as fast, but to be fair, I added a third way "console.logs" deserializes a JavaScript literal and uses the same recursive printing style as console.log.
public class Konsoll
    {
        public int Indent = 0;
        public JavaScriptSerializer jss = new JavaScriptSerializer();
        public void logs(string s)
        {
            object o = jss.DeserializeObject(s);
            loggs(0, o);
        }
        private void loggs(int indent, object o)
        {
            if (o is Dictionary<string, object>)
            {
                foreach (KeyValuePair<string, object> kvp in (Dictionary<string, object>)o )
                {
                    Console.Write(kvp.Key);
                    Console.Write(':');
                    loggs(indent + Indent, kvp.Value);
                }
            }
            else if (o is Object[])
            {
                for (int i = 0; i < ((Object[])o).Length; i++)
                {
                    Console.Write(i);
                    Console.Write(':');
                    loggs(indent + Indent, ((Object[])o)[i]);
                }
            }
            else if (o == null)
            {
                Console.Write("null");
            }
            else
            {
                Console.Write(o.ToString());
            }

        }
        private void logg(int indent, object o)
        {
            
            if (o is System.Dynamic.DynamicObject)
            { 
                
                foreach (string egenskap in ((System.Dynamic.DynamicObject)o).GetDynamicMemberNames())
                {
                    // Console.Write(new String(' ', indent));
                    Console.Write(egenskap);
                    Console.Write(':');
                    logg(indent + Indent, ((dynamic)o)[egenskap]);
                }
            }
            else if (o == null)
            {
                Console.Write("null");
            }
            else
            {
                Console.Write(o.ToString());
            }
        }
        public void log(object o)
        {
            logg(0, o);
        }

    }
Writing a test:
            using (var engine = new V8ScriptEngine())
            {
                engine.AddHostObject("console", new Konsoll());
                engine.AddHostType("Console", typeof(System.Console));
                var start3 = DateTime.Now;
                for (int i = 0; i < 1000; i++)
                {
                    engine.Execute("Console.Write(JSON.stringify({v1:4,v2:['a','bc', 'de', {f:'g'}],h:1,i:2,j:3,k:4}));");
                }
                var tid3 = DateTime.Now.Subtract(start3);

                var start = DateTime.Now;
                for (int i = 0; i < 1000; i++ )
                {
                    engine.Execute("console.logs(JSON.stringify({v1:4,v2:['a','bc', 'de', {f:'g'}],h:1,i:2,j:3,k:4}));");
                }
                var tid = DateTime.Now.Subtract(start);
                var start2 = DateTime.Now;
                for (int i = 0; i < 1000; i++)
                {
                    engine.Execute("console.log({v1:4,v2:['a','bc', 'de', {f:'g'}],h:1,i:2,j:3,k:4});");
                }
                var tid2 = DateTime.Now.Subtract(start2);


                
                Console.WriteLine("static tok : " + tid.ToString());
                Console.WriteLine("dynamic tok : " + tid2.ToString());
                Console.WriteLine("Console.Write tok: " + tid3.ToString());
                string str;
                while ((str = Console.ReadLine()) != "end")
                {
                    engine.Execute(str);
                }
            }
Getting the result:
static tok : 00:00:05.3335333
dynamic tok : 00:00:05.6545654
Console.Write tok: 00:00:02.4172417
So the "static" console.logs alternative to dynamic only slightly cheaper.

In the logging example - I should just pass the jsonstring to .net, but generally, if I need to send a literal to .net in a predefined structure, it's ok to use dynamic. I think, however, there is one weakness in GetDynamicMemberNames: that you don't know if its an array or object. Is there another way of knowing?

New Post: Passing javascript objects to c# native code

$
0
0
So the "static" console.logs alternative to dynamic only slightly cheaper.

Right, but that's after you minimized your usage of the dynamic infrastructure. In your original implementation you declared o as a dynamic parameter, which led to unnecessary dynamic calls to GetDynamicMemberNames() and ToString(). You also redundantly evaluated o[egenskap] several times; each of those indexing operations is a dynamic call into the underlying script engine.

​​I think, however, there is one weakness in GetDynamicMemberNames: that you don't know if its an array or object. Is there another way of knowing?

For arrays, GetDynamicMemberNames() returns the valid indices as strings. If that's not what you're looking for, remember that examining script objects is often easiest to do in script code:
dynamic isScriptArray = engine.Evaluate("(function (x) { return x instanceof Array; })");

var result = engine.Evaluate("[1,2,3,4,5]");
if (isScriptArray(result)) {
    // do something
}
Cheers!

New Post: What is correct option to use ClearScript.V8 as NuGet package?

$
0
0
Hi guys,

Currently i faced with exception on MVC 4 app:
Cannot load V8 interface assembly; verify that the following files are installed with your application: ClearScriptV8-32.dll, ClearScriptV8-64.dll, v8-ia32.dll, v8-x64.dll
I run it on Win7 x64 on VS 2013 with installed all C++ packages.
All dlls (ClearScriptV8-32.dll, ClearScriptV8-64.dll, v8-ia32.dll and v8-x64.dll) included in project as Content and marked do not copy (as marked in some discussions before).

What`s wrong? what i need to make it works?

New Post: Calling VBScript function by dispatchId

$
0
0
Hi,

There is legacy application that wrote on delphi. It uses with a VB Script Engine.
The delphi code call VBScript function by dispatchId that cached during init script engine.
Is there a way in ClearScript call function by disptach id

Thanks.
Viewing all 2297 articles
Browse latest View live




Latest Images