[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
- To: Coordination of admins/developers of the game programming library Allegro <alleg-developers@xxxxxxxxxx>
- Subject: Re: [AD] Timer patch
- From: Elias Pschernig <elias@xxxxxxxxxx>
- Date: Mon, 04 Feb 2008 14:59:43 +0100
On Sun, 2008-02-03 at 03:45 -0800, Ryan Dickie wrote:
> I struggled a bit tonight but i got the new 2.6.24 kernel compiled
> with the tickless scheduling. It is damned accurate (no more periodic
> os interupt). Calling al_rest 1000 times for 1 ms sleeps gave the
> following results.
>
> 1000x 1ms delays
> Time Slept 1.065
> Cummulative error 0.064732
> Error per sleep 0.000065
>
> The error in the periodic timer. This is just the error of the timer
> thread itself. The event wakeup itself should add some error as well.
> I'm too tired to code that up just now ;)
> Error:-0.000012
> Percentage: 0.012000 (100 * -error / delay time )
>
> The error with the old ticking kernel is about 1.5ms (sometimes peaked
> as high as 2.5). This is now a factor of 10x more accurate than the
> windows ones which themselves are only 200us off.
>
I made a stupid test as well (attached). The max - min reading shows
around 15 us for most seconds here, which sounds good to me :) (2.6.24
here, but I think unlike al_rest this is not affected by the tickless
scheduler, so should be the same with 2.6.23)
--
Elias Pschernig <elias@xxxxxxxxxx>
/* An example demonstrating different blending modes.
*/
#include <allegro5/allegro5.h>
#include <allegro5/a5_font.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
/* A structure holding all variables of our example program. */
struct Example
{
A5FONT_FONT *myfont; /* Our font. */
ALLEGRO_EVENT_QUEUE *queue; /* Our events queue. */
double FPS; /* How often to update per second. */
int x[4];
bool first_tick;
double this_time, prev_time, accum_time;
double min_diff, max_diff, second_spread;
double second;
double timer_events;
} ex;
/* Print some text. */
static void print(int x, int y, char const *format, ...)
{
va_list list;
va_start(list, format);
char message[1024];
uvszprintf(message, sizeof message, format, list);
va_end(list);
ALLEGRO_COLOR color;
color = al_map_rgb(0, 0, 0);
al_set_blender(ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, color);
a5font_textout(ex.myfont, message, x, y);
}
/* Draw our example scene. */
static void draw(void)
{
int h = a5font_text_height(ex.myfont);
al_clear(al_map_rgb_f(1, 1, 1));
print(0, 0, "%.9f target for 50 Hz Timer", 0.02);
print(0, h, "%.9f now", ex.this_time - ex.prev_time);
print(0, 2 * h, "%.9f accum over one second",
ex.accum_time / ex.timer_events);
print(0, 3 * h, "%.9f min", ex.min_diff);
print(0, 4 * h, "%.9f max", ex.max_diff);
print(300, 3.5 * h, "%.9f (max - min)", ex.second_spread);
int y = 240, i;
for (i = 0; i < 4; i++)
al_draw_rectangle(ex.x[i], y + i * 60, ex.x[i] + (1 << i),
y + i * 60 + 60, al_map_rgb(1, 0, 0), ALLEGRO_FILLED);
}
/* Called a fixed amount of times per second. */
static void tick(void)
{
ex.this_time = al_current_time();
if (ex.first_tick)
ex.first_tick = false;
else {
if (ex.this_time - ex.second >= 1) {
ex.second = ex.this_time;
ex.accum_time = 0;
ex.timer_events = 0;
ex.second_spread = ex.max_diff - ex.min_diff;
ex.max_diff = 0;
ex.min_diff = 1;
}
double duration = ex.this_time - ex.prev_time;
if (duration < ex.min_diff) ex.min_diff = duration;
if (duration > ex.max_diff) ex.max_diff = duration;
ex.accum_time += duration;
ex.timer_events++;
}
draw();
al_flip_display();
int i;
for (i = 0; i < 4; i++) {
ex.x[i] += 1 << i;
ex.x[i] %= 640;
}
ex.prev_time = ex.this_time;
}
/* Run our test. */
static void run(void)
{
float x, y;
ALLEGRO_EVENT event;
while (1) {
al_wait_for_event(ex.queue, &event, ALLEGRO_WAIT_FOREVER);
switch (event.type) {
/* Was the X button on the window pressed? */
case ALLEGRO_EVENT_DISPLAY_CLOSE:
return;
/* Was a key pressed? */
case ALLEGRO_EVENT_KEY_DOWN:
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
return;
break;
/* Is it time for the next timer tick? */
case ALLEGRO_EVENT_TIMER:
tick();
break;
}
}
}
/* Initialize the example. */
static void init(void)
{
ex.FPS = 50;
ex.first_tick = true;
ex.myfont = a5font_load_font("font.tga", 0);
if (!ex.myfont) {
allegro_message("font.tga not found");
exit(1);
}
}
int main(void)
{
ALLEGRO_DISPLAY *display;
al_init();
al_install_keyboard();
al_install_mouse();
display = al_create_display(640, 480);
al_show_mouse_cursor();
init();
ALLEGRO_TIMER *timer = al_install_timer(1.000 / ex.FPS);
ex.queue = al_create_event_queue();
al_register_event_source(ex.queue, (void *)al_get_keyboard());
al_register_event_source(ex.queue, (void *)al_get_mouse());
al_register_event_source(ex.queue, (void *)display);
al_register_event_source(ex.queue, (void *)timer);
al_start_timer(timer);
run();
al_destroy_event_queue(ex.queue);
return 0;
}
END_OF_MAIN()