Привязка данных в Dart вдохновлена MDV (Model Driven Views), который действительно не является частью вебкомпонентов. Однако, части необходимые для MDV постепенно проникают в платформу:
скрытые классы всегда используются. словарное представление тоже имеет скрытый класс, который собственно и говорит что поля представлены словарем.
превратится-ли result в словарь зависит от количества полей и некоторых других факторов.
основное ускорение здесь получается от того, что вы полустатическим образом фиксируете структуру литерала в коде, не нужно ничего растить и т.д., то, что он не перейдет в словарь дополнительная плюшка из этого.
ну и eval'а на V8 нужно избегать как огня — произведенный им код не оптимизируется. хотя в данном конкретном случае это и не важно, потому что основное время тратится в клонировании object literal boilerplate, которое выполняется большей частью в стабе.
ничто не мешает, просто не реализованна нормальная протяжка констант. а без протяжки констант на одном локальном type feedback тут далеко не уедешь из-за полиморфизма точки вызова внутри цикла, который внутри forEach.
над каждым элементом функция честно вызывается. в зависимости от того, что функция делает цена этого вызова может быть заметна, а может быть амортизированна и не очень заметна.
если vector существует в единственном числе, то тут разницы между глобальным и не глобальным scope не должно быть.
Хранение 32-битных величин сложный вопрос. На ia32 те из них которые не влезают в smi (31-bit signed integer) превратятся в полновесные числа с плавающей точкой. Зависит от многих факторов: как много тех кто не влезает в 31бит, как они будут использоваться и т.д. Int32Array может оказаться оптимальным в некоторых случаях.
дырки это та проблема, которой рекомендации рекомендуют избегать, чтение из дырки требует поиска свойства через цепочку прототипов и оптимизированный код не любит этого и просто деоптимизируется. К тому же если у вас в массиве много дырок, то V8 может внезапно решить, что память важнее производительности и ради экономии места превратит длинный дырявый массив в словарь.
splice же, который удаляет и сдвигает элементы не оставляет после себя дырок, поэтому безобиден в данном отношении. Следует, впрочем, всегда помнить, что он имеет линейную сложность по количеству сдвигаемых элементов.
64-битная сборка только на Linux используется AFAIK
> Но у вас в блоге заметил странную магию с «use strict», который не дает захватывать контекст.
В данном конкретном примере "use strict" разрывает связь между arguments и формальными параметрами. Это убирает создание контекста и позволяет инлайнить этот код (если функция создает контекст, то такую пока V8 не инлайнит).
я бы сказал, что это спорная рекомендация и они совсем не эквивалентны. все конечно же зависит от конкретного кода, splice, например, линейная операция по количеству сдвигаемых элементов. в каких-то случаях может лучше arr[i] = null; делать (хоть оно и не эквивалентно delete)
1. По типу содержимого быстрые элементы бывают трех видов и трансформируются в одном направлении от менее общих к более общим: smi (small integer) -> double -> object. Бывают еще дырявые (holey) и непрерывные (packed). Еще бывают медленные элементы — представляются словарем.
2. Рекомендация соблюдать мономорфизм относится не к функциям, а к отдельным операциям, например, оператору умножения, оператору [] или вызову метода. Операции работают быстрее, когда они мономорфны — выполнятся над объектами одного и того же типа/скрытого класса. Как вы определяете «полиморфную функцию»?
3. V8 инлайнит функции, которые требуют переключения контекста на ia32 (Mac, Windows), но не инлайнит на x64/arm. Что касается функционального программирования, то зависит от того какие именно паттерны мы сравниваем. В большинстве случаев ООП основанное на связке constructor + prototype chain имеет больше шансов быть хорошо заоптимизированным. Можно почитать мой блог о том, какие именно проблемы возникают если опираться на замыкания: mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html
А собственно кроме узких мест ничего никогда тюнить и не надо. Все советы по оптимизации бесполезны в 99% случаев, пока вы не наткнетесь на случай попадающий в злые 1%, где надо костьми лечь но выжать все что можно.
groups.google.com/d/msg/mdv-discuss/I6oiK8z0LdI/H3i4MlszsFcJ
eval
ом код не оптимизируется. Ноnew Function
— неeval
, поэтому произведенный им код оптимизируется.превратится-ли
result
в словарь зависит от количества полей и некоторых других факторов.основное ускорение здесь получается от того, что вы полустатическим образом фиксируете структуру литерала в коде, не нужно ничего растить и т.д., то, что он не перейдет в словарь дополнительная плюшка из этого.
ну и
eval
'а на V8 нужно избегать как огня — произведенный им код не оптимизируется. хотя в данном конкретном случае это и не важно, потому что основное время тратится в клонировании object literal boilerplate, которое выполняется большей частью в стабе.Библиотека имеет некоторое сходство с Java, но также и имеет и сходство с JavaScript. К тому же она в активной переработке.
for
если зарядить на длинном массиве, много-много раз пустую функцию то будет видна цена вызова.над каждым элементом функция честно вызывается. в зависимости от того, что функция делает цена этого вызова может быть заметна, а может быть амортизированна и не очень заметна.
если vector существует в единственном числе, то тут разницы между глобальным и не глобальным scope не должно быть.
Хранение 32-битных величин сложный вопрос. На ia32 те из них которые не влезают в smi (31-bit signed integer) превратятся в полновесные числа с плавающей точкой. Зависит от многих факторов: как много тех кто не влезает в 31бит, как они будут использоваться и т.д. Int32Array может оказаться оптимальным в некоторых случаях.
прежде всего
delete
не прописываетundefined
, он удаляет свойство полностью оставляя вместо него дырку. разницу просто увидеть на примере кода:дырки это та проблема, которой рекомендации рекомендуют избегать, чтение из дырки требует поиска свойства через цепочку прототипов и оптимизированный код не любит этого и просто деоптимизируется. К тому же если у вас в массиве много дырок, то V8 может внезапно решить, что память важнее производительности и ради экономии места превратит длинный дырявый массив в словарь.
splice
же, который удаляет и сдвигает элементы не оставляет после себя дырок, поэтому безобиден в данном отношении. Следует, впрочем, всегда помнить, что он имеет линейную сложность по количеству сдвигаемых элементов.Chrome на Mac по сей день 32-битный
64-битная сборка только на Linux используется AFAIK
> Но у вас в блоге заметил странную магию с «use strict», который не дает захватывать контекст.
В данном конкретном примере
"use strict"
разрывает связь междуarguments
и формальными параметрами. Это убирает создание контекста и позволяет инлайнить этот код (если функция создает контекст, то такую пока V8 не инлайнит).Strict mode описан в стандарте: es5.github.com/#C
> как можно заставить заинланиться некоторые мои функции (например математические).
Если вы набросаете примеры кода, то можно будет обсудить почему что-то не инлайнится и какая будет польза от инлайна :-)
splice
, например, линейная операция по количеству сдвигаемых элементов. в каких-то случаях может лучшеarr[i] = null;
делать (хоть оно и не эквивалентноdelete
)--trace-deopt
действительно выпилили.Что касается
--trace-op
t/--trace-deopt
то они ничего не выводят если ничего не оптимизируется/деоптимизируется. Попробуйте какой-нибудь горячий цикл.2. Рекомендация соблюдать мономорфизм относится не к функциям, а к отдельным операциям, например, оператору умножения, оператору [] или вызову метода. Операции работают быстрее, когда они мономорфны — выполнятся над объектами одного и того же типа/скрытого класса. Как вы определяете «полиморфную функцию»?
3. V8 инлайнит функции, которые требуют переключения контекста на ia32 (Mac, Windows), но не инлайнит на x64/arm. Что касается функционального программирования, то зависит от того какие именно паттерны мы сравниваем. В большинстве случаев ООП основанное на связке constructor + prototype chain имеет больше шансов быть хорошо заоптимизированным. Можно почитать мой блог о том, какие именно проблемы возникают если опираться на замыкания: mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html
А собственно кроме узких мест ничего никогда тюнить и не надо. Все советы по оптимизации бесполезны в 99% случаев, пока вы не наткнетесь на случай попадающий в злые 1%, где надо костьми лечь но выжать все что можно.
тест кстати слегка шумный: например, непонятно зачем там создается closure на каждую итерацию цикла.