Nashorn: JavaScript that
doesn’t suck
Tomer Gabel, Wix
CodeMotion Tel-Aviv, November 2014
Agenda
• History
• Features
• Behind the scenes
• Performance
• Juggling Act
History
• Existing Rhino engine:
– Slow
– Non-compliant
– Did I mention slow?
• JavaScript since 1998:
– Adoption went thr...
Nashorn in a nutshell
• Project Nashorn
– Started in July 2011
– Integrates with JSR-223
– Reference use-case
for JSR-292
...
Why bother?
Why you care
• Extensibility and scripting
– Macro systems (a la VBA)
– Event hooks
• Server-side JavaScript
–...
Features
• Self-contained
• Small: 1.5MB JAR
• Implements ECMAScript 5.1
–100% compliant!
• Runtime-compiled to bytecode
(...
JSR-223 at a glance
import javax.script.*;
ScriptEngineManager manager =
new ScriptEngineManager();
ScriptEngine nashorn =...
Integrating JSR-223
• Injecting state
nashorn.put("name", "Schnitzel McFry");
nashorn.eval(
"print("hello " + name + "!");...
Integrating JSR-223
• Invoking JavaScript from Java
nashorn.eval(
"function hello(name) { " +
" print("hello " + name + "!...
Nashorn Extensions
• Java object
– Java.type
– Java.extend
– Java.from
– Java.to
– Java.super
• A bunch more
Integrating JSR-223
• Invoking Java from JavaScript
nashorn.eval(
"var HashMap = Java.type("java.util.HashMap");" +
"var m...
Integrating JSR-223
• Implementing a Java interface
nashorn.eval(
"var runnable = { " +
" "run": function() { print("hello...
Integrating JSR-223
• Single Abstract Method (SAM) promotion:
nashorn.eval(
"var Thread = Java.type("java.lang.Thread");" ...
BEHIND THE SCENES
The challenge
• JavaScript is dynamic
– Things can change at runtime
– Optimization is all about assumptions
The challenge
• JavaScript is dynamic
– Things can change at runtime
– Optimization is all about assumptions
• For example...
The challenge
• JavaScript is dynamic
– Things can change at runtime
– Optimization is all about assumptions
• For example...
The challenge
• JavaScript is dynamic
– Things can change at runtime
– Optimization is all about assumptions
• For example...
The challenge
• Naïve multiplication operator:
– Receive LHS and RHS as java.lang.Objects
– Unbox
– Test for potential ove...
The challenge
• That’s just one
example.
– Primitive widening
– Dynamic dispatch
– Type coercions
– Prototype mutation
• A...
The challenge
• Runtime code manipulation is not
the JVM’s strong suite
–Can only load entire classes
–High overhead
–Hard...
Enter JSR 292
• Based on an experimental project, the
Da Vinci Machine
• Adds two new concepts to the JVM:
– invokedynamic...
invokedynamic
• The name is
misleading
• It’s not about
invocation
• … but about
runtime linkage
invokedynamic
Bootstrap
M...
Why is this cool?
• Generated code is linked at runtime
• Code is hotswappable
– Guards for branching (over/underflow)
– S...
Don’t forget JEP 122
• The PermGen space is no more
– Now called “Metaspace”
– Resides in native heap
– Block allocator an...
SO HOW DOES IT PERFORM?
Pretty damn fast!
• 2-10 times faster than Rhino
• ~60% percent of V8
• Not much research out there
Avatar.js
• Implements the
Node model and API
on the JVM
• Supports most
modules
– Some natively
– Some via JNI
• … and it...
QUESTIONS?
WE’RE HIRING!
Contact me:
• http://www.tomergabel.com
• tomer@tomergabel.com
• @tomerg
of 30

Nashorn: JavaScript that doesn't suck - Tomer Gabel, Wix

As presented in CodeMotion Tel Aviv: http://telaviv.codemotionworld.com
Published on: Mar 3, 2016
Published in: Technology      
Source: www.slideshare.net


Transcripts - Nashorn: JavaScript that doesn't suck - Tomer Gabel, Wix

  • 1. Nashorn: JavaScript that doesn’t suck Tomer Gabel, Wix CodeMotion Tel-Aviv, November 2014
  • 2. Agenda • History • Features • Behind the scenes • Performance • Juggling Act
  • 3. History • Existing Rhino engine: – Slow – Non-compliant – Did I mention slow? • JavaScript since 1998: – Adoption went through the roof – Technology advances (V8, SpiderMonkey…)
  • 4. Nashorn in a nutshell • Project Nashorn – Started in July 2011 – Integrates with JSR-223 – Reference use-case for JSR-292 • Released with Java 8 in March 2014
  • 5. Why bother? Why you care • Extensibility and scripting – Macro systems (a la VBA) – Event hooks • Server-side JavaScript – More on this later • End-user programmability – Rule engines – Reporting engines/ETL – BPL and workflow • … and more Why Oracle cares • Atwood’s law • Node.js – A real threat to Java’s server- side growth • Reference use-case for JSR- 292 – Drive innovation – Drive optimization – Reference implementation
  • 6. Features • Self-contained • Small: 1.5MB JAR • Implements ECMAScript 5.1 –100% compliant! • Runtime-compiled to bytecode (no interpreted mode as with Rhino) • Fast!
  • 7. JSR-223 at a glance import javax.script.*; ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine nashorn = manager.getEngineByName("nashorn"); nashorn.eval( "print("hello world!");");
  • 8. Integrating JSR-223 • Injecting state nashorn.put("name", "Schnitzel McFry"); nashorn.eval( "print("hello " + name + "!");");
  • 9. Integrating JSR-223 • Invoking JavaScript from Java nashorn.eval( "function hello(name) { " + " print("hello " + name + "!");" + "} " ); Invocable context = (Invocable) nashorn; context.invokeFunction("hello", "world");
  • 10. Nashorn Extensions • Java object – Java.type – Java.extend – Java.from – Java.to – Java.super • A bunch more
  • 11. Integrating JSR-223 • Invoking Java from JavaScript nashorn.eval( "var HashMap = Java.type("java.util.HashMap");" + "var map = new HashMap(); " + "map.put("name", "Schnitzel"); " + "map.put("surname", "McFry"); " ); HashMap<String, String> map = (HashMap<String, String>) nashorn.get("map");
  • 12. Integrating JSR-223 • Implementing a Java interface nashorn.eval( "var runnable = { " + " "run": function() { print("hello world"); }" + "} " ); Invocable invocable = (Invocable) nashorn; Runnable runnable = invocable.getInterface( nashorn.get("runnable"), Runnable.class);
  • 13. Integrating JSR-223 • Single Abstract Method (SAM) promotion: nashorn.eval( "var Thread = Java.type("java.lang.Thread");" + "var thread = new Thread(function() { " + " print("hello world"); " + "} ); " ); Thread thread = (Thread) nashorn.get("thread"); thread.start(); thread.join();
  • 14. BEHIND THE SCENES
  • 15. The challenge • JavaScript is dynamic – Things can change at runtime – Optimization is all about assumptions
  • 16. The challenge • JavaScript is dynamic – Things can change at runtime – Optimization is all about assumptions • For example, what is the type of: var x = 500000;
  • 17. The challenge • JavaScript is dynamic – Things can change at runtime – Optimization is all about assumptions • For example, what is the type of: var x = 500000; x *= 500000; And now?
  • 18. The challenge • JavaScript is dynamic – Things can change at runtime – Optimization is all about assumptions • For example, what is the type of: var x = 500000; x *= 500000; And now? • How would you implement this?
  • 19. The challenge • Naïve multiplication operator: – Receive LHS and RHS as java.lang.Objects – Unbox – Test for potential over/underflow – Multiply via appropriate codepath – Box and return • You can specialize via static analysis • … but on-the-fly optimization is better
  • 20. The challenge • That’s just one example. – Primitive widening – Dynamic dispatch – Type coercions – Prototype mutation • All of these per call site! function square(x) { return x * x; } square(10) //== 100 square(3.14) //== 9.8596 square("wat") //== NaN
  • 21. The challenge • Runtime code manipulation is not the JVM’s strong suite –Can only load entire classes –High overhead –Hard PermGen space limit –Class unloading issues
  • 22. Enter JSR 292 • Based on an experimental project, the Da Vinci Machine • Adds two new concepts to the JVM: – invokedynamic bytecode instruction – MethodHandles • The first bytecode extension since 1999!
  • 23. invokedynamic • The name is misleading • It’s not about invocation • … but about runtime linkage invokedynamic Bootstrap Method Target Call Site Compile-time Runtime Invokes Returns MethodHandle
  • 24. Why is this cool? • Generated code is linked at runtime • Code is hotswappable – Guards for branching (over/underflow) – SwitchPoints for hotswap (promotions) • Hotswapping is lightweight – No class generation or loading • Resulting codepath can be JITted
  • 25. Don’t forget JEP 122 • The PermGen space is no more – Now called “Metaspace” – Resides in native heap – Block allocator and classloader isolation – Dynamic size (with bounds) • Maximum size (hard) • Low/high watermark for GC • This applies to all GCs (not just G1)
  • 26. SO HOW DOES IT PERFORM?
  • 27. Pretty damn fast! • 2-10 times faster than Rhino • ~60% percent of V8 • Not much research out there
  • 28. Avatar.js • Implements the Node model and API on the JVM • Supports most modules – Some natively – Some via JNI • … and it does work! • mocha • coffee-script • uglify-js • underscore • request • async • jade • express • mongodb • Redis Most popular per nodejsmodules.org Supported module highlights
  • 29. QUESTIONS?
  • 30. WE’RE HIRING! Contact me: • http://www.tomergabel.com • tomer@tomergabel.com • @tomerg

Related Documents