# Воскресенье 28 твитов
всем привет! меня зовут Вячеслав и эту неделю я вещаю из под капота JS - здесь темно и повсюду C++... отвечаю на вопросы про V8 и перформанс
23:21окей сегодня последний день моего задумчивого молчания в этом твиттере
12:06я мог бы набросить под конец, признавшись, что я не особо-то люблю JavaScript, ну да всем это и так известно :)
12:10тут как-то купил пельмени в магазине; вот покупные пельмени - это как готовый язык программирования, а самодельные - это когда сам написал
12:40... хочу самодельных пельменей и свой язык программирования - но времени нет
12:41@jsunderhood не встречал людей в зравом рассудке, которые его любят. Он объективно очень плох.12:59
продолжая тему пельменей - у покупных пельменей внутри сплошной NaM (Not-a-Meat), он получается если сложить говядину с undefined.
14:35стоит ли сделать digest из всех технических вопросов, на которые я ответил? (исключая секретные рецепты моей любимой еды)
14:49stefan-marr.de/papers/pldi-ma… <- скоро все смогут писать быстрые виртуальные машины на коленке, поэтому надо рубить бабло пока эта тема горячая
14:52я думаю если устану писать код, напишу книгу "Еда и Программирование"
15:06вот допустим гречка, столь любимая на просторах нашей необъятной родины, это очевидная метафора на Pascal.
15:08на тебя одинаково странно смотрят, когда ты говоришь "я ем гречку" и "я пишу на Паскале"
15:08@jsunderhood а что насчёт C++ и Go?15:10
.@shuvalov_anton C++ - это Доширак, ты его заварил - все вокруг умерли, а ты один счастливый сидишь и кушаешь обжигаясь
15:11.@shuvalov_anton а Go... овсянная каша? очень просто и полезно для желудка, если от С++ у тебя язва.
15:13окей, всех с прошедшей неделей, поднимаю бокал за вас, пишущих на JS без страха и сомнений pic.twitter.com/wBI9t4bDxP
15:36вот краткое содержание недели mrale.ph/blog/2015/04/1…, ловите меня на mrale.ph и в основном твиттере @mraleph. всем пока!
19:20и еще, смотрите на языки программирования за пределами JS: C++, Haskell, Rust, Go, C#, Lua, Dart, OCaml, Clojure, Agda, всёвсёвсё
19:37это не особо-то полезно в рамках тотальной тирании JS в вебе, но чего тираны всегда боятся? ЗНАНИЙ.
19:38знания расширяют угол обзора... кто видел Erlang, тот на колбэки смотрит косо, хоть Erlang в остальном и как-то пффффф
19:40а когда угол обзора расширяется - то это можно и к тому языку на котором пишешь применить. вот.
19:42@jsunderhood java, php, python, ruby :)19:42
.@beshkenadze да, на все надо смотреть. на PHP надо смотреть, чтобы понять как не надо делать :) *набросил и убежал*
19:43на часах 11. хочу еще набросить - пока не пробило 12 и пароль не отобрали. многие думают, что в программировании главное - писать код.
20:53мне же кажется, что в программировании главное - это хорошо подумать и ничего не написать... ненаписанный код = несломанные тесты, ляпота!
20:55вот еще интересный вопрос: есть сериалы про агентов FBI, есть сериалы про врачей, а есть ли сериалы про программистов?
21:08последний сериал про программистов, который я видел выглядел как-то так (главный программист в центре \o/) pic.twitter.com/DU16J3yTsH
21:13всё, 12:07, мой пароль превратился в тыкву. вот вам стихотворение Фернандо Пессоа напоследок pic.twitter.com/M5RlwAJLYW
22:09# Понедельник 14 твитов
утро понедельника начинается с чтения LLVM Weekly - на прошлой неделе ничего интересного, впрочем, не случилось llvmweekly.org/issue/66
9:20@jsunderhood появились ли какие-то отпимизации в V8, связанные с defineProperty? Почему U*Array (UInt32) не содержит всех методов из Array?13:52
. @GrantedN typedarrays исторически не были array, поэтому у них другой прототип; в ES6 все методы типа map будут people.mozilla.org/~jorendorff/es…
13:54. @GrantedN про defineProperty: зависит от того, что именно вас интересует: сам defineProperty или проперти им созданные?
13:55.@GrantedN если сам defineProperty то он как был медленный и печальный, так примерно пока и остается
13:56.@GrantedN с другой стороны если определять им non-writable свойство на прототипе какого-нибудь объекта то это используется в оптимизациях
13:57а вот демка скрытой проблемы с производительностью при использовании accessors mrale.ph/irhydra/2/#gis… / gist.github.com/mraleph/88ef8e…
14:34... смотреть надо что заинлайнилось во вкладке Source pic.twitter.com/lZpppn1cY2
14:35на работе сегодня выходной, тут в твиттере - тоже. чувствую себя героем фантастического рассказа "Позвоните!" fantlab.ru/work65898
16:21обнаружил у себя в рюкзаке распечатку статьи "Common Compiler Optimisations are Invalid in the C11 Memory Model" mpi-sws.org/~viktor/papers…
19:28казалось бы при чем тут JS? а вот при чем: docs.google.com/document/d/1ND…
19:30@jsunderhood Вячеслав, немного не по теме, но всё же... Что вы думаете о реализациях виртуального дома в js? Есть ли за этим будущее?21:00
.@milk_is_my_life на мой взгляд за ними есть настоящее,
кто знает, что будет в будущем? может веб умрет, может DOM станет легковесным
21:00.@milk_is_my_life а тема у нас JS и все-все-все, так что любой вопрос по теме, даже если я на него ответа не знаю :)
21:01# Вторник 88 твитов
@jsunderhood тогда как JS стать лучше/быстрее? В чем слабые места современных движков?8:04
.@roman01la я бы сказал, что самое слабое место современных движков это непредсказуемость производительности
8:05.@roman01la классический пример был с Object.freeze: долгое время в V8 замороженные объекты неожиданно были значительно медленнее обычных
8:07.@roman01la Object.freeze починили, но он хорошо подчеркивает суть - что в бенчмарках не встречается, то имеет случайную производительность
8:08.@roman01la поэтому я считаю, что JS движки нынче должны развиваться в ширину, а не продолжать копать яму, стоя на одном месте
8:09.@roman01la вот допустим forEach очень медленный по сравнению с обычным for-loop. почему медленный? "потому что гладиолус".
9:23@jsunderhood можно немного подробнее про ширину?)9:23
.@roman01la или пример с accessors который я вчера твитнул - можно сделать Clash случай таким же быстрым как NoClash.
9:25.@roman01la или Object.defineProperty / Object.prototype.hasOwnProperty они не очень-то быстрые, а можно сделать быстрыми
9:26в JS сообществе очень популярно изобретать велосипеды, вот и для меня это самый удобный способ добраться до работы pic.twitter.com/UqqXgBfnKc
9:37@jsunderhood реализация forEach внутри отличается от for-loop? Почему бы JIT не инлайнить forEach в for-loop.10:02
.@roman01la forEach реализован через for-loop github.com/v8/v8-git-mirr…
10:02.@roman01la проблема как раз в том, что никто пока не озаботился тем, чтобы forEach инлайнился и все лишнее оптимизировалось в никуда
10:04.@roman01la я для этого как раз написал тулзу -> mrale.ph/irhydra/2/, там флаги и инструкции на первой странице
10:05@jsunderhood Как можно посмотреть оптимизированный код в рантайме?10:05
@jsunderhood есть будущее у компиляции LLVM-кода под браузеры, asm.js — как нового ассемблера и js на уровне железа? destroyallsoftware.com/talks/the-birt…10:06
.@shuvalov_anton asm.js - весьма неполноценный. и мне кажется весьма странным решение "прятать" байткод внутри JSкода
10:09.@shuvalov_anton все мое отношение к нему было выражено 2 года назад mrale.ph/blog/2013/03/2… и почти не изменилось с тех пор.
10:09.@shuvalov_anton однако веб достаточно странная штука. тут часто побеждает популизм и политика, а не нормальные технические решения.
10:10@jsunderhood интересно, какие термины используют англоязычные разработчики для велосипеда, костыля и всякой упячки?10:23
.@dosyara костыль можно так и переводить "crutch". "изобретать велосипед" ~ "reinvent the wheel", все универсальное :)
10:27.@dosyara еще близкий аналог русского "костыля", это "kludge" (a workaround or quick-and-dirty solution that is clumsy, inelegant)
10:29@jsunderhood В FF Nightly реализованы типизированные объекты wiki.ecmascript.org/doku.php?id=ha… Нужна ли в JS статическая типизация?10:37
.@roman01la типизированные объекты не привносят статической типизации в язык, поэтому вопрос не совсем понятен
10:38.@roman01la еще не совсем понятен смысл слова "нужна", кому нужна? у мощных статических систем типов есть свои преимущества.
10:39.@roman01la но если я сейчас начну о них рассуждать, то я неизбежно скачусь в рассуждения о вкусе и личных предпочтениях.
10:40@jsunderhood Добавление typed objects и других типизированных структур как-то повлияет на ежедневную разработку?..10:53
.@roman01la повлияет, если ваша ежедневная разработка требует оптимизаций на уровне object layout & memory locality :)
10:55.@roman01la в остальных случаях JS VMных собственных оптимизаций, которые случаются сами по себе, должно хватать.
10:56@jsunderhood То есть веб-разработчику не стоит заморачиваться о таких вещах, а лучше исправлять свой обычный JS код? :)10:59
.@roman01la прежде всего нужно писать нормальный код (не пренебрегая простейшими знаниями об алгоритмах) и continuous performance tracking
11:01.@roman01la ... а не так что фигачить код скажем год, а потом спохватиться и начать бегать вокруг него пытаясь оптимизировать
11:02@jsunderhood есть ли в Dart AOT компиляция при компиляции в JS? Почему?11:34
. @kanterov Dart в JS компиляция по определению AOT, потому что она проиходит один раз во время сборки проекта.
11:35. @kanterov если эту компиляцию делать не AOT, а "JIT" на стороне клиента то получается нужно весь Dart код посылать с зависимостями
11:36.@kanterov хотя этот подход было бы интересно попробовать и написать такой JIT, у думаю пиковую производительньсть было бы проще достичь
11:37.@kanterov но и прогревать его пришлось бы паяльной лампой. хороший пример - это pypy.js arewepythonyet.com
11:39.@kanterov [впрочем у pypy.js большой overhead как раз из-за того, что они используют pypy скомпилированный emscripten]
11:41@jsunderhood Rust или Go? Что тебе больше нравится и что станет мейнстримом (и станет ли)?12:20
.@raxpost о обоих языков есть прикольные фичи и недостатки, например, у Go бедная система типов - а у Rust сильно уж замороченная.
12:23.@raxpost я вообще к языкам программирования (за исключением русского языка) отношусь без особого фанатизма. молоток он нужен чтобы стучать
12:24.@raxpost поэтому если стоит выбор в вакууме между Rust и Go, то я предпочту съесть еще мягких французских булок и выпить чаю
12:26.@raxpost в будущем число языков программирования только продолжит расти поэтому понятие mainstream станет размываться
12:28.@raxpost достаточен ли размер языкового community для обеспечения всех потребностей оного в велосипедах и прочих фреймворках
12:32.@raxpost есть ли кому подхватить флаг, если разработчики компилятора попадут под автобус дружно?
12:32.@raxpost мне кажется и Go, и Rust хоть и имеют большие растущие community, все еще уязвимы перед оным автобусом-языконенавистником.
12:34@jsunderhood что по поводу оптимизаций в V8 для apply, bind или call. Раньше видел что call быстрее, потом apply, а потом bind, а сейчас?13:19
.@GrantedN зависит от ситуации. но bind действительно самый медленный из всех, потому что его никто не разгоняет :(
13:19.@GrantedN для foo.call() были не так давно реализованы оптимизации в Crankshaft, поэтому в теории он сейчас должен быть самым быстрым
13:20.@GrantedN в неоптимизированном случае call быстрее за счет того, что нет нужды выделять временный массив аргументов
13:22еще случайный факт об о мне: в моем "музыка для программирования" плейлисте youtube.com/watch?v=_2xa46… соседствует с youtube.com/watch?v=foGkU6…
13:31@jsunderhood а что с иммутабельными данными в движках? Они используют преимущества неизменяемости для оптимизаций?13:32
.@roman01la V8 не особо использует, могла бы и лучше. я уже приводил, пример с non-writable свойством на прототипе twitter.com/jsunderhood/st…
13:36. @roman01la с другой стороны если написать вот такой цикл gist.github.com/mraleph/141f0e…, то там o.x не будет вынесено за цикл, хотя могло бы.
13:39. @roman01la одновременно в этом примере hidden class check будет убран - т.е. вроде как V8 понимает что объект immutable но вроде как и нет
13:39.@roman01la числа, строки, булевы значения, замороженные объекты - больше ничего вроде нет иммутабельного
13:42.@roman01la если объект "ускользает" из области компиляции, то компилятор обычно сдается и предполагает любые побочные эффекты
13:43.@roman01la с другой стороны компиляторы пытаются отслеживать все это делать, escape analysis и т.д. т.е. это возможно в опр. пределах
13:44@jsunderhood @roman01la как объект может оттуда ускользнуть? Ведь весь код всёравно проходит через компилятор?13:45
. @ALF_er код обычно проходит через компилятор не весь сразу (это было бы слишком долго) а "кусками" @roman01la
13:46. @ALF_er плюс в современных JS VM несколько компиляторов - все начинается с тупого, который почти ничего не оптимизирует @roman01la
13:47. @ALF_er а оптимизирующий компилятор приходит позже и оптимизирует только то "горячие" фрагменты @roman01la
13:47. @ALF_er в современных JS VM эти фрагменты = функции, т.е. оптимизирующий компилятор оптимизирует ф-ии отдельно друг от друга @roman01la
13:49. @ALF_er например в gist.github.com/mraleph/141f0e… он придет оптимизировать foo и не сможет заинлайнить вызов bar @roman01la
13:50. @ALF_er поэтому вызов bar будет для него непрозрачен @roman01la
13:51. @ALF_er поэтому если мы бы в bar передаваем что-то, то непонятно что bar там с ним делает. @roman01la
13:51@jsunderhood компиляторы не движутся в сторону оптимизации на более высоких уровнях? Вообще куда сейчас движутся компиляторы? к чему?13:52
. @ALF_er да это как-то давно изученная тема intraprocedural vs interprocedural analysis и interprocedural - медленно и память кушает
13:54. @ALF_er поэтому надо взвешивать стоимость и какой выхлоп получается. поэтому пока в JS мире intraprocedural + inlining работает ОК
13:55. @ALF_er тот же asm.js и Strong Mode developers.google.com/v8/experiments у них ноги растут от нежелания делать interprocedural analysis
13:58@jsunderhood вот здесь github.com/babel/babel/is… для оптимизации предлагают выносить try-catch в отдельную функцию, это правда поможет?13:59
.@roman01la Crankshaft не поддерживает try-catch по историческим причинам, поэтому горячим функциям это помогает быть оптимизированными.
14:00.@roman01la но у них должно быть нетривиальное тело (циклы там всякие), что бы прирост производительности был хорошо заметен
14:01адаптивная оптимизация одной картинкой pic.twitter.com/t3KiTwWaNO
14:04@jsunderhood а я опять о насущном :)22:03
Вячеслав, что вы думаете о реактивном подходе в построении сложных spa приложений?Имею ввиду rxjs,bacon
.@milk_is_my_life я думаю, что это функциональненько, и больше ничего :)
22:04.@milk_is_my_life я UI практически не делаю => нет опыта для сравнения. а когда делаю, то тяп-ляп на коленке (e.g. mrale.ph/saga/ )
22:07@jsunderhood Если бы это была основная архитектура, какими были бы современные ЯП? Или это не влияет?22:29
.@roman01la насколько я знаю многие экспериментальные clockless CPU имели достаточно классические системы комманд
22:30.@roman01la Charles Moore вон выпускает сейчас clockless CPU который по сути дела реализует Forth. ничего необычного :)
22:32.@roman01la с другой стороны я стал сейчас искать последние новости --- оказывается IBM сделала en.wikipedia.org/wiki/TrueNorth
22:36.@roman01la я сомневаюсь что этот TrueNorth "a neuromorphic CMOS chip" программируется на каком-нибудь С++ или JS
22:38.@roman01la нашел я, как они его программируют dl1.frz.ir/FREE/papers-we… вообщем это из другой реальности все.
22:44.@roman01la лучше уж посмотреть на Chuck Moore с его 144 core Forth CPU infoq.com/presentations/… это как-то ближе и понятнее
22:45# Среда 41 твит
начнем утро головоломкой из разряда "и на старуху бывает проруха" jsperf.com/es6-map-vs-obj…
7:43... напихали в объект кучу свойств obj[keys[i]] = i и почему-то читать эти свойства быстрее c ключами из Object.keys(obj), а не из keys
7:48@jsunderhood пользуешься ли ты IDE для C++? Xcode?7:49
.@vecmezoni нет, я пишу код в Sublime Text - основная рабочая машина у меня на Linux.
7:49никто что-то не спешит отгадывать мою головоломку, а я меж тем пью кофе из своей любимой JS-кружки pic.twitter.com/mA61kNUbSs
11:01@jsunderhood о, расскажи про kinesis, как тебе?11:33
.@23ydobemos спас меня от боли в запястьях - пять лет использую, только радость :)
11:35отгадка на загадку: дело в том, что obj[key] быстрее всего работает когда key - это интернализованная строка.
14:03... массив keys содержит строки результаты конкатенации, которые в V8 не интернализованы, а objectKeys содержит интернализованные строки.
14:04... потому что имена свойств внутри объекта V8 хранит в интернализованных виде -> Object.keys(obj) возвращает массив интернализованных строк
14:07@jsunderhood Что такое интернализованные строки? Без этого не понятно, откуда берется оптимизация.14:25
.@roman01la если A и B две интернализованные строки, то A === B только в том случае если A и B это один и тот же объект.
14:27.@roman01la иными словами интернализация строки - это поиск посимвольно равной ей строки в некотором глобальной таблице.
14:28.@roman01la подробнее: en.wikipedia.org/wiki/String_in…
14:28.@roman01la некоторые реализации некотрых языков, наприер, Lua интернализуют все строки
14:29.@roman01la V8 интернализует только некоторые, поэтому возможно ситуация что две посимвольно равные строки представлены разными объектами
14:29.@roman01la здесь под "объектом" понимается объект уровня реализации, а не языка. из JavaScript это заметить нельзя
14:31@jsunderhood Выходит, что V8 тогда не сравнивает посимвольно, а по внутреннему объекту, которому принадлежит строка?14:37
. @roman01la разумеется где-то далеко внутри операции obj[key] V8 сравнивает строки посимвольно (иначе это была бы неправильная реализация)
14:38.@roman01la но в начале, на fast path, она пробует найти ключ в словаре простым сравнением указателей.
14:39.@roman01la и вот как раз случай obj[objectKeys[i]] всегда попадает на этот fast path и никогда не идет в slowPath.
14:40в сорцах chromium есть прикольные тулзы: вот, например, одна раскладывает бинарник на части и рисует с помощью d3 pic.twitter.com/LK50ttKymi
15:33... можно кликая найти из какого файла пришла куча кода в бинарник, сама тулза здесь -> chromium.googlesource.com/chromium/src/+…
15:34@jsunderhood @roman01la Получается V8 копирует строки? Крайне не экономное расходование памяти.можно же владеть указателем на один объект16:59
.@reklatsmasters зависит от того, что вы вкладываете в понятие "копирует" и при каких условиях. допустим вы сложили две строки A + B
17:02.@reklatsmasters если бы V8 всегда интернила результат конкатенации ей надо было бы ее выполнить и пойти искать равную строку в таблице
17:03.@reklatsmasters вместо этого V8 на самом деле производит аналог rope - Const String фактически пару указателей (A, B) и не копирует ничего
17:04.@reklatsmasters таким образом экономится и память и время на копирование и интернинг.
17:05.@reklatsmasters конечно возможно такая ситуация, что вы производите много копий одной и той же строки "aaaa" + "bbbb" и храните их все
17:06.@reklatsmasters в этом случае интернинг бы существенно сэкономил память. но не ясно насколько это частный случай? скорее всего не очень.
17:07.@reklatsmasters поэтому ухудшать общий случай операции со строками - ради оптимизации частного не стоит.
17:08.@reklatsmasters программист может попрофилировать потребление памяти и сделать руками interning
17:09.@reklatsmasters вот какая-то такая логика стоит за не интернингом всех подряд строк. строковые литералы "a" и ключи всегда интернятся.
17:10про строки (я от этих картинок даже прослезился, вспомнив как конспекты одногрупниц ксерил) pic.twitter.com/bDzh96Kvkx
17:45@jsunderhood flatten-строка быстрее? Может какие-то конкретные операции? Стоит игра свеч? @roman01la18:33
.@oelifantiev из flatten строки очевидно быстрее брать по индексу. этим чаще всего заморачиваться *не* надо - V8 сама их плющит
18:33@jsunderhood после какого объема ключей деградирует производительность объекта?18:35
.@oelifantiev на этот вопрос простого ответа нет - зависит от того как объект создан и что понимается под "производительностью объекта"
18:36.@oelifantiev эвристики для перехода в словарное представление периодиечески меняются, поэтому конкретными цифрами заморачиваться нет смысла
18:37@jsunderhood насколько возможно и целесообразно заранее "прогревать" JIT для некого кода, который вероятно скоро будет вызван?18:37
.@dmitryshimkin прогревать можно, но для больших приложений сложно - и если у вас этот код горячий он и сам постепенно прогреется.
18:38# Четверг 3 твита
сегодня был самый безвопросый день - все JS программисты видимо готовятся к выходным
19:47@jsunderhood Правду пишут? twitter.com/roman01la/stat…22:39
.@roman01la да
22:39# Пятница 9 твитов
внезапно натолкнулся на вопрос про таинственное замедление JS кода в Chrome stackoverflow.com/questions/2942…
8:41... глянул на это дело в IRHydra по быстрому: оказывается это связано с тем, что сломалась одна оптимизация, которую я делал 3 года назад
8:42... карма. вот так сделаешь оптимизацию, уйдешь в другой проект - а оптимизация все живет и живет своей жизнью и периодически ломается
8:44... отгадка - что сломалось и как чинить, будет через час :)
8:45добрался до написания ответа на утренний вопрос stackoverflow.com/questions/2942… и фикса этого бага codereview.chromium.org/1077113002/
13:01чем короче фикс, тем сложнее объяснить почему что-то в оптимизаторе не работает без него
13:05выходные надвигаются, пора закоммитить что-нибудь и убежать.
16:51не знаю как вас, а меня расстраивает, что я не могу написать [1,2,3,4].reduce(Math.max) в JS
19:29ну т.е. я, конечно, могу написать, но толку с этого особо не будет.
19:30# Ссылки
mrale.ph
- http://mrale.ph/irhydra/2/#gist:88ef8e9f7d8b17090777
- http://mrale.ph/irhydra/2/
- http://mrale.ph/blog/2013/03/28/why-asmjs-bothers-me.html
- http://mrale.ph/blog/
- http://mrale.ph/saga/
- http://mrale.ph/blog/2015/04/12/jsunderhood.html
- http://mrale.ph/
other
- http://llvmweekly.org/issue/66
- https://people.mozilla.org/~jorendorff/es6-draft.html#sec-%typedarray%.prototype
- https://gist.github.com/mraleph/88ef8e9f7d8b17090777
- https://gist.github.com/mraleph/141f0ed76bd24fb28243
- http://fantlab.ru/work65898
- https://mpi-sws.org/~viktor/papers/popl2015-c11comp.pdf
- https://docs.google.com/document/d/1NDGA_gZJ7M7w1Bh8S0AoDyEqwDdRh4uSoTPSNn77PFk/view
- https://github.com/v8/v8-git-mirror/blob/ba41489da55a3484ceb5ac84c07de546578a2161/src/array.js#L1176-L1205
- https://github.com/babel/babel/issues/1176
- https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript
- http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects
- http://arewepythonyet.com/
- https://www.youtube.com/watch?v=_2xa46ytiSs
- https://www.youtube.com/watch?v=foGkU6x3eSE
- https://developers.google.com/v8/experiments
- http://en.wikipedia.org/wiki/TrueNorth
- http://en.wikipedia.org/wiki/String_interning
- http://dl1.frz.ir/FREE/papers-we-love/new_paradigms/cognitive-computing-programming-paradigm-corelet-language.pdf
- http://www.infoq.com/presentations/power-144-chip
- http://jsperf.com/es6-map-vs-object-lookup
- https://chromium.googlesource.com/chromium/src/+/master/tools/binary_size
- http://stackoverflow.com/questions/29424013/strange-javascript-performance
- http://stackoverflow.com/questions/29424013/strange-javascript-performance/29562128#29562128
- https://codereview.chromium.org/1077113002/
- http://stefan-marr.de/papers/pldi-marr-et-al-zero-overhead-metaprogramming/