Interesting. I saw malloc when profiling, but it wasn't very high, and
makes sense a really good allocator like jemalloc might be able to make it
negligible.

On Sun, Nov 6, 2016 at 1:12 PM, Aidan Hobson Sayers <[email protected]>
wrote:

> I ended up not implementing the arena allocation used in the emscripten
> optimizer (it probably wouldn't be terribly tricky to add, there are notes
> in cashew.rs) because profiling never identified it as being a big deal.
> You can verify this just by looking at the primitive timing of the
> different phases of registerizeHarder and eliminate - overall, the vast
> majority of time is spent in phases that just analyse the AST. AST node
> replacement happens where possible, e.g. `*x = Num(0f64)`, but it's likely
> mostly that jemalloc (the default allocator in rust, which may be
> considered cheating) is probably pretty quick. I could make wild guesses at
> other causes (perhaps jemalloc is good at deallocating and reallocating
> 32-byte types and does something clever internally), but it was never high
> enough on the profiler to get my attention. That's not to say there aren't
> savings to be made, but I could spend time better elsewhere even with the
> current speed.
>
> On 6 November 2016 at 19:50, Alon Zakai <[email protected]> wrote:
>
>> Very interesting, thanks!
>>
>> In particular about Rust helping avoid leaking, that's something I hadn't
>> thought of, very nice. However, the reason the C++ optimizer leaks is,
>> aside from complexity as you mentioned, also for another reason: to avoid
>> memory allocation overhead, so that allocation is always bumping a pointer,
>> and freeing is just ignoring it. If you're not leaking, then I guess you
>> have lists of freed objects for reuse, or such? I wonder if it's possible
>> to measure that overhead. (For comparison, in the binaryen optimizer I've
>> focused on reusing nodes; there is still leaking when that isn't possible,
>> but it's relatively rare.)
>>
>> Memory-wise, yeah, keeping the 1-1 mapping to the Uglify AST definitely
>> hurt the C++ optimizer's memory usage. The binaryen optimizer does
>> something similar to what you said, with properly strongly-typed nodes. So
>> e.g. -4096 would be a Const node, currently taking 20 bytes (it could be
>> 16, though).
>>
>> On Sun, Nov 6, 2016 at 11:25 AM, Aidan Hobson Sayers <[email protected]>
>> wrote:
>>
>>> The memory improvements are basically down to the AST being more
>>> strongly typed in Ayzim - structurally it's the same (there's a simple 1-1
>>> mapping between representations). For example, the uglifyjs AST
>>> representation of `-4096` is `["unary-prefix", "-", ["num", 4096]].
>>> This was translated faithfully to the C++ optimizer, so the arrays are `
>>> Value
>>> <https://github.com/kripken/emscripten/blob/1.36.14/tools/optimizer/simple_ast.h#L80>`s,
>>> which are dynamically typed by being a tagged union. The memory cost of a
>>> single `Value` is 16 bytes (`double` is the largest type in the union,
>>> and you pay that again to be able to hold the tag in the struct and pad
>>> it)...and then there's another 3*ptrsize bytes to store the vector type
>>> somewhere if the `Value` is an array (typically to point to a child
>>> node...so just add this for every node since they're all children!). You
>>> then multiply the size of `Value` by the number of items in the array,
>>> which is two at minimum (ish). Overall, for an AST node you're paying 
>>> `3*ptrlen
>>> + 32 + (16*N_additional_array_items)`.
>>>
>>> However, you know that  `X` in `["num", X]` is a double, and that each
>>> AST node has a limited set of possible tags, so you can treats whole AST
>>> nodes as tagged unions, rather than the individual AST node fields. In
>>> Ayzim you end up paying `ptrlen + 32` for any single ast node (ish).
>>>
>>> On top of this, the Emscripten optimizer leaks memory
>>> <https://github.com/kripken/emscripten/blob/1.36.14/tools/optimizer/optimizer.cpp#L467>
>>>  when
>>> replacing nodes (and elsewhere), probably because it's actually pretty
>>> tricky to keep track of what you're replacing, whether you've got another
>>> pointer to it hanging around somewhere and whether it's safe to deallocate.
>>> Leveraging the Rust ownership system made it quite tricky to translate
>>> parts of the C++ code, but the result is no memory leaks.
>>>
>>> Speedups were probably mostly from a) better overall optimization of the
>>> AST node tagged enum, b) less compact memory, c) using a string interning
>>> library with some interning at compile time (thanks to the Servo project)
>>> so some value comparisons could be inlined rather than going via pointer
>>> lookup, and d) a carefully chosen piece of low hanging fruit in
>>> registerizeHarder.
>>>
>>> The language helped in that I felt it gave me niceties to help me
>>> succeed (e.g. 'first class' tagged unions, exhaustiveness checking on
>>> matching tagged unions), it has a good library experience and the whole
>>> memory safety thing is nice. Downsides were the compile times, difficulties
>>> of translating highly unsafe C++ code and a number of language papercuts
>>> (lexical lifetimes in particular). Someone with full understanding of the
>>> optimizer and C++ would have been very able to do all the
>>> macro-optimizations in C++ so Rust isn't more powerful, but as a fallible
>>> human it helped me a lot and I felt much less like I was juggling chainsaws
>>> than when I've made my previous changes to the C++ optimizer :) For
>>> example, I'd feel pretty optimistic about my ability to add the duplicate
>>> function eliminator to it.
>>>
>>> I should have made my testing process clearer - during development I was
>>> diffing output of optimizing the sqlite and unity asm.js full library
>>> files. The only remaining differences I'm aware of are a) better float
>>> representation from ayzim and b) the three test cases here
>>> <https://github.com/aidanhs/ayzim/tree/0.1.2/testcases> (all three very
>>> minor - one ayzim is better at, one emscripten is better at, one ayzim gets
>>> very slightly wrong with float representation). If you spy other
>>> differences, let me know.
>>>
>>> On 5 November 2016 at 19:38, Alon Zakai <[email protected]> wrote:
>>>
>>>> Very cool!
>>>>
>>>> For those interested to check this out, you can just replace the
>>>> existing optimizer executable, and if you want to go back, just deleting
>>>> the replacement will make emcc rebuild the original one.
>>>>
>>>> Regarding those improvements to speed and memory use, I'm curious where
>>>> they come from - what were the changes you made? Small things, or large
>>>> structural changes to the AST? For comparison, the binaryen optimizer also
>>>> has some major improvements to speed and memory compared to the emscripten
>>>> asm.js one, and that's mostly from the redesigned AST - I'm curious if we
>>>> ended up doing similar things to improve on the old optimizer. Also, do you
>>>> think your choice of language had an effect here?
>>>>
>>>> Have you verified this generates the same output as the asm.js one,
>>>> btw? You mention it passes the test suite, but I'm also curious if it's
>>>> literally generating the same code as well.
>>>>
>>>> On Fri, Nov 4, 2016 at 8:08 PM, Aidan Hobson Sayers <[email protected]
>>>> > wrote:
>>>>
>>>>> Using Ayzim as a drop-in replacement for the Emscripten asm.js native
>>>>> optimizer when compiling an asm.js project of moderate or large size on
>>>>> `-O2` or `-O3` should result in a ~50-75% reduction in memory usage and a
>>>>> ~25-50% speedup when running asm.js native optimizer passes (i.e. most of
>>>>> the "js opts" stage as seen in in EMCC_DEBUG output).
>>>>>
>>>>> To get it, download the compiled releases for Linux and Windows from the
>>>>> ayzim releases page <https://github.com/aidanhs/ayzim/releases>,
>>>>> extract them and replace (after backing up!) the existing optimizer(.exe)
>>>>> binary in `emsdk/emscripten/incoming_optimizer_64bit/` (if you're not
>>>>> on `incoming` but still feel brave, take a look at your emscripten config
>>>>> file, usually at `$HOME/.emscripten`, which should point you to the right
>>>>> place).
>>>>>
>>>>> --
>>>>>
>>>>> Some background: when I was trying to port a large application to
>>>>> asm.js about 6 months ago I had serious problems with the Emscripten 
>>>>> asm.js
>>>>> optimizer - it would split the 750MB .js file into chunks and promptly
>>>>> consume all 8GB of my RAM by trying to optimize the chunks in parallel,
>>>>> swapping everything else out of memory and grinding the machine to a halt.
>>>>> I tackled this problem by taking a brief(!) diversion to rewrite the
>>>>> optimizer in Rust to be more memory efficient. Along the way I added a few
>>>>> speedups.
>>>>>
>>>>> Ayzim is probably an entry in the "well this might have been useful
>>>>> two years ago" section of software (since asm.js is 'shortly' going to be
>>>>> made redundant by wasm) but someone may find a use for it. For example,
>>>>> people wanting to understand the structure of the Emscripten optimizer ast
>>>>> may want to look at this code
>>>>> <https://github.com/aidanhs/ayzim/blob/0.1.2/src/cashew.rs#L141>
>>>>> and/or ask me since I'm very familiar with it now :)
>>>>>
>>>>> In time I may extend Ayzim to support wasm optimizations and move it
>>>>> to being more of a library, but that's for the future.
>>>>>
>>>>> Aidan
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "emscripten-discuss" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "emscripten-discuss" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "emscripten-discuss" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "emscripten-discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "emscripten-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to