7 ms·
That still doesn't make sense to me.. how can JIT in general be slower than Java when Java is JITed?
by shawnz 7y ago
That still doesn't make sense to me.. how can JIT in general be slower than Java when Java is JITed?
- throwaway894345 7y agoThe claim wasn’t about JIT in general, but rather about JS.
- deleted 7y ago[deleted]
- pizlonator 7y agoThen it’s problematic to be so JS and V8 centric. Also the post specifically talked about JS being faster than Python and slower than Java so that’s what this thread is about.
- throwaway894345 7y agoI’m not advocating for the post or anything else, I was just clarifying a misunderstanding.
- seanmcdirmid 7y agoThe Java JIT has static type information to work with, the JS JIT can only infer type information via heroic efforts. Static types do mean something, especially when working with primitives and other unboxed data types.
- erik_seaberg 7y agoThis. Javascript engines have to do stuff like https://mathiasbynens.be/notes/shapes-ics https://mathiasbynens.be/notes/shapes-ics to assume many objects will have the same key names and types and create an optimized class layout, with some kind of expensive fallback if anyone ever randomly stores a key or value that violates the assumption. They can't even be sure you'll always be doing integer math (unless you resort to bit masking a la asm.js). Hinting (like __slots__ in Python) might have helped some.
- discreteevent 7y agoThis was one of the main motivations for writing dart. The V8 implementers were tired of having to write these kinds of hacks. Even though dart was initially a dynamically typed language, the shape of the objects was stable.
- pizlonator 7y agoYeah what you said.
- raverbashing 7y agoYou're not wrong, but I always wonder how the verbosity and crazy class hierarchy of Java code doesn't make things slower. I know that compilers are smart, but the API doesn't make things easier at all
- bosswipe 7y agoVerbosity makes the programmer slower not the program.
- raverbashing 7y agoYes I understand some verbosity is structural and won't change anything, for example SomeClass x = new SomeClass(); won't make anything slower (ignoring auto for now) Now, I read Java code and I can't help but wonder how things are harder For example, setters and getters, what would be a simple memory write becomes a function call. Not complaining when you actually need it. Reading the examples here (and those are not too bad) https://developer.android.com/reference/java/net/HttpURLConnection https://developer.android.com/reference/java/net/HttpURLConn... it seems you have to actually fight the API to get anything done Why do you need to cast the return of a url.openConnection() to a HttpURLConnection? (I mean, how many connection types exist?)
- pgrulich 7y agoSo for getters and setters a Jit can inline the function call and in the end you have a direct memory access. In your example you have to cast because URLConnection could be a HttpURLConnection or JarURLConnection. But again a good Jit would speculate that it is always a HttpURLConnection and deoptimize if not.
- imtringued 7y agoThe JVM also has full information about the class hierarchy at runtime. If you add a class that overrides a function it will deoptimize that overriden function to a virtual function but otherwise the JVM will just treat it as a static function and inline it if necessary.
- pcr910303 7y agoWell, you're right that JS JITs can only infer type information via heroic efforts, but AFAIK the Java compiler throws away any type information from the source code, which means that the JVM JIT needs to inver type information again from the byte code. Still, the JVM JIT is faster than JS due to reasons explained in the sibling comment of the parent one.
- BorisTheBrave 7y agoThis is not true, bytecode stores fields and classes as fully qualified strings: https://stackoverflow.com/a/17406592 https://stackoverflow.com/a/17406592
- pdpi 7y ago> but AFAIK the Java compiler throws away any type information from the source code You're thinking about generics. .class files preserve a whole bunch of type information (I'm building a .class decompiler in my free time, and I'm looking at that very same data in my debugger ATM).
- The_Colonel 7y agoYou probably know this, but it's not obvious to the random reader. Even generic types are available in the Java .class file and are accessible from the reflection API. Spring for example uses this quite heavily.
- cogman10 7y agoIt depends on where you are at. Type information is present in fields and class inheritance For example, a class like this `class Foo implements Bar<String>` Retains the fact that the generic type is a String. That information is completely lost at method invocation. So a method that takes a `Bar<String>` ultimately compiles to a method that takes a `Bar` and knows nothing of the String. To get that generic information down you have to engage in some fun tricks using either the class or field method I mentioned earlier. (Usually you do this with a second type parameter where it matters).
- masklinn 7y ago> The Java JIT has static type information to work with I don't know that the java JIT has type feedback. However regardless Java being statically typed means Java code is structurally closer to what a JIT wants and can analyse, it's much more difficult (and thus rarer) to fuck around with types and objects generated on the fly at runtime for instance, you're not going to add new attributes to an instance whereas that's just tuesday in javascript.
- titzer 7y agoJava JITs definitely do have type feedback. They profile the types of objects at virtual call sites and do guarded inlining, as well as removing expensive interface casts, etc. The JVM doesn't really have a distinction between classes generated on the fly and those that were on disk, as they all go through a classloader anyway. JVMs, for the most part, blow their brains out at the end of the day and start with zero the next VM run.
- kevingadd 7y agoThe design of JavaScript is not very friendly to high performance. Even though Java is itself not easy to generate efficient code from, producing efficient code from JavaScript is far more difficult.
- ridiculous_fish 7y agoThe peer comment about static typing is correct, but there's more, err, flavor to be enjoyed in the challenges of JITing JS. Here's some deopt scenarios to keep you up at night. To whet your appetite, what happens if you redefine Math.round? Java prohibits this for obvious reasons, but a JS joker may write: Math.round = () => Infinity; JS engines really do inline Math.round, and must be prepared for this nonsense. It gets worse. Maybe you check for a property which is usually not found: if (!val.uuid) val.uuid = uuidgen(); Hidden classes can almost reduce this to a pointer comparison. But what if someone adds a uuid property on Object.prototype? Every check is busted! v8 handles this with "validity cells", and it's ugly, requiring that every object know about every object which "inherits" from it. Now if you are a monster you may choose to write: Object.defineProperty(Array.prototype, "42", {value: "lol"}); console.log([][42]); // yes it prints "lol" Every array gets a default value for 42. Think about how you would JIT numeric code in such an environment...
- progval 7y agoPython suffers the same issue. There's some discussion about dealing with it in this PEP and the pages it links: https://www.python.org/dev/peps/pep-0509/ https://www.python.org/dev/peps/pep-0509/
- The_Colonel 7y agoPython does not seem to be even trying to be competitive in performance though so it's less of an issue for them.
- progval 7y agoThey do, it's just not a priority. The PEP I linked (as well as most of the work of its author, Victor Stinner, in the last years) are motivated by JITing. There's also the "frame evaluation API" PEP [1], whose purpose is to allow pluggable evaluators in CPython without forking the entire interpreter, like Unladen Swallow had to. [1]: https://www.python.org/dev/peps/pep-0523/ https://www.python.org/dev/peps/pep-0523/
- 7y ago