Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Possible bug with text outputs

This thread is locked; no one can reply to it. rss feed Print
Possible bug with text outputs
Lucas Adami
Member #8,528
April 2007

Hello.

I'm developing my game with Allegro 4.9.8.
While programming, I realized that sometimes my program uses too much CPU processing.
Then, trying to find where it was the cause, I discovered that al_font_textout() was the answer. I made a test program to prove this, and I was right:

- I load a ttf font
- Use a color
- In a loop (with sleep()!) I use that function

When I remove the line of al_font_textout(), my CPU proccessment goes 2~ in max. With al_font_textout(), it reachs 30~35.

I attached my program files so you can test it too.

Does this only happens with me?
If not, isnt it a bug?
Is it a know bug that was solved on 4.9.9?

Thank you ;)

count
Member #5,401
January 2005

I haven't tested the executable but I looked at the code. What I noticed was that you don't use a proper timing method.

You should have a look at this awesome allegro 5 tutorials and especially tutorial 3 which will explain how to use proper timing with allegro 5.

Maybe this will already solve your problem because the redrawing of your screen will only been done when necessary (so it will use less cpu).

Lucas Adami
Member #8,528
April 2007

Christopher, I dont use the sleep as it is on the test code on my project ;)

But, it has nothing to do with the CPU usage. If I change the text output to a bmp drawing ( I tested with a bmp of 1MB! -> al_draw_bitmap() ), the CPU usage does not pass 3~.

Todd Cope
Member #998
November 2000
avatar

Text output seems slow to me, too, but I hadn't done any testing to verify it. In one of my games the CPU usage jumps up when I display around 5 lines of text on the screen. My game is using bitmap fonts.

Peter Wang
Member #23
April 2000

I think there is some inefficiency there, but it would be nice if you guys tested with 4.9.9 or later, and preferably with the profiling builds. I didn't notice anything particularly wrong with Lucas' example on my machine (OpenGL on Linux).

Milan Mimica
Member #3,877
September 2003
avatar

Most functions you used in that example don't exist in SVN version.

Neil Walker
Member #210
April 2000
avatar

You should have a look at this awesome allegro 5 tutorials

Looking at the code I see this:

ALLEGRO_TIMER *timer = al_install_timer(1.0/refresh_rate);
  al_start_timer(timer);
  ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue();
  al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_get_keyboard());
  al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)timer);

Assuming this is the typical usage for timers, would it not be good to add an optional parameter to al_install_timer to flag whether to start it up on creation, thereby removing the need to temporary variables, additional function calls, etc. and making initialisation a quick and simple process and done in the same way (as per get mouse, get joystick, etc), e.g. the above code be reduced to:

  ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue();
  al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_get_keyboard());
  al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_install_timer(1.0/refresh_rate,true));

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Elias
Member #358
May 2000

You should have a look at this awesome allegro 5 tutorials

Some of the examples coming with A5 also show a somewhat more robust way to handle updates by having optional frame skipping. If you redraw at each timer tick as in the tutorial you will run into problems on slow computers.

Assuming this is the typical usage for timers, would it not be good to add an optional parameter to al_install_timer to flag whether to start it up on creation

Sounds reasonable to me. Or maybe reduce it all even further to:

queue = al_init_simple(640, 480, 1.0 / 60);

with:

ALLEGRO_EVENT_QUEUE *al_init_simple(int width, int height, float frequency)
{
    ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue();
    al_create_display(width, height);
    al_install_keyboard();
    al_install_mouse();
    al_register_event_source(queue, al_get_keyboard());
    al_register_event_source(queue, al_get_mouse());
    al_register_event_source(queue, al_get_current_display());
    ALLEGRO_TIMER *timer = al_install_timer(1.0 / frequency);
    al_register_event_source(queue, timer);
    al_start_timer(timer);
    return queue;
}

I'm sure this would cover the usage in most A5 programs.

--
"Either help out or stop whining" - Evert

Milan Mimica
Member #3,877
September 2003
avatar

Or start_timer() could return ALLEGRO_TIMER* passed to it :)

Evert
Member #794
November 2000
avatar

You'll want to grab the timer handler to be able to stop/pause the timer (for instance).

Peter Wang
Member #23
April 2000

How do you know how long the stuff in between starting the timer and the start of your main loop will take? I presume you'd want to minimise that. I'd rather stick with explicitly starting the timer.

Neil Walker
Member #210
April 2000
avatar

How do you know how long the stuff in between starting the timer and the start of your main loop will take? I presume you'd want to minimise that. I'd rather stick with explicitly starting the timer.

That's why I offered a boolean start up flag, you can have two values: true and false ;)

I just see having to assign and not use objects as a waste, when function chaining is not available.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

SiegeLord
Member #7,827
October 2006
avatar

Elias said:

Some of the examples coming with A5 also show a somewhat more robust way to handle updates by having optional frame skipping. If you redraw at each timer tick as in the tutorial you will run into problems on slow computers.

Which ones? The main loops should be standardized for the examples at some point. As is there are various combinations of rest(1) loops, timer loops, delta time loops etc etc.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Elias
Member #358
May 2000

Yeah, I meant what most use, like e.g. ex_bitmap or ex_blit. I also don't see why you would use variable frame length or redraw depending on whether enough time to the last update has passed.

--
"Either help out or stop whining" - Evert

SiegeLord
Member #7,827
October 2006
avatar

Elias said:

Yeah, I meant what most use, like e.g. ex_bitmap or ex_blit.

Most, but not all. IMHO they should all use it the system in ex_bitmap, or as outlined here. It is very flexible, and I like it.

I don't suppose there is a desire to introduce an al_game_loop(void (*logic)(), void (*input)(), void (*draw)(), ALLEGRO_EVENT_QUEUE *queue) function to the library?

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

count
Member #5,401
January 2005

I probably don't get this completely.
Would you care to elaborate on this a little bit?

Elias said:

If you redraw at each timer tick as in the tutorial you will run into problems on slow computers.

Here is the problem I have. I don't see the real difference between the two solutions.
The tutorial I linked to does this:

#SelectExpand
1 case ALLEGRO_EVENT_TIMER: 2 { 3 // Determine the change in time between frames, in seconds 4 time = al_current_time(); 5 dt = time-old_time; 6 7 // If the computer lags for some reason, don't penalize the player 8 // Cap dt at 0.5 seconds 9 if(dt > 0.25) dt = 0.25; 10 11 // UPDATE 12
13 if(time - event.timer.timestamp <= 1.0/refresh_rate) {
14 // DRAWING 15 } 16 17 // Make the time at this frame the old time, for the next frame 18 old_time = time; 19 break; 20 }

So because of line 14 it doesn't draw on each tick. Or am I wrong?
Steve says on his site:

Each event is timestamped with the number of seconds since the program began. This conditional is checking that the tick event happened within the past frame. If the timer tick is from more than a frame ago, we disregard it and will not perform any drawing operatings.

The difference I see in this example is, that drawing is only done, when the queue is empty. Why is this a good thing?

Hope I don't bother you too much with this questions. :(

Elias
Member #358
May 2000

The al_event_queue_is_empty(queue) is only for the case when the game runs really slow (1 FPS or so, because neither DirectX nor OpenGL acceleration is available). Then the events queue would fill up and you'd have to wait a long time for something like pressing the Esc key or close button to register. The timestamp comparison might have the same effect though - we should make one of the examples use it to know.

--
"Either help out or stop whining" - Evert

SiegeLord
Member #7,827
October 2006
avatar

I don't see the real difference between the two solutions.

The wiki's method is fixed time step, and the tutorial's method is delta-time for one. Moreover, the tutorial's method doesn't really make sense to me, given that it is a delta time method... why would you call the update multiple times per frame? If you convert it to a fixed time method, then it should behave the same as the wiki's method, only be more complicated.

Elias said:

The al_event_queue_is_empty(queue) is only for the case when the game runs really slow (1 FPS or so, because neither DirectX nor OpenGL acceleration is available)

No, it isn't. It's for when the game runs at any speed lower than the set FPS. Whenever the drawing operation takes more than 1/FPS time, there are multiple timer ticks that happen during it. al_event_queue_is_empty(queue) makes sure we take care of all of them before drawing, the standard fixed time stepping tactic.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Elias
Member #358
May 2000

Ahh, makes sense. For me, the only time that could happen is when using software routines (as otherwise drawing is nearly instant and there would never be multiple timer ticks if they are as slow as 60 per second). But, I interpreted it completely wrong... have yet to get completely accustomed to the events-based mindset after using the A4 way for so long :)

--
"Either help out or stop whining" - Evert

count
Member #5,401
January 2005

SiegeLord said:

Whenever the drawing operation takes more than 1/FPS time, there are multiple timer ticks that happen during it.

if(time - event.timer.timestamp <= 1.0/refresh_rate)

SiegeLord said:

If you convert it to a fixed time method, then it should behave the same as the wiki's method, only be more complicated.

Given this informations I guess that this is not true?

Elias said:

Some of the examples coming with A5 also show a somewhat more robust way to handle updates by having optional frame skipping. If you redraw at each timer tick as in the tutorial you will run into problems on slow computers.

Otherwise I still don't see what is the problem with the code in the tutorial.
(I don't mean the delta time vs fixed time but that it may run into problems on slow computers)

brunooo
Member #8,346
February 2007
avatar

I have problems with it too. When I start drawing too many texts, the game starts to lose too much performance! I also noticed that on slower computers, my games are not running as good as 4.2.2 runned :-/

I am using the software.skoobalon.com tutorials :-X

Elias
Member #358
May 2000

A5 uses Direct3D/OpenGL for all drawing operations and so the performance should only depend on your drivers (and usually it is a lot faster than A4 for everything you do).

However if for some reason you are using the software emulation of A5 it will be slow because unlike A4 alpha blending is on by default. You could try turning blending off and compare then, it will probably run at the same speed.

--
"Either help out or stop whining" - Evert

brunooo
Member #8,346
February 2007
avatar

I will try that! But text printing still bothers me :/

Milan Mimica
Member #3,877
September 2003
avatar

Text output is slow. ex_ttf runs at 80FPS here, and all it does it displaying dozen of lines on the screen.

brunooo
Member #8,346
February 2007
avatar

Yes, the ex_ttf here runs at 85 fps, but it uses 99% of cpu and when I open the Task Manager to see how much cpu % it uses, it crashes. I need to open the task manager first and then run it. :-/

Go to: