Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как JS соединяет значения в шаблонной строке? (https://javascript.ru/forum/misc/78174-kak-js-soedinyaet-znacheniya-v-shablonnojj-stroke.html)

Malleys 07.08.2019 01:56

Цитата:

Сообщение от SuperZen
ну получается magic quotes продуктивнее ) в моем браузере...

Вы в своём тесте специально подобрали такое вычисление, которое показывает, что первый тест быстрей выполнится.

Цитата:

Сообщение от рони
Google Chrome, Firefox, последние, если менять очерёдность массивов, то массив, созданный первым, быстрее проходит тест, у меня так.

Логично, ведь первый тест раньше выполняется.

Научное измерение длительности какого-либо процесса выглядит так:
  • Измерить начальное время t₀
  • Запустить и дождаться окончания процесса
  • Измерить конечное время t₁

Разность Δt = t₁ − t₀ указывает на длительность процесса. При необходимости можно повторить процесс измерения несколько раз и найти среднее арифметическое для получения усреднённого результата.

Я думаю, что два вычисления не отличаются по эффективности (т. е. они одинаково эффективны), если время их выполнения различается не более чем на полпорядка.
(function(size, iterations, tests) {
	console.log('I assume I break NOTHING \uD83D\uDE1C')

	var iterationsResult = [];

	for(var i = 0; i < iterations; i++) {
		var v = 100 + Math.round(1400 * Math.random());

		iterationsResult.push(tests.map(test => ({
			start: performance.now(),
			value: Array.from({ length: size }, () => test(v)),
			end: performance.now(),
			get dt() { return this.end - this.start }
		})));
	}

	var times;
	console.table(
		(times = iterationsResult
			.reduce((memo, results) => results.map((result, i) => memo[i] + result.dt), new Array(tests.length).fill(0))
			.map(v => v / iterations / size))
			.reduce((m, v, i) => ({ ...m, [tests[i]]: {
				duration: `${(1000000 * v).toFixed(3)} ns`,
				order: 0.5 * Math.round(2 * Math.log(v / 1000) / Math.log(10))
			} }), {})
	);
}
)(100000, 10, [
	randomValue => `${randomValue}px`,
	randomValue => randomValue + "px",
	_ => {}
])
В таблице, которую вы видите в консоли, представлены три столбца: в первом указана выполняемая функция, во втором указано вычисленное время выполнения одной такой функции, в третьем вычислен порядок времени выполнения с точностью до полпорядка.


Например, такой результат означает, что и шаблонные строки и обычные одинаково эффективны. (А, например, вычисление пустой функции на полпорядка меньше, а значит более эффективно, чем любая строка)

j0hnik 07.08.2019 03:31

Лучше больше итераций, разброс как всегда большой.

рони 07.08.2019 14:36

Цитата:

Сообщение от Malleys
Логично, ведь первый тест раньше выполняется.

какая связь между местом в массиве и скоростью выполнения?

Alexandroppolus 07.08.2019 15:18

Цитата:

Сообщение от рони
какая связь между местом в массиве и скоростью выполнения?

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

А по сабжу - сильно подозреваю, что современные компиляторы js (по крайней мере, оптимизирующие компиляторы) превращают оба варианта в один и тот же набор инструкций.

Malleys 07.08.2019 16:11

Цитата:

Сообщение от рони
какая связь между местом в массиве и скоростью выполнения?

Почему вы это у меня спрашиваете? Вы не понимаете, что написал SuperZen в его коде?

Цитата:

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

Удивительная подгонка мировоззрения под лживый тест!

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

Цитата:

Сообщение от рони
какая связь между местом в массиве и скоростью выполнения?

Поскольку SuperZen складывает показания часов, то тест находящийся на первом месте естественным образом будет иметь наименьшее показание!

Вот, например, у меня была открыта некоторое время страница с его кодом... Я скопировал код и выполнил в консоли...
Код:

BREAK THE MYTH ;p
size: 100000, iterations 10
tests[0] : 49098279.895
tests[1] : 49100864.53000001

Как следует понимать такие результаты, я не знаю. Оно показывает время с начала загрузки страницы до начала/окончания выполнения одного теста, сложенного с началом/окончанием выполнения второго теста... Что это обозначает, я не знаю!

В посте №11 я указал, как измеряется длительность какого-либо процесса.

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

рони, Alexandroppolus, вы конечно можете считать сколько угодно меня за идиота... ведь проблема именно в этом, а не в том, что вы якобы не видите, что в том тесте вовсе не измеряется время вычисления!

UPD И на всякий случай код SuperZen, о котором речь...
const obj = (function (size, iterations, tests) {
  console.log('BREAK THE MYTH ;p')
  const array = Array.from({ length: size })
  const iterator = Array.from({ length: iterations })
  const score = iterator.map(iter => tests.map(test => {
    const start = performance.now()
    test(array)
    const end = performance.now()
    return [start, end]
  })).reduce((acc, result) => {
    result.forEach(row => {
      row.forEach((r, i) => {
        acc[i] += r
      })
    })
    return acc
  }, Array(tests.length).fill(0))
  console.log(`size: ${size}, iterations ${iterations}`)
  score.map((s, i) => console.log(`tests[${i}] : ${s}`))
})(
  100000,
  10,
  [
    array => array.map((item, i) => `${i}myth`),
    array => array.map((item, i) => i + 'myth'),
  ],
)
Чтобы он его не поменял и потом не набежали лэймасы и не развели опусы о том, что там всё в порядке, а дескать это мализ во всём виноват...

рони 07.08.2019 16:26

Malleys,
я не понимаю достаточно хорошо ни ваш код, ни код SuperZen,
я незнаю почему первый бегун всегда бежит быстрее, чем все остальные..
что тут происходит order: 0.5 * Math.round(2 * Math.log(v / 1000) / Math.log(10)), для меня тоже тайна.

Malleys 07.08.2019 17:27

Цитата:

Сообщение от рони
я не понимаю достаточно хорошо ни ваш код, ни код SuperZen

Наверное вам стоит самим написать код, который измеряет время выполнения функции.

Цитата:

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

Я тоже не знаю... Но в мире SuperZen всё происходит именно так!

Цитата:

Сообщение от рони
что тут происходит order: 0.5 * Math.round(2 * Math.log(v / 1000) / Math.log(10)), для меня тоже тайна.

Тут вычисляется порядок времени выполнения с точностью до полпорядка.

Порядок позволяет классифицировать величины, например, единицы, десятки, сотни, тысячи... а также десятые части целого, сотые части целого, тысячные части целого... и т. д. Например, если говорить о секундах, то, например, 2 и 5 секунд могут быть отнесены к классу единиц... а, 2 и 50 секунд относятся к разным классам. (единицы и десятки)

Порядок, который вычисляется в примере, является показателем степени, в которую нужно возвести число 10.

Любое число можно представить в стандартной форме, в виде мантиссы и порядка.

Почему в приведённой теме так сильно уделяется внимание мантиссе. Например, приводится тест, в котором говорится, что один вариант выполняется на 3% быстрее. Но вы понимаете, что такое 3% от 100нс? Я думаю, что вы плохо это представляете.

При сравнении результатов мантиссу можно отбросить, не принимать её во внимание... Понятное дело, что если у вас оба процесса таким образом показывают, например, 10⁻⁷ сек. = 0.0000001 сек., то не имеет значения, какая там мантисса, оба варианта одинаково эффективны и быстры!

Другое дело, если отбросив мантиссы вы получаете, например, 10⁻⁷ сек. = 0.0000001 сек. и 10⁻⁵ сек. = 0.00001 сек., то так и так видно, что процесс длительностью 10⁻⁵ сек. менее эффективен. Не имеет значения, какая там мантисса.

Если вам нужно более точное сравнение, то можно воспользоваться такой формулой...
, где x₁ и x₂ — времена выполнения сравниваемых процессов, r — основание логарифма, в данной теме 10. При выполнении условия можно говорить об одинаковой эффективности!

рони 07.08.2019 17:39

Malleys,
спасибо.

SuperZen 07.08.2019 17:47

рони,
Malleys,

в моем коде была ошибка:
return [start, end]

был уверен, что я написал end - start )))

немного модифицированный вариант )
const obj = (function (size, iterations, tests) {
  console.log('BREAK THE MYTH ;p')
  const array = Array.from({ length: size })
  const iterator = Array.from({ length: iterations })
  const score = iterator.map(iter =>
    tests.map(test => {
      const start = performance.now()
      array.forEach((_, i) => test(i))
      const end = performance.now()
      return end - start
    }))
  console.table(score)
  const results = score.reduce((acc, results) => {
    results.forEach((result, i) => {
      acc[i] += result
    })
    return acc
  }, Array(tests.length).fill(0))
  console.table(results)
})(
  100000,
  10,
  [
    i => `${i}myth`,
    i => i + 'myth',
    () => { }
  ],
)


но теперь нет конкретного победителя, от рефреша к рефрешу новые результаты...

Malleys 07.08.2019 18:08

Цитата:

Сообщение от SuperZen
но теперь нет конкретного победителя, от рефреша к рефрешу новые результаты...

немного модифицировал вариант, чтобы выводило порядки одного вызова...
(function (size, iterations, tests) {
  console.log('BREAK THE MYTH ;p')
  const array = Array.from({ length: size })
  const iterator = Array.from({ length: iterations })
  const score = iterator.map(iter =>
    tests.map(test => {
      const start = performance.now()
      array.forEach((_, i) => test(i))
      const end = performance.now()
      return Math.log((end - start) / 1000 / size) / Math.log(10)
    }))
  console.table(score)
  const results = score.reduce((acc, results) => {
    results.forEach((result, i) => {
      acc[i] += result / iterations;
    })
    return acc
  }, Array(tests.length).fill(0))
  console.table(results)
})(
  100000,
  10,
  [
    i => `${i}myth`,
    i => i + 'myth',
    () => { }
  ],
)


Часовой пояс GMT +3, время: 18:59.