Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > JavaScript, Ajax
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.03.2014, 09:57   #1
Linel
Форумчанин
 
Аватар для Linel
 
Регистрация: 21.02.2009
Сообщений: 372
По умолчанию Один таймер vs много таймеров - дайте совет

Здраствуйте.

Встала такая задача:

Есть большой массив объектов, которые следует отобразить на canvas. Объекты постоянно движутся с разной скоростью.

Отображать буду с помощью requestAnimationFrame(), вызывая метод draw(), который будет брать текущие координаты объекта и по каким-то правилам его рисовать в данных координатах.

Возникла задача менять координаты всех объектов с наименьшими проблемами с перфомансом.

Первая идея была такая:

Ну, окей есть у нас объект. Он движется. Запускаем таймер, который раз в n миллисикунд меняет кординаты

Код HTML:
setInterval(move, n)
где вункция move() что-то делает с координатами раз в n миллисекунд.

Проблема в том, что объектов может быть много, например, 200.
И изменение координат некоторых объектов должно происходить быстро. В итоге получаю 200 таймеров, которые раз, с кажем, 20 миллисекунд производят расчеты.

Возникла другая идея.
Сделать один глобальный таймер, который обнавляется, скажем, раз в 5 миллисекунд. И у каждого объекта раз в эти 5 миллисекунд высчитывать новые координаты на основе скорости этого объекта.

Оправдывает ли себя такой подход или же больщой разницы с перформансом не будет?
No name. Just Linel.

Последний раз редактировалось Linel; 30.03.2014 в 09:59.
Linel вне форума Ответить с цитированием
Старый 30.03.2014, 11:12   #2
Naive
Раздолбайских Дел
Старожил
 
Аватар для Naive
 
Регистрация: 22.05.2009
Сообщений: 3,828
По умолчанию

Вот начал с верной мысли, а дальше что-то намудрил)
requestAnimationFrame() это и есть таймер, зачем тебе другие?
Тебе лишь нужно будет отслеживать тайм-штамп и в зависимости от задержки отображения высчитывать все нужные координаты для каждого отдельно взятого движущегося объекта. Обычная инкапсуляция.
Однако обычный холст может тормозить со всей этой радостью. Возможно стоит глянуть в сторону webGL.
Alar, верни репу!
Naive вне форума Ответить с цитированием
Старый 30.03.2014, 11:39   #3
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,547
По умолчанию

Цитата:
Сообщение от Linel Посмотреть сообщение
Сделать один глобальный таймер, который обнавляется, скажем, раз в 5 миллисекунд.
Очень сомневаюсь, что такой интервал сработает.
Arigato вне форума Ответить с цитированием
Старый 31.03.2014, 00:36   #4
Naive
Раздолбайских Дел
Старожил
 
Аватар для Naive
 
Регистрация: 22.05.2009
Сообщений: 3,828
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
Очень сомневаюсь, что такой интервал сработает.
тока проверял, минималка на моей машине в хроме получилась 2мс...именно тауймаут, однако при этом страница ничем загружена не была...
Alar, верни репу!
Naive вне форума Ответить с цитированием
Старый 31.03.2014, 00:50   #5
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,547
По умолчанию

То есть если в такой таймер поставить команду tick++, то через 10 секунд tick==5000?
Arigato вне форума Ответить с цитированием
Старый 31.03.2014, 05:04   #6
Naive
Раздолбайских Дел
Старожил
 
Аватар для Naive
 
Регистрация: 22.05.2009
Сообщений: 3,828
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
То есть если в такой таймер поставить команду tick++, то через 10 секунд tick==5000?
Нет, точно нет. JS — асинхронный язык, все, что выкладывается на "отсрочку", т.е. таймер, или интервал, или фреймсет; выкладывается в асинхронную очередь.
То есть если ты запустил таймер, скажем с алертом таймштампа на 5мс, а после него закинул вычисление факториала от 1000, то асинхронный код подождет своей очереди.
Бонус:
Код:
var a = function() {requestAnimationFrame(function(){console.log(Date.now()); a()});} a();
*выводит таймштамп в консоль сразу после отрисовки страницы браузером.
Попробуй этот код на простой странице, типа этого форума и на тяжкой, типа примеров webGL.
Alar, верни репу!
Naive вне форума Ответить с цитированием
Старый 31.03.2014, 05:17   #7
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,547
По умолчанию

Я спрашивал не про загруженность, а на пустой странице даст он тебе tick==5000 или нет? И если нет, то на сколько он будет меньше.
Arigato вне форума Ответить с цитированием
Старый 31.03.2014, 08:00   #8
Fenex
Форумчанин
 
Аватар для Fenex
 
Регистрация: 15.02.2012
Сообщений: 821
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
Я спрашивал не про загруженность, а на пустой странице даст он тебе tick==5000 или нет? И если нет, то на сколько он будет меньше.
Сильно зависит от машины же. Более того, чем тяжелее будет функция (в плане вычислений), тем выше будет разброс времени выполнения функции даже на одной и той же странице.

У себя проверил код - давало 495 (для 2 сек) и около 2470 (для 10 сек) на странице ya.ru.

Код:
var count = 0;
var timer = setInterval(function() {
    count++;
}, 2);
setTimeout(function() {
    clearInterval(timer);
    console.log(count);
}, 2000);
Время 2 мс - очень маленькое, смысла в таких задержках нет никакого. Каждый раз таймаут складывает в очередь выполнения код, чтобы этих копий не накапливалось и они не вызывались сразу друг за другом партиями, был создан механизм защиты от вызова одной и той же функции без таймаута (если предыдущая копия функции ещё не обработана, она уничтожается из очереди). В данном случае скорее всего так и есть - javascript только тем и занимался, что добавлял и убирал из очереди выполнения функцию (утрирую, конечно же).
^-.-^ My GitHub

Последний раз редактировалось Fenex; 31.03.2014 в 08:10.
Fenex вне форума Ответить с цитированием
Старый 31.03.2014, 11:40   #9
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,547
По умолчанию

Вот такой код, тестирую на пустой странице:
Код:
function start(){
	var tick=0;
	var startTime=Date.now();
	var timer=setInterval(function(){tick++}, 2);
	setTimeout(function(){
		var waiting=Date.now()-startTime;
		clearInterval(timer);
		alert(waiting+' - '+tick+' - '+Math.ceil(waiting/tick));
	}, 2000);
}
Результаты для разных браузеров (реальное время до остановки таймера - количество тиков - реальное значение интервала):
Firefox: 2002 - 392 - 6
Opera: 2000 - 409 - 5
Chrome: 2001 - 412 - 5
Safari: 2002 - 410 - 5
Maxthon: 2001 - 416 - 5
Нигде интервал 2 не получается.

Последний раз редактировалось Arigato; 31.03.2014 в 12:05.
Arigato вне форума Ответить с цитированием
Старый 31.03.2014, 17:43   #10
Naive
Раздолбайских Дел
Старожил
 
Аватар для Naive
 
Регистрация: 22.05.2009
Сообщений: 3,828
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
Нигде интервал 2 не получается.
У меня мб просто комп мощнее)

Цитата:
Maxthon: 2001 - 416 - 5
А вот это уже странно, он же на движке Тридент? у них вроде была минималка на задержку 20мс...
Какая версия?
Alar, верни репу!
Naive вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Дайте совет digital-stream HTML и CSS 3 09.07.2012 11:59
дайте совет! Cassius Общие вопросы Delphi 6 10.12.2011 02:43
Дайте совет Михаил70 Свободное общение 17 14.09.2009 20:52
Дайте совет! Arch100 Помощь студентам 2 11.10.2008 01:40