Контролируйте и точно измеряйте, как долго изображение отображается
Для изучения времени реакции ( см. Также этот вопрос, если вам интересно) мы хотим контролировать и измерять время отображения изображений. Мы бы хотели учесть время, необходимое для перекраски на машинах разных пользователей.
Редактировать: Первоначально я использовал только встроенное выполнение для синхронизации и думал, что не могу доверять ему, чтобы точно измерить, как долго картинка была видна на экране пользователя, потому что рисование занимает некоторое время.
Позже я обнаружил событие " MozAfterPaint ". Требуется изменение конфигурации для запуска на компьютерах пользователей, и соответствующий WebkitAfterPaint этого не сделал. Это означает, что я не могу использовать его на компьютерах пользователей, но я использовал его для собственного тестирования. Я вставил соответствующие фрагменты кода и результаты моих тестов ниже.
Я также вручную проверил результаты с помощью SpeedTracer в Chrome.
// from the loop pre-rendering images for faster display
var imgdiv = $('<div class="trial_images" id="trial_images_'+i+'" style="display:none"><img class="top" src="' + toppath + '"><br><img class="bottom" src="'+ botpath + '"></div>');
Session.imgs[i] = imgdiv.append(botimg);
$('#trial').append(Session.imgs);
// in Trial.showImages
$(window).one('MozAfterPaint', function () {
Trial.FixationHidden = performance.now();
});
$('#trial_images_'+Trial.current).show(); // this would cause reflows, but I've since changed it to use the visibility property and absolutely positioned images, to minimise reflows
Trial.ImagesShown = performance.now();
Session.waitForNextStep = setTimeout(Trial.showProbe, 500); // 500ms
// in Trial.showProbe
$(window).one('MozAfterPaint', function () {
Trial.ImagesHidden = performance.now();
});
$('#trial_images_'+Trial.current).hide();
Trial.ProbeShown = performance.now();
// show Probe etc...
Результаты сравнения длительностей, измеренных с использованием MozAfterPaint и встроенного выполнения.
Это не делает меня слишком счастливым. Во-первых, средняя продолжительность отображения примерно на 30 мс меньше, чем хотелось бы. Во-вторых, дисперсия с использованием MozAfterPaint довольно велика (и больше, чем для встроенного выполнения), поэтому я не могу просто настроить ее, увеличив setTimeout на 30 мс. В-третьих, это на моем довольно быстром компьютере, результаты для других компьютеров могут быть хуже.
Результаты от SpeedTracer
Это было лучше. Время, когда изображение было видимым, обычно находилось в пределах 4 (иногда) 10 мс от предполагаемой продолжительности. Выглядело также, как будто Chrome учитывал время, необходимое для перекраски в setTimeout
вызов (таким образом, между вызовами была разница в 504 мс, если изображение необходимо перекрасить). К сожалению, я не смог проанализировать и построить результаты для многих испытаний в SpeedTracer, потому что он только записывает на консоль. Я не уверен, отражает ли расхождение между SpeedTracer и MozAfterPaint различия в двух браузерах или что-то, чего не хватает в моем использовании MozAfterPaint (я вполне уверен, что правильно интерпретировал вывод SpeedTracer).
Вопросы
Я хотел бы знать
- Как я могу измерить время, когда оно фактически было видно на компьютере пользователя, или, по крайней мере, получить сопоставимые значения для набора различных браузеров на разных компьютерах для тестирования (Chrome, Firefox, Safari)?
- Могу ли я компенсировать время рендеринга и рисования, чтобы получить фактическую видимость 500 мс? Если бы мне пришлось полагаться на универсальное смещение, это было бы хуже, но все же лучше, чем показывать изображения в течение столь короткого промежутка времени, чтобы пользователи не видели их сознательно на несколько медленных компьютерах.
- Мы используем
setTimeout
, Я знаю оrequestAnimationFrame
но не похоже, что мы могли бы получить какие-либо выгоды от его использования:
Предполагается, что исследование будет сосредоточено на всей продолжительности исследования, и более важно, чтобы мы получили отображение +/-500 мс, чем определенное количество кадров в секунду. Правильно ли мое понимание?
Очевидно, что Javascript не идеален для этого, но он наименее вреден для наших целей (исследование должно выполняться в режиме онлайн на собственных компьютерах пользователей, прося их установить что-то, что может отпугнуть, Java не включена в браузеры Mac OS X). больше).
На данный момент мы разрешаем только текущие версии Safari, Chrome, Firefox и, возможно, MSIE (функция обнаружения для performance.now и полноэкранного API, я еще не проверял, как работает MSIE).
2 ответа
Поскольку я еще не получил больше ответов, но многому научился, редактируя этот вопрос, я публикую свой прогресс в качестве ответа. Как вы увидите, он все еще не оптимален, и я с радостью присужду награду любому, кто его улучшит.
Статистика
- В самой левой панели вы видите распределение, которое заставило меня усомниться в оценках времени, которые я получал.
- Средняя панель показывает, чего я добился после кэширования селекторов, переупорядочивания некоторых вызовов, использования еще нескольких цепочек, минимизации повторных обращений с помощью
visibility
и абсолютное позиционирование вместоdisplay
, - Крайняя правая панель показывает, что я получил после использования адаптированной функции Джо Ламберта с использованием requestAnimationFrame. Я сделал это после прочтения поста блога о том, что rAF теперь имеет точность до миллисекунды. Я думал, что это только поможет мне сгладить анимацию, но, очевидно, это также поможет улучшить фактическую длительность отображения.
Результаты
На последней панели среднее значение для времени "отрисовки к краске" составляет ~500 мс, среднее значение для времени выполнения в линейном режиме рассеивается реалистично (имеет смысл, потому что я использую ту же метку времени для завершения внутреннего цикла ниже) и коррелирует с "рисовать -покрасить "сроки".
Различия в продолжительности еще немного, и я бы хотел их уменьшить, но это определенно прогресс. Мне придется протестировать его на некоторых более медленных и некоторых компьютерах с Windows, чтобы увидеть, действительно ли я доволен этим, изначально я надеялся получить все отклонения ниже 10 мс.
Я мог бы также собрать гораздо больше данных, если бы сделал тестовый набор, который не требует взаимодействия с пользователем, но я хотел сделать это в нашем реальном приложении, чтобы получить реалистичные оценки.
window.requestTimeout
используя window.requestAnimationFrame
window.requestTimeout = function(fn, delay) {
var start = performance.now(),
handle = new Object();
function loop(){
var current = performance.now(),
delta = current - start;
delta >= delay ? fn.call() : handle.value = window.requestAnimationFrame(loop);
};
handle.value = window.requestAnimationFrame(loop);
return handle;
};
Редактировать:
Вы пытались получить начальные миллисекунды, и после того, как событие запущено, вычислите разницу? вместо setTimeout. что-то вроде:
var startDate = new Date();
var startMilliseconds = startDate.getTime();
// when the event is fired :
(...), function() {
console.log(new Date().getTime() - startMilliseconds);
});
по возможности старайтесь избегать использования jQuery. простой JS даст вам лучшее время отклика и лучшую общую производительность