Pull to refresh
10
0
Yuri Karadzhov@Large

Пользователь

Send message
Так нет там ветвлений, там проверка входных параметров на соответствие ожидаемым, она достаточно простая, если она не проходит — все деоптимизация и попытка повторной оптимизации. Потому производительных жс выглядит довольно плохо так как приходится отказываться от любого вида мономорфизма. Иногда компилятор может быть уверенным на счет типа, если значение получено из типизированного массива (это пока не всегда хорошо работает, но это исправляют) или выполняется явное приведение типов. Так что в принципе как раз математику на жс писать можно довольно производительную, но на васм производительность будет более предсказуемой. По тестом это даже не на порядок, а в несколько раз 2-7.
Если тип не изменился — то не так уж и страшна эта проверка, так что не так все и плохо с математикой в js. Плохо правда, что не всегда делается приведение операций к типу данных и при сложении int8 могут использоваться операции над int32, но это сейчас в процессе доработки.

Поддержка int64 и вообще чисел произвольного размера добавлена в предложения.

На самом деле 53 и 11.
wasm не умеет dom, это работает только через внешние вызовы. игры и так в 3д рисуются, разве что частично UI бывает удобнее сделать на dom
сейчас это даже медленнее так как из wasm просто дергаются внешние функции на js, сама же wasm ничего о дом не знает и умеет только считать int и float 32 и 64, да в линейную память писать.
ну посмотрите, там ведь так и написано декоратор применяется к классу.

нет нельзя, класс может наследоваться от чего-то другого, так что нужен именно декоратор-миксин.
Что в коде и делается. Там одна описка при проверке на итератор тоже нужно проверять прототип. А так как раз изменяется прототип класса, а не каждый объект.
Можно написать простенький декоратор который будет это делать для синхронного или для асинхронного итератора. Пример map:
function functor(Target) {
  if(!Reflect.has(Target, Symbol.asycIterator)) throw new Error(`${Target} should be async iterable`);
  if(!Reflect.defineProperty(Target.prototype, 'map', {
    value: async function(transform) {
      const res = [];
      for await(const el of this) {
        res.push(transform(el));
      }
      return res;
    }
  }) throw new Error(`${Target} already has a map method`);
 return Target;
}

@functor // или после объявления класса functor(Queue) если не хочется включать бабель для декоратора
class Queue {...}

В данном примере map просто асинхронно выгребет коллекцию, применит к ней заданную трансформацию и вернет промис с результатом, но можно поведение усложнять и генерировать события на каждый приход элемента.
Загвоздки нет, просто код будет выглядеть менее уродски. Вот аналог с обычным итератором:
for(const taskPromise of queue) {
  const task = await taskPromise;
  task ? resolve(task) : break;
}

Просто итератор будет бесконечный и проверку на выход прийдется делать руками каждый раз. В случае же асинхронного итератора у вас проверка будет спрятана в сам итератор и он не будет бесконечным.
Просто в жс быстрый код — это обычно уродский код, а его не так просто поддерживать. Понятно, что стоит выделять критические места типа работы с многомерными массивами в библиотеки и их уже максимально оптимизировать. Но проект лучше держать в читабельном виде максимально долго.
Для тежелых операций f, g разница не может быть в два раза, если операции очень дешевые, то оверхед может быть заметен и как раз и будет давать разницу в два раза.

Как правило, если проект большой, лучше писать красивее и понятнее, а уже потом думать о скорости. Часто узкие места появляются совсем не там где их ждешь.
А почему я их не должен использовать? Я и Foldable монады использую с их методом reduce там где это помогает читабельности. Оптимизация — это уже второй вопрос, где нужно можно и через цикл переписать, но обычно до этого не доходит, тем более на этом много не выиграешь.

В моно у вас компилятор перед выполнением все проверки сделает и выдаст вам идеальный машинный код, а в жс это все будет делать JIT ему прийдется многое угадывать и про ваш элемент и про ваш предикат. А если код который будет выполняться в компиляторе написан на смеси жс и с++ (да v8, это как раз компилятор с++ на жс и с++) то у вас будет теряться время на переход, так что не все так просто.
Я про внутреннюю реализацию в браузере, сейчас в v8 эти методы переводят на с++ и они будут инлайнится компилятором чтоб убрать расходы на переключение между с++ и js и повысить производительность. Про O(n) — сравните 100 n и n ** 2 при небольших n — или n и 10000 n, все имеет значение, для этого и используют комбинированные алгоритмы. У меня повседневное использование это счет и отрисовка графики, компилятор — нет, хотя не вижу в этом ничего дурного, но кодеки писали, не сказал бы, что мы что-то делаем не так.
Нативный метод может быть реализован на javascript или еще хуже — смеси c++ и javascript, сейчас почти все методы массива не оптимизированы на типизированных массивах. O(n) тоже бывает разным.
оверхед самого цикла не большой потому разница между
for(const el of arr) {f(el); g(el);}

и
for(const el of arr) f(el);
for(const el of arr) g(el);

не значительна
Паша, ну не редакс заставляет людей писать быдлокод, а руки-крюки. Проблема не в языке, везде нужно мастерство, чтоб сделать что-то стоящее. А юнити с ассет стором как раз сделал разработку ширпотребной, с пхп сравнить нельзя, но посмотри внутрь популярных плагинов и печалью наполнятся дни твои =)
Сейчас контекста операции нет и работает это не так, просто независимо друг от друга операнды без знания операции приводятся к примитивам, а затем происходит операция. Если проверять как говорите вы — прийдется сильно менять существующую схему работы. Как оно будет реализовано в итоге и будет ли пока загадка, я просто предположил как это может быть сделано дешево, с минимальными изменениями и добавлением дополнительного контекста.
Просто никому ее не показывайте и вред будет минимальным =)
Потому что могу)

Так наверняка можете и что-то более производительное и рабочее сделать тут главное не превращать все в монады, а оборачивать. Если решите поиграться — смотрите на спецификацию FantasyLand.
Да, я тоже мечтаю именно о такой реализации, но пока основная загвоздка в механизме работы арифметических операций, пока операнды приводятся к примитивам независимо друг от друга ничего об операции не зная и до выполнения операции, это хорошо работает для примитивов, но плохо сочетается с перезагрузкой, поэтому нужна новая схема применения операторов. Мне кажется через контекст операции это реализуется проще всего. Сначала каждый из операндов регистрирует себя в контексте операции (сейчас с помощью Symbol.toPrimitive можно регистрироваться в глобальном контексте), а затем во время вычисления операции нужно проверять — если контекст не пустой, то уже зная операцию вызывать нужный переопределенный метод для операндов из контекста (сейчас этого шага нет и операция просто проходит с примитивами, а в случае с фейковой перезагрузкой нужно иметь какой-то оберточный метод который будет проводить данную операцию для возвращения результата из контекста). Это кажется наименее затратной схемой которая минимально меняет правила применения операндов и видимо не особо повлияет на производительность для операций с примитивами (добавится простая проверка пустоты контекста).
Она понемногу появляется, можно например перезагружать оператор for-of через переопределения Symbol.iterator, можно перезагружать оператор точка (получение свойства) через прокси и т.д. Все к этому движется в основном благодаря символам, арифметические операции выполняются по другим правилам (если встречается объект он приводится с помощью Symbol.toPrimitive к примитиву) но возможно они введут новый символ который будет создавать контекст для операции (что-то по типу того как делается в фейковой перегрузке операторов, только не глобальный контекст, а именно локальный для операции).

Information

Rating
Does not participate
Date of birth
Registered
Activity