Giter Club home page Giter Club logo

Comments (3)

iamstolis avatar iamstolis commented on September 23, 2024

You are right that putMember() and removeMember() are not overly fast. The root of the problem is that they are generic (work for any property/member) and as such cannot specialize itself well. I suggest you to use evaluation of an appropriate script instead. A script that contains a separate assignment for each binding can specialize each assignment and can be much faster. You can imagine that each assignment remembers where to write the value while the general method has to find the right place with each invocation.

So, you can rewrite your bindAll to something like

StringBuilder sb = new StringBuilder();
variables.forEach((name, value) -> {
    sb.append(name).append("=variables['").append(name).append("'];");
});
String script = sb.toString();
BiConsumer<Evaluator, String> bindAll =
    (evaluator, snippet) -> {
        evaluator.bind("variables", ProxyObject.fromMap(variables));
        evaluator.eval(script);
    };

There is a similar problem with the repeated invocation of removeMember() in close(). You can rewrite it to

StringBuilder sb = new StringBuilder();
bindings.getMemberKeys().forEach(s -> sb.append(s).append("=undefined;"));
eval(sb.toString());

You may wonder why I don't suggest to use delete i.e.

bindings.getMemberKeys().forEach(s -> sb.append("delete ").append(s).append(';'));

That's because I found that we do not specialize well the delete performed on a global object. I have fixed this bug already, but I don't expect you to use the latest development build. So, the delete variant is (unfortunately) slow in the latest release still.

In fact, it may be redundant to do anything in close(). If you decide to write all values for every script then you can keep close() empty. Actually, writing the same set of properties/members may be a good idea because it leads to the same set of "hidden classes/shapes" of the global object. So, the locations (where the value should be written) are kept consistent for all scripts.

Finally, I noticed that your example runs in interpreter mode only (without runtime compilation). I hope that this is just to keep the example simple. If you care about performance then you should run with runtime compilation, of course.

When I applied the mentioned suggestions then the execution time of your example decreased from ~30s to ~0.35s on my machine.

from graaljs.

JonHenson avatar JonHenson commented on September 23, 2024

Thank you!

Using a script to bind the values has improved performance dramatically. I've modified my code (and committed to the repo) to time 300,000 evaluations (originally 30,000) and to use runtime compilation and execution after warmup is - for me - ~1.5 seconds with GraalJS vs 2 seconds with Rhino.

The reason I was using interpreter only mode is that I'm only able to execute with compilation enabled when running from my IDE. With an uber jar I get an exception saying: No language and polyglot implementation was found on the class-path but that was lower down my list of things to solve than bindings performance - guess it's now risen to the top!

$ mvn clean package &&
> "$JAVA_HOME/bin/java" -Dpolyglotimpl.TraceClassPathIsolation=true -jar target/binding-test.jar
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< jon.test:js-perf-test >------------------------
[INFO] Building js-perf-test 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
:
:
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.939 s
[INFO] Finished at: 2024-01-12T10:57:43Z
[INFO] ------------------------------------------------------------------------
[class-path-isolation] Start polyglot class-path isolation
[class-path-isolation] Collected 1 class-path entries from java.class.path system property
[class-path-isolation] Class-path entry: target\binding-test.jar
[class-path-isolation] No truffle-api and/or polyglot found on classpath.
Exception in thread "main" java.lang.IllegalStateException: No language and polyglot implementation was found on the class-path. Make sure at last one language is added on the class-path. If you put a language on the class-path and you encounter this error then there could be a problem with isolated class loading. Use -Dpolyglotimpl.TraceClassPathIsolation=true to debug class loader islation problems. For best performance it is recommended to use polyglot from the module-path instead of the class-path.
        at org.graalvm.polyglot.Engine$PolyglotInvalid.noPolyglotImplementationFound(Engine.java:2071)
        at org.graalvm.polyglot.Engine$PolyglotInvalid.createHostAccess(Engine.java:2057)
        at org.graalvm.polyglot.Engine$PolyglotInvalid.createHostAccess(Engine.java:2023)
        at org.graalvm.polyglot.Engine$Builder.build(Engine.java:753)
        at org.graalvm.polyglot.Engine.create(Engine.java:346)
        at jon.test.js.LazyBinding.graalEvaluatorFactory(LazyBinding.java:85)
        at jon.test.js.LazyBinding.main(LazyBinding.java:296)

from graaljs.

JonHenson avatar JonHenson commented on September 23, 2024

@iamstolis Thanks for your advice on all of this, it took me longer to circle back to it than I had hoped it would.

I ended up dealing with "unbinding" by evaluating:

Object.keys(globalThis).forEach(k=>globalThis[k]=undefined)

From your comment, it seems that using delete may be the way to go in the future; however, using delete currently seems to have no effect (the variable remains in the bindings map with its value unchanged).

(Incidentally, the issue with running in non-interpreted mode was resolved by moving to the 21.0.2 VM)

from graaljs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.