Как стать автором
Обновить

Комментарии 17

К сожалению, понятие "тип" (type) для JavaScript уже используется в другом значении. К примеру:


const arr = [1, 2, 3];

Тип (type) элементов — number; сорт элементов (elements kind) — PACKED_SMI_ELEMENTS.

Тогда «содержимое». Не знаю почему, но мне очень режет глаз такой перевод.

Слоупок на связи и соощает, что наличие типов в самом языке js никак не резервирует этот термин в рантайме. В языке могут быть свои типы, в реализации v8 внутри свои типы и ничто не мешает их так называть. Сорта элементов для заголовка норм, отсылка на мем, но как термин сильно режит ухо.

А почему преобразование в реальный Array сделано через Array.prototype.slice, а не через стандартный Array.from?

Этот вопрос нужно задать автору оригинала. Я бы, действительно, использовал Array.from.


Мое предположение в том, что статью начали писать до того, как стали широко доступны возможности ES 2015.

Кто-нибудь вникал как оно устроено под капотом? Было бы интересно узнать в каких случаях v8 использует адрессную арифметику вида:


const arr = [0,1,2,3,4];
arr[3]; // &arr + sizeof(arr[0]) * 3

Полагаю для holed это невозможно. Но используется ли это в случае packed? Хранится ли это всё в одном последовательном блоке памяти или оно дробится на chunk-и? По сути насколько эти elements близки к нормальным массивов из языков со статической системой типов.

Про это можно почитать подробнее, например, в этой статье (кажется, мне стоило сначала перевести ее, а не эту :)


Если совсем коротко: есть два основных способа хранения: fast (массив) и slow (словарь). Packed элементы всегда хранятся в массиве, для holey-элементов есть два варианта: массив со специальным значением для "дырки" или словарь.

Спасибо за ссылку. Я эту статью даже пару лет назад читал вроде.


Fast elements are simple VM-internal arrays where the property index maps to the index in the elements store

По сути это всё что я там нашёл про это. Т.е. всё упирается в то, что такое VM-internal arrays и как они map-ят индексы к the elements store. Наверное это классические цельно-блочные массивы с адресной арифметикой.

Нашёл


TNode<IntPtrT> CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
                                                         ElementsKind kind,
                                                         ParameterMode mode,
                                                         int base_size) {
  // ...

  if (constant_index) {
    return IntPtrConstant(base_size + element_size * index);
  }

Кажется это оно.

Вместо arguments следует использовать rest parameters, доступные, начиная с ECMAScript 2015. Они являются настоящими массивами, и к тому же выглядят более читаемо.

Только не забудьте скормить это бейбел и преобразовать автоматически обратно в работу с arguments.


Вообще статья интересная, но проблема в том, что в js мало того что часто нужно поддерживать старые браузеры все ещё, так и оптимизации не стабильны — выход новой версии движка может как и смягчить правила, так и ужесточить. Как было с исключениями — сперва они ломали JIT, теперь не ломают, так и тут выход за пределы может перестать быть условием превращения массива в более медленный

Я считаю, что не все так плохо.


Только не забудьте скормить это бейбел и преобразовать автоматически обратно в работу с arguments.

caniuse говорит, что ES6 (он же ES2015), где ввели rest parameters, есть у порядка 95% пользователей. Мне кажется, что для большинства вебсайтов как раз этот стандарт логично брать как минимальный поддерживаемый.


в js мало того что часто нужно поддерживать старые браузеры все ещё

Есть как минимум два случая, когда это не так: Node.js и Electron. В случае разработки под эти платформы нам точно известен движок и его (минимальная) версия, и можно сознательно рассчитывать на оптимизации.

Так то оно так, но мы долго выбивали себе отказ от старых IE (потому что продажникам конечно удобнее написать что работает хоть в нетскейп). Вообще помогает делать две сборки — под старые и новые браузеры, задача решаемая, но много ли людей ее решают?


Про Электрон согласен, но сложно представить числодробилку на nodejs, а массивы из трёх элементов (которые обычно вообще по объектам, а не числам) оптимизировать — экономить на спичках. Справедливости ради, не ходить за пределы массива и использовать ...rest вместо аргументов — хорошие практики сами по себе, но разряженность массивов — последнее, чтобы я советовал оптимизировать.


К слову, если уж на то пошло, часто стоит задуматься об использовании Set вместо массива если вы хотите проверить находится ли свойство в перечне.

Ну т.е. я помню времена когда спорили что одинарные кавычки работают быстрее двойных и все как бешеные исправляли это. А на практике прирост нулевой. Так и тут — я уже вижу как впечатлительные коллеги будут комментировать что у меня разряженный массив (хм, вообще очень редкая ситуация если так подумать), а сами будут использовать reduce, пересоздавая массив на каждом элементе. Зато неразряженный!

Справедливости ради, автор явно отмечает, что в большинстве случаев не стоит таким заморачиваться. А именно про разреженные массивы даже отдельно говорит, что прирост, чаще всего, будет незаметен.


Карго-культ из таких советов делать, разумеется, не стоит. Но они помогают лучше понять, почему какой-то код может быть медленнее, чем другой.

спорили что одинарные кавычки работают быстрее двойных и все как бешеные исправляли это.

А расскажите подробнее, пожалуйста? Я этих времен не застал, и теперь очень интересно. Это действительно было правдой?

Это из PHP, там в двойных кавычках текст интерпретируется, в одинарных нет. Звучит логично, что двойные должны быть медленннее, но на практике это было экономией на спичках. Не уверен как дела сейчас обстоят.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории