PDA

Просмотр полной версии : Очень точный таймер


wvxvw
06.06.2008, 04:55
Вобщем... столкнулся с такой вот незадачей... нужен таймер, который бы работал на порядок точнее родного... Т.е. по тех характеристикам в течение 45 секунд должен тикать каждые 33 миллисекунды с погрешностью не более 6 миллисекунд (и при этом, желательно не сильно нагружать процессор)... Даже, не, скорее не так: нужно добиться, чтобы функция вызывалась точно по истечении 33 миллисекунд (само по себе выполнение функции примерно укладывается в это же время).
Что я уже попробовал:
- запускать таймер с минимальным интервалом. (эмпирическим путем выяснилось, что разницы между 1-6..8 миллисекунд практически нету. При вызове раз в 10 миллисекунд погрешность составляет примерно 6-15 миллисекунд (почти в 3 раза... млин =( ). Т.е. можно высчитывать дельту между ожидаемым временем тика и реальным, и немного постаравшись результаты примерно укладываются в +-6 мс, но тестится все в "тепличных условиях", боюсь, что на практике окажеться хуже...
- просто в цикле проверять текущее время, конечно, работает, но во время цикла все равно ничего не сделаешь %)

ЗЫ. сравнительные тесты сетИнтервала/сетТаймаута и Таймера - примерно одинаково, особой разницы не заметил.
ЗЫЫ. просто интересны варианты решения, мб есть что-нибудь, о чем не подумал.

ЗЫЫЫ. ессно, не нужно думать, что этим кто-то собирается пользоваться, но нужно добиться примерно похожих результатов...
package
{

/**
* ...
* @author wvxvw
*/
import flash.utils.getTimer;
import flash.utils.setTimeout;

public class PTimer
{

private static var _pi:int = 0;
private static var _s:int = 0;
private static var _b:Boolean = true;
private static var _d:int = 0;
private static var _t:PTimer;

public function PTimer()
{
_t = this;
}
public static function start(interval:int, d:int = 0):void
{
if (!_pi) _pi = interval;
_s = getTimer();
if (!_d) _d = _s;
var dt:int = _pi - (_s - _d) % _pi;
pulse(dt);
}
public static function stop():void
{
_b = false;
_pi = 0;
_d = 0;
}
private static function pulse(dt:int):void
{
if (!_b) return;
var i:int;
var t:int = dt;
for (i = 0; i >= 0; i++)
{
if (getTimer() - _s >= t) {
//trace('timer: ' + getTimer());
setTimeout(start, 1, t);
break;
}
}
}
}

}

silin
06.06.2008, 10:38
имхо гиблое дело, если речь о плеере/плагине
только в цикле отслеживать, но это работа на сам таймер
попробовал рядом запустить флешку, которая как раз только этим и занимается и по LocalConnection докладывает основной, но там десятки мс теряются влегкую, что сводит на нет эту затею..
других вариантов не вижу

aksios
06.06.2008, 15:58
Помоему, надо совсем другой подход применять - для создания таймера повышенной точности. Нужно привязываться к тактам, за которые выполняется оператор и вывод данных отдельно подготавливать.
В общем, флеш неоправдан.

wvxvw
06.06.2008, 17:01
silin:
угу, тоже думал, но фик там... =)

aksios:
ну это по определению должен быть флеш... было бы что-то другое, наверное, по другому бы и решал... тут проблема еще и такая, ну, предположим, я знаю, когда функция закончила работать, и до следующего вызова осталось около 10 миллисекунд, и, тут-то, млин незадача, как ее вызвать-то именно через 10 миллисекунд, а не через 5-15... заускать цикл так как в примере - хреновый вариант т.как параллельно с флешкой должно быть запущено еще одно приложение (обязательно), а когда флешка начинает считать цикл она (по крайней мере на моем компе) занимает 1 проц на 100% (у мну их 2 х 2,3)... а это как-то очень жирно для такой нехитрой операции как "ничего не делать" %)