HNHacker News
TopNewBestAskShowJobs

mraleph

857 karma · joined September 29, 2010

mrale.ph
submissionscomments
mraleph··on The fear of dart:mirrors
People use Dart on the server and seem to be quite happy with it: see for example https://aqueduct.io/ as an example of homegrown server framework that heavily relies on mirrors.

But it is true that mirrors more dead than alive on the JS target.

I also would expect that eventually Flutter would want something in this space that is compatible with AOT compilation because it allows to tremendously cut down on boilerplate in some cases.

mraleph··on The fear of dart:mirrors
I should have stated this more clearly in the post - that it is lazy. I referred to the code itself, but did not explain what the code does very clearly, just said that it has a lot of overhead.
mraleph··on The fear of dart:mirrors
> This all smacks of a language that isn't very mature, at least for general-purpose programming.

Could you clarify what "smacks" of a language that isn't very mature? There are libraries written in any language that are not tuned for performance.

The goal of this post is to show that poor performance of a single library should not be interpreted as poor performance of a language feature that this library uses... Instead you must rigorously evaluate performance issues. (And also provide feedback to language implementors)

It is true that builtin libraries could have provided a better JSON deserialization support... So if your definition of an immature general-purpose language depends on whether or not there is a fast JSON deserialize built right into the core libraries - then Dart certainly does not pass.

However one can also define a general purpose programming language as a language in which programmer could efficiently implement all sorts of things, including but not limited to an efficient JSON deserializer - which seems to be the case for Dart.

> why would I choose Dart over Go?

I don't know. Why do you have to choose Dart over Go? You choose want you like most and what makes you most productive. For me it would be Dart for you it might be Go. Such is life. Not everybody has to write everything in the same language.

We can offer you to try Dart. You can refuse to try. You can also try it and then refuse to use it... Endless possibilities :)

mraleph··on V8: A Tale of TurboFan
> multiple times faster

This is an unsubstantiated claim. If LuaJIT was indeed multiple times faster on arbitrary code, everybody would be just running JS on something like LuaJIT in browsers :)

LuaJIT does spectacular job on loops, especially if you limit yourself to number crunching and FFI.

But if you code is polymorphic, makes heavy use of normal OOP and does not decompose into a graph of biased loops and linear traces V8 will pull ahead due to its method-compiler nature which is not susceptible to tracing pitfalls.

Here is an interesting example: there is an issue[1] "Metatable/__index specialization" in LuaJIT repository filed by Mike Pall himself, it's about adding infrastructure which would allow traces to make optimistic assumptions about metatable constness, because it would greatly improve the quality of traces produced from OOP heavy code. (Also this is precisely the limitation that is already imposed on FFI metatypes to allow JIT generate better code). The issue is still unimplemented in LuaJIT... However this is something that V8 could do for several years now, because it is extremely important for the kind of code people are writing in the real world.

[1] https://github.com/LuaJIT/LuaJIT/issues/41

mraleph··on V8: A Tale of TurboFan
> And slightly off topic, but what are the plans for the dart VM? Is it going to end up using TurboFan or will it stay with Crankshaft?

Dart VM is a code base independent of V8, so V8's plans to adopt one or another compiler have no implications on Dart VM.

Dart VM's IR is closer to Crankshaft, but it supports full language unlike Crankshaft (so in this sense it is closer to TurboFan).

We currently have no plans to radically rework the compilation pipeline, because we see no need for that.

mraleph··on Dart in 2016: Fastest growing language at Google, 2nd fastest in TIOBE
That seems to be this bug

https://github.com/flutter/flutter/issues/6586

mraleph··on Dart in 2016: Fastest growing language at Google, 2nd fastest in TIOBE
> Regarding Flutter [...] none of the devices I own was able to launch the application.

Is it still the case that none of your devices are able to launch Flutter Galler App? In an unfortunate coincidence the build that was published to Play Store right before the Dart Summit was flawed and declared that it is incompatible with most of the devices except for latest generation ones. This was rapidly fixed - but fixed build did not get into the Play Store on time.

mraleph··on Nectar: A Native JavaScript Compiler Inspired by Crystal Lang and Nim Lang
if I were to make a bet, I'd say that they don't implement the whole JavaScript and that there is some sort of a static type system which either rejects some programs where types can't be inferred or causes performance to fall of the cliff where types can't be inferred.

so essentially it's likely "JavaScript-like compiler" rather than "JavaScript compiler"... similar to how Crystal is Ruby-like but not really Ruby.

mraleph··on Adventures in the land of substrings and RegExps
> It's almost like those kuh-razy V8 people

I don't get what's the connection between V8, less_dart and naive implementation that `RegExp.matchAsPrefix` had in Dart VM.

mraleph··on Adventures in the land of substrings and RegExps
I guess I should have been more clear in my advice about not using regular expressions: if you have a tool that allows glueing multiple regular expressions together and erasing the cost of the abstraction (e.g. no allocation of temporary match result objects, substrings, etc) - then certainly that would be a preferred way to code the lexer. Just don't sprinkle a bunch of unconnected `new RegExp()` / `re.exec` around the code and expect that to be reach peak lexing speed.
mraleph··on My love-hate relationship with LuaJIT (2015)
If one heads over to GitHub to check some recently closed issues and recent commits one will discover that there are people who can understand and debug LuaJIT issues.

LuaJIT is not magic, it's a software. Very neat and tightly written but it's still just a bunch of C/assembly/Lua code.

Written by one human, and thus other humans can understand it too.

mraleph··on V8 Release 5.1
I think the question we all should really be asking is how long will it take to get to the point where WASM is practically useful for anything that noticeable chunk of web users cares about.
mraleph··on Printing Floating-Point Numbers: A Faster, Always Correct Method [pdf]
> http://goto.ucsd.edu/~andrysco/errol/ seems to be the artifact in question.

The artifact reveals that authors of the paper benchmarked Grisu3 in the debug mode (low compiler optimization level, ASSERTions enabled).

Changing their scripts to actually build Grisu3 in release mode turns tables:

    ==== Absolute Results ====
    Errol3            1196 cycles
    Grisu3            802 cycles
    Dragon4           6176 cycles
    Grisu3 w/fallback 833 cycles
    ==== Relative Speedup of Errol ====
    Grisu3            0.67x
    Dragon4           5.16x
    Grisu3 w/fallback 0.70x
(these are results on my machine with both Grisu3 and Errol3 compiled with -O3, original scripts build Errol with -O2 which makes it yet more slower than Grisu3).

So ultimately it seems that Grisu3 is still faster.

I also wanted to try benchmarking it on ARM - but it actually fails to build due to its dependency on __uint128_t which does not seem to be supported by my cross-compilation tool chain (at least for 32bit ARMs).

mraleph··on ChakraCore GitHub repository is now open
> Do you have any insight on why that still has not been done after so many years?

I can't really speak for either V8 or SpiderMonkey but I think there are few reasons -

a) nobody got to doing it, even though it was discussed multiple times, e.g. for V8 it just was not the right time to implement it as its trying to completely revamp its optimization pipeline and certain Crankshaft idiosyncrasies make this sort of optimization pretty brittle;

b) I am not entirely sure that it will actually speedup that much code, this kind of code is rarely on an extremely hot code-path (extremely hot code paths must strive to avoid allocation entirely!);

c) there is a reasonable workaround that provides good performance (manual loop);

d) ES6 provides something better than arguments object: rest arguments.

mraleph··on ChakraCore GitHub repository is now open
> no edge-case of an implementation can make its way into programmers' habits, something that tends to happen a lot with JavaScript.

Edge cases should not, and they almost never do... However performance optimizations is a very special area - you have to know how things are implemented and utilize this knowledge.

> mostly it was stuff where the key is needed in a function/closure (just threw this together straight in the text area here):

This code is also buggy - all closures will point to the same `key`.

mraleph··on ChakraCore GitHub repository is now open
> The variable has to be in the local scope and can't be in any higher or lower scope, not just a global scope (which your words acknowledge, but your code snippet doesn't)

Sure! I am just trying to say that in my opinion whenever you have a non-local variable used as iteration variable in for-in then you most probably have a bug in your code. I tried to illustrate this with an global variable example because it's a common source of JS bugs - when people leak things into a global namespace by accident.

> Some real world examples[0][1][2]

These links refer to a different bailout reason --- "ForIn is not fast case". The original ForIn support in Crankshaft (written coincidentally by me) only supported this kind of for-in because it was the important case to support and the one where you can get good performance with reasonable investment of time.

Given time and bug reports from people hitting this bailout I would certainly extend ForIn support to cover a more generic case (assuming that supporting more generic case would make some code faster), however just in a couple of months after I landed this initial support I switched to a different project, so I never had chance to revisit this.

This bailout reason is actually not in V8 anymore - as now V8 supports both fast and slow cases in Crankshaft[1]

[1] https://github.com/v8/v8/blob/master/src/crankshaft/hydrogen...

mraleph··on ChakraCore GitHub repository is now open
> optimization decisions that the V8 team have made

Optimization decisions that V8 team have made are much more universal than it might seem.

It is true there are sometimes strange artificial corner cases - but those are often either bugs or temporary solutions that are going to be replaced with something more generic as soon as they start to hurt too much code.

> which ends up with having to jump through some hoops in a for-in loop

Could you clarify which hoops precisely do you need to jump through?

I am not sure I can imagine a reasonable chunk of code that strives to be both fast, well written and wants to use a context captured or global for-in variable.

    for (IWantThisVariableToEndUpOnGlobalObject in obj) { }
How often do you write code like this?
mraleph··on Why I'm joining the Dart Team
> Does anyone know how Dart will be affected by web assembly?

WebAssembly right now is a suitable target only for C++ like languages. There is a hope that in the future WebAssembly will introduce features enabling efficient compilation of dynamic languages, but so far it's unclear when this hope is going to materialize into something more tangible than a few entries on the road map.

mraleph··on Microsoft Edge's JavaScript engine to go open-source
I am glad you find my stuff useful enough to recommend it to other people! Thanks.

I just wanted to point out a minor detail: I am an ex-V8 engineer - I have not been working on V8 since 2012.

mraleph··on How PostCSS became 1.5x faster by changing 2 lines of code
Some of this slide is a bit outdated by now.

Using Object.seal, Object.freeze and Object.defineProperty with writable, enumerable, configurable not set to true does not cause object named properties convertion to dictionary mode. However they still convert elements storage (one containing properties with names "0", "1", etc) to dictionary mode.

Similary accessors don't cause object properties storage conversion to dictionary mode unless there is a transition clash.

    var obj = {};
    obj.__defineGetter__("foo", function () { return 0; })
    print(%HasFastProperties(obj));  // => true
    
    var obj = {};
    obj.__defineGetter__("foo", function () { return 0; })  // Transition clash
    print(%HasFastProperties(obj));  // => false
Nothing changed with respect to `delete obj.foo`: this always converts named properties storage conversion to dictionary mode. However `delete arr[index]` doesn't (at least for arrays that were not in slow mode already), rules for objects depend on the amount of holes in the elements part of the object.
mraleph··on New Fn() vs. Object.create(P)
> At the same time, if I'm trying to simplify the test case and set only numeric values and not object ones, I've got nearly the same results: 3.953s and 3.922s for 10x more iterations (prop-benchmark-f.js and prop-benchmark-g.js).

Well, the secret here is that even if you have an empty constructor V8 still initially gives enough slack to you object for 10 in-object properties, and by coincidence you have precisely 10 properties.

Just add one more and observe the difference.

mraleph··on New Fn() vs. Object.create(P)
There is a bug in your code:

    var o = new F(i, i, i, i, i, i, i, i, i, i, z)
    z = o
    // ... skipped 
    o.z = z
This makes o.z = o, so only the last object survives. When you use constructor you actually link all of them together - which means there is more garbage around - GCs are more expensive.

If you fix this bug, e.g. by doing

    var o = new F(i, i, i, i, i, i, i, i, i, i, z)
    o.z = z
    z = o
you actually OOM in prop-benchmark-a.js case because object there is less compact than one created by constructor. Just as the post predicts.
mraleph··on New Fn() vs. Object.create(P)
> Is worrying about this for normal web apps just a micro-optimization or can you see instances where this would affect an application's speed significantly?

I don't think there is such thing as an average web application so things must be decided on the case-by-case basis.

In general if creation/usage of some "class" of objects is on the very hot path - then their layout can affect performance of the hot path. In this case constructor might be preferable for the reasons outlined in the post (faster construction, one less indirection for the property access). However the decision must be made only after deep investigation.

mraleph··on New Fn() vs. Object.create(P)
It was originally written for the jsconf talk and since has always been sitting in that repo. I was planning to move it out - but never got to it.
mraleph··on New Fn() vs. Object.create(P)
ES2015 class does not provide you with a way to declare instance fields. You still create them imperatively in the constructor. Which means for the purposes of the post ES2015 classes are not different from standalone constructor functions - as VM still has to figure out optimal layout dynamically.
mraleph··on New Fn() vs. Object.create(P)
It's done with my original Dart version of Shaky. The CoffeScript version is a port of the Dart version.

You can also notice that http://shaky.github.bushong.net/ does not support certain additional features that the post uses, e.g. it does not render curly brace or wavy "~~~~~" break line from the:

   +-------+
   |   1   +-+
   +-------+ |
   |   2   | |
   +-------+  > N slots reserved for in-object properties
   ~~~~~~~~~ |
   +-------+ |
   |   N   +-+
   +-------+
mraleph··on New Fn() vs. Object.create(P)
> I guess it's an obvious way to design it.

It's an obvious way to design it... if you start with explicitly declared properties in your language.

For JavaScript a state-of-art for a long time was more like this:

  +-------+
  |   *---+-> hashtable for properties
  +-------+
  |       |
  ~~~~~~~~~ various metadata (e.g. prototype chain)
  ~~~~~~~~~
  |       | 
  +-------+
all properties mixed together, all stored in a hash table, etc.

The non-obvious thing to design here is how you escape from the realm of hashtables into the realm of something both more compact and faster to work with (given certain statistical assumptions about the properties of the code).

mraleph··on Shaky: ASCII Diagram to PNG
I wrote the original code (not this CoffeeScript port) so that I could create simple diagrams fast without resorting much to dragging stuff around with mouse. If you want to create a sequence of diagrams where each next one is just slightly different from the previous one then textual approach is simply superior to point-and-click style editing. Other parts of my motivation were outlined here[1].

Having this ASCII -> image converter also allows me to embed diagrams into blogposts as text without actually making images out of them. See [2] as an example of such embedding.

[1] http://mrale.ph/blog/2012/11/25/shaky-diagramming.html [2] http://mrale.ph/blog/2014/07/30/constructor-vs-objectcreate....

mraleph··on IRHydra: Display V8 and Dart VM Intermediate Representations
I should probably update the screencast because I have changed UI since recording it.

Mostly changing colors, but also adding few important features, like "interesting mode" which I sometimes demo in the talks[1].

"Interesting mode" hides uninteresting/confusing IR instructions and splices sources into the IR helping people to navigate it and find IR chunks that interest them.

[1] http://mrale.ph/talks/goto2015/#/97

mraleph··on IRHydra: Display V8 and Dart VM Intermediate Representations
I'd love to work more on it, but sadly it's really outside of my real work right now - as I haven't been working on V8 for several years now.

It is past the demo stage though - I know people who use it and it is the only tool I use myself to look at V8 deopts (on a rare occasion when I need to).

I do answer questions and fix bugs whenever possible - so if you would like to use IRHydra and can't figure something out - just send me a mail or file a bug on GitHub.

I originally had hopes that something like this will eventually be incorporated in DevTools - but this hope has withered by now.

← PreviousPage 3 of 10Next →