Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self-executing function changing dramatically the execution time #68

Open
rodrigoroma opened this issue Oct 29, 2016 · 8 comments
Open

Comments

@rodrigoroma
Copy link

Hi,

the first thing that I want to say is congratulations for your excellent work on Jurassic!

I've got an interesting case that I don't know if it is the normal behavior, a bug or if I'm doing something wrong.

Take the following code as an example:

Line 0001: (function () {
Line 0002:     var a = 0;
Line 0003:     
Line 0004:     a++;
Line 0005:     a++;
               .
               .
               .
Line 2002:     a++;
Line 2003:     a++;
Line 2004: })();

The above code runs in approximately 80ms but if I remove the self-executing function (lines 1 and 2004), it runs in something about 900ms.

If the "a++;" instruction is repeated 10k times instead of 2k, with the self-executing function it takes 120ms and without this function it gives "An unhandled exception of type 'System.StackOverflowException' occurred in Jurassic.dll"

Before running this Javascript code I do some other stuffs in the Jurassic engine but I don't think it's relevant. I can provide further details if necessary.

@paulbartrum
Copy link
Owner

That's very strange. I can't take a look right now, sorry, I'm on holiday :-) But I'll take a look when I get back.

@paulbartrum
Copy link
Owner

I tried it, but both the self-executing and non-self-executing function took about the same amount of time. Can you clarify exactly what code you were using when you experienced the slow execution and/or the stack overflow exception?

kpreisser added a commit to kpreisser/jurassic that referenced this issue Dec 8, 2016
@kpreisser
Copy link
Collaborator

kpreisser commented Dec 8, 2016

Hi @paulbartrum,

I can reproduce the StackOverflowException and the long run time just by creating a new ScriptEngine and executing the code from @rodrigoroma without the self-executing function expression, using Jurassic from the current master branch.

I have created a repro with commit kpreisser@49dda06. When I run this project on a 64-Bit machine (using VS 2015), I'm getting a StackOverflowException.

Thanks!

@rodrigoroma
Copy link
Author

Hi @paulbartrum and @kpreisser,

I've also created a simple program to reproduce this issue (it's attached).

My environment is Visual Studio Community 2015 in Windows 10 Pro (64 bits version) using the latest version of Jurassic available in NuGet (I've just created a new Console Application and ran Install-Package Jurassic).

My guess is that the long time has something to do with global variables because if I put the declaration of "a" out of the self-executing function (that is, in the global scope), it also takes a long time.

Line 0001: var a = 0;
Line 0002:     
Line 0003: (function () {
Line 0004:     a++;
Line 0005:     a++;
               .
               .
               .
Line 2002:     a++;
Line 2003:     a++;
Line 2004: })();

Thanks!

Program.txt

@paulbartrum
Copy link
Owner

paulbartrum commented Dec 9, 2016

Accessing global variables is quite a bit slower than accessing local variables. But I'm not sure that's the problem here. Separating out the compilation and the execution:

ScriptEngine engine = new ScriptEngine();
var compiledCode = engine.Compile(new StringScriptSource(generateCode(false)));
compiledCode.Execute();

99% of the elapsed time is in the compilation, not the execution. I'll keep looking.
EDIT: I got mixed up, the majority of the time is in reading or writing the global variables.

@rodrigoroma
Copy link
Author

Ok, thanks again for your attention!

@paulbartrum
Copy link
Owner

Oh no, I'm wrong, the elapsed time is in the execution.

------------------------------------
Without the self executing function
Compile time: 154, execution time: 1086 (b=2000)
Compile time: 54, execution time: 1071 (b=2000)
Compile time: 56, execution time: 1067 (b=2000)
Compile time: 62, execution time: 1065 (b=2000)
Compile time: 56, execution time: 1073 (b=2000)
------------------------------------
With the self executing function
Compile time: 27, execution time: 44 (b=2000)
Compile time: 24, execution time: 42 (b=2000)
Compile time: 15, execution time: 41 (b=2000)
Compile time: 11, execution time: 41 (b=2000)
Compile time: 13, execution time: 42 (b=2000)

That means it's likely to be a problem with the codegen for reading or writing a global variable (or both).

@zgsxtyzgd
Copy link

zgsxtyzgd commented Mar 29, 2017

I made some small changes to the Jurassic code, I hope @paulbartrum understanding。
In class CompiledScript I use EvalMethodGenerator instead of GlobalMethodGenerator so that CompiledScript.Compile can be compiled with the return value of a function (global functions are written into (function (args) {body}), the compilation of these functions results in a filename as a key The static Dictionary <string,CompiledScript>, can then be used in a multithreaded environment, I use a ReaderWriterLock to deal with concurrency
Now very quickly, because it no longer needs to be repeated Parse

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants