Что касается кода для неизвестного движка Javascript, какие соображения оказывают наибольшее влияние на скорость выполнения и сохранение памяти?

Затем, я полагаю, более полный вопрос звучит так: "Как влияют эти соображения, когда известен движок Javascript (в расчете на популярный движок)".

Мне кажется, что мне нужно спросить "сообщество", потому что такие, как Strongloop, которые создают такие вещи, как Node.js, также пишут код, подобный util.inherits, функция внутри которого вместо: TheConstructorFunction.prototype.constructor = TheConstructorFunction они создают определение свойства, которое само имеет 4 устанавливаемых свойства:

ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
        value: ctor,
        enumerable: false,
        writable: true,
        configurable: true
    }
});

Это кажется мне неэффективным, но тогда я только 3 года стремился писать лучше Javascript, в отличие от авторов такого кода. Есть ли объяснение, почему это эффективно или неэффективно?

В одном ответе говорится, что util.inherits не является неэффективным, поскольку операции с подклассами редки. Но, учитывая, что некоторые библиотеки имеют дело с сотнями и тысячами операций подкласса, происходящих между сборкой и наблюдением за результатами теста, если Node.js внутренне использует util.inherits, то это влияет на время разработки его потребителей. Я думаю, что на этом уровне эффективность имеет значение, и я надеюсь, что util.inherits не используется внутренне. Я даже не понимаю цель использования util.inherits. Зачем это вообще нужно? Я думаю, что это способствует усугублению неэффективности. require('util').inherits(C1,C2); почти синоним и, вероятно, медленнее, чем C1.prototype=Object.create(C2.prototype); C1.prototype.constructor=C1; Если это просто для того, чтобы заманить потребителей, я к этому хорош. Меня беспокоит, если эти профессионалы используют эту функцию внутри, так как большие библиотеки будут зависеть от эффективности Node.js. Что касается изготовления .constructor non-enumerable... Я думаю, что случай, когда его "перечислимость" имеет значение, редок и должен быть оставлен на усмотрение потребителя, но если внутренние операции зависят от util.inherits, это на самом деле не оставлено на усмотрение потребителя.

2 ответа

Это кажется мне неэффективным

Нет. Эффективность здесь не имеет значения. Создание подклассов является редкой операцией, и даже если код будет медленнее, чем простое присваивание (скорее всего, разница невелика), это не влияет на производительность.

Что важно, особенно для библиотечных функций, таких как utils.inherit которые используются везде, это правильность. Так почему же они используют атрибуты свойств? Чтобы сделать .constructor не перечисляемый, как это стандартно для .prototype объекты, которые изначально созданы и, следовательно, обычно ожидаемы.

Учитывая, что здесь не нужно учитывать ни скорость, ни память, оптимизаций, как вы, вероятно, ожидаете, здесь не происходит.

На это лучше всего отвечают авторы движков JavaScript.

Этот процесс называется настройкой производительности.

Вот руководство Google. Вот руководство Mozilla.

Заставить Node.js быстро запускать javascript - это ядро ​​бизнеса Strongloop. Они серьезно относятся к оптимизации JavaScript.

Есть несколько таких ошибок.

Хотя в основном не блокируйте цикл обработки событий - используйте обещания, асинхронные операции, обратные вызовы и т. Д.

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

Как только вы дойдете до основной причины вашего поиска настройки производительности, вы должны начать копать глубже. Вы должны профилировать свой код.

У Торстена Лоренца есть устаревшее, но все еще в основном актуальное хранилище GitHub, которое содержит много полезной инсайдерской информации о V8.

Есть много разработчиков, которые публикуют статьи в блогах, как этот парень. Вы должны убедиться, что они знают, о чем говорят. Он делает.

Bluebird, хорошо известная реализация Promises, - вершина правильной оптимизации. У них есть статья и руководство по тем вещам, которые они отметили, которые являются просто общими вещами, которые убивают оптимизацию.

Обновить

Пример, который вы привели для реализации util.s цепочки наследования, вероятно, должен быть отдельным вопросом. Я не уверен, что если они там будут мартышки, я бы посмотрел остальную часть класса и прототипы.

См. Эту статью MDN о плюсах и минусах и вариациях известных способов реализации наследования, особенно для использования Object.create Но и другие тоже.

Единственная веская причина для расширения встроенного прототипа (также называемого "исправлением обезьян") - это поддержка возможностей новых движков JavaScript; например Array.forEach и т. д.

Вот некоторые рассуждения о том, почему это делается. Не так давно я ответил на вопрос о введении класса в начало цепочки наследования с целью добавления метода расширения всем своим детям. Это не отличная идея.

Оказывается, Object.create в util.js реализация inherits возможно, изначально была попытка оптимизации. Согласно ранним изменениям, это сделало прототип неявно неизменным, теоретически улучшив производительность разрешения метода. Говоря педантично, это никогда не было правильно, и всегда было по сути взломом возможностей наследования прототипов JavaScript. Новые ревизии заменяют это на Object.setPrototypeOf,

Изменить: Если вы проголосовали против, я был бы признателен, почему.

Другие вопросы по тегам