@@ -12,7 +12,7 @@ | |||
# http://sam.zoy.org/wtfpl/COPYING for more details. | |||
# | |||
# The latest version of this script can be found at the following place: | |||
# http://sam.zoy.org/autotools/ | |||
# http://caca.zoy.org/wiki/build | |||
# Die if an error occurs | |||
set -e | |||
@@ -45,6 +45,7 @@ libcaca_la_SOURCES = \ | |||
graphics.c \ | |||
event.c \ | |||
time.c \ | |||
prof.c \ | |||
$(codec_source) \ | |||
$(driver_source) \ | |||
$(NULL) | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* libcaca Colour ASCII-Art library | |||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org> | |||
* Copyright (c) 2006-2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
@@ -327,6 +327,12 @@ static int caca_install_driver(caca_display_t *dp, char const *driver) | |||
dp->timer.last_sec = 0; | |||
dp->timer.last_usec = 0; | |||
#if defined PROF | |||
_caca_init_stat(&dp->display_stat, "dp[%p] disp_sys time", dp); | |||
_caca_init_stat(&dp->wait_stat, "dp[%p] disp_wait time", dp); | |||
_caca_init_stat(&dp->ev_sys_stat, "dp[%p] ev_sys time", dp); | |||
_caca_init_stat(&dp->ev_wait_stat, "dp[%p] ev_wait time", dp); | |||
#endif | |||
dp->lastticks = 0; | |||
/* Mouse position */ | |||
@@ -347,6 +353,12 @@ static int caca_uninstall_driver(caca_display_t *dp) | |||
if(dp->plugin) | |||
dlclose(dp->plugin); | |||
#endif | |||
#if defined PROF | |||
_caca_fini_stat(&dp->display_stat); | |||
_caca_fini_stat(&dp->wait_stat); | |||
_caca_fini_stat(&dp->ev_wait_stat); | |||
_caca_fini_stat(&dp->ev_sys_stat); | |||
#endif | |||
return 0; | |||
} | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* libcaca Colour ASCII-Art library | |||
* Copyright (c) 2002-2006 Sam Hocevar <sam@hocevar.net> | |||
* Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
@@ -24,6 +24,7 @@ typedef struct caca_privevent caca_privevent_t; | |||
typedef struct caca_figfont caca_figfont_t; | |||
#if !defined(_DOXYGEN_SKIP_ME) | |||
# define STAT_VALUES 20 | |||
# define EVENTBUF_LEN 10 | |||
# define MAX_DIRTY_COUNT 8 | |||
#endif | |||
@@ -144,6 +145,13 @@ struct caca_timer | |||
int last_sec, last_usec; | |||
}; | |||
/* Statistic structure for profiling */ | |||
struct caca_stat | |||
{ | |||
char *name; | |||
int imean, itable[STAT_VALUES]; | |||
}; | |||
/* Private event structure */ | |||
struct caca_privevent | |||
{ | |||
@@ -204,6 +212,10 @@ struct caca_display | |||
/* Framerate handling */ | |||
int delay, rendertime; | |||
caca_timer_t timer; | |||
#if defined PROF | |||
struct caca_stat display_stat, wait_stat; | |||
struct caca_stat ev_sys_stat, ev_wait_stat; | |||
#endif | |||
int lastticks; | |||
struct events | |||
@@ -249,4 +261,11 @@ extern int _pop_event(caca_display_t *, caca_privevent_t *); | |||
/* Internal window functions */ | |||
extern void _caca_set_term_title(char const *); | |||
/* Profiling functions */ | |||
#if defined PROF | |||
extern void _caca_dump_stats(void); | |||
extern void _caca_init_stat(struct caca_stat *, char const *, ...); | |||
extern void _caca_fini_stat(struct caca_stat *); | |||
#endif | |||
#endif /* __CACA_INTERNALS_H__ */ |
@@ -20,11 +20,25 @@ | |||
#if defined PROF && !defined __KERNEL__ | |||
# define PROFILING_VARS | |||
# define STAT_IADD(s, n) \ | |||
do \ | |||
{ \ | |||
struct caca_stat *ss = s; \ | |||
int ii, nn = n; \ | |||
for (ii = STAT_VALUES - 1; ii > 0; ii--) \ | |||
ss->itable[ii] = ss->itable[ii - 1]; \ | |||
ss->itable[0] = nn; \ | |||
ss->imean = ((int64_t)ss->imean * 15 + nn) / 16; \ | |||
} \ | |||
while(0) | |||
# define START_PROF(obj, fn) | |||
# define STOP_PROF(obj, fn) | |||
#else | |||
# define PROFILING_VARS | |||
# define STAT_IADD(s) do { } while(0) | |||
# define START_PROF(obj, fn) do { } while(0) | |||
# define STOP_PROF(obj, fn) do { } while(0) | |||
#endif | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* libcaca Colour ASCII-Art library | |||
* Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org> | |||
* Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
@@ -67,24 +67,38 @@ int caca_get_event(caca_display_t *dp, int event_mask, | |||
{ | |||
caca_privevent_t privevent; | |||
caca_timer_t timer = {0, 0}; | |||
int usec = 0; | |||
#if defined PROF | |||
caca_timer_t proftimer = {0, 0}; | |||
int profsys = 0, profwait = 0; | |||
#endif | |||
int ret = 0, usec = 0; | |||
#if defined PROF | |||
_caca_getticks(&proftimer); | |||
#endif | |||
if(!event_mask) | |||
return 0; | |||
goto end; | |||
if(timeout > 0) | |||
_caca_getticks(&timer); | |||
for( ; ; ) | |||
{ | |||
int ret = _get_next_event(dp, &privevent); | |||
#if defined PROF | |||
profwait += _caca_getticks(&proftimer); | |||
#endif | |||
ret = _get_next_event(dp, &privevent); | |||
#if defined PROF | |||
profsys += _caca_getticks(&proftimer); | |||
#endif | |||
/* If we got the event we wanted, return */ | |||
if(privevent.type & event_mask) | |||
{ | |||
if(ev) | |||
memcpy(ev, &privevent, sizeof(privevent)); | |||
return ret; | |||
goto end; | |||
} | |||
/* If there is no timeout, sleep and try again. */ | |||
@@ -100,18 +114,25 @@ int caca_get_event(caca_display_t *dp, int event_mask, | |||
privevent.type = CACA_EVENT_NONE; | |||
if(ev) | |||
memcpy(ev, &privevent, sizeof(privevent)); | |||
return 0; | |||
ret = 0; | |||
goto end; | |||
} | |||
/* Otherwise sleep a bit. Our granularity is far too high for values | |||
* below 10000 microseconds so we cheat a bit. */ | |||
if(usec > 10000) | |||
_caca_sleep(10000); | |||
else | |||
_caca_sleep(1000); | |||
_caca_sleep(usec > 10000 ? 10000 : 1000); | |||
usec += _caca_getticks(&timer); | |||
} | |||
end: | |||
#if defined PROF | |||
profwait += _caca_getticks(&proftimer); | |||
STAT_IADD(&dp->ev_sys_stat, profsys); | |||
STAT_IADD(&dp->ev_wait_stat, profwait); | |||
#endif | |||
return ret; | |||
} | |||
/** \brief Return the X mouse coordinate. | |||
@@ -147,12 +147,21 @@ int caca_get_display_time(caca_display_t const *dp) | |||
*/ | |||
int caca_refresh_display(caca_display_t *dp) | |||
{ | |||
#if defined PROF | |||
caca_timer_t proftimer = { 0, 0 }; | |||
#endif | |||
#if !defined(_DOXYGEN_SKIP_ME) | |||
#define IDLE_USEC 5000 | |||
# define IDLE_USEC 5000 | |||
#endif | |||
int ticks = dp->lastticks + _caca_getticks(&dp->timer); | |||
#if defined PROF | |||
_caca_getticks(&proftimer); | |||
#endif | |||
dp->drv.display(dp); | |||
#if defined PROF | |||
STAT_IADD(&dp->display_stat, _caca_getticks(&proftimer)); | |||
#endif | |||
/* Invalidate the dirty rectangle */ | |||
caca_clear_dirty_rect_list(dp->cv); | |||
@@ -164,6 +173,9 @@ int caca_refresh_display(caca_display_t *dp) | |||
_caca_handle_resize(dp); | |||
} | |||
#if defined PROF | |||
_caca_getticks(&proftimer); | |||
#endif | |||
/* Wait until dp->delay + time of last call */ | |||
ticks += _caca_getticks(&dp->timer); | |||
for(ticks += _caca_getticks(&dp->timer); | |||
@@ -172,6 +184,9 @@ int caca_refresh_display(caca_display_t *dp) | |||
{ | |||
_caca_sleep(IDLE_USEC); | |||
} | |||
#if defined PROF | |||
STAT_IADD(&dp->wait_stat, _caca_getticks(&proftimer)); | |||
#endif | |||
/* Update the render time */ | |||
dp->rendertime = ticks; | |||
@@ -182,6 +197,10 @@ int caca_refresh_display(caca_display_t *dp) | |||
if(dp->lastticks > (int)dp->delay) | |||
dp->lastticks = 0; | |||
#if defined PROF | |||
_caca_dump_stats(); | |||
#endif | |||
return 0; | |||
} | |||
@@ -484,6 +484,10 @@ | |||
RelativePath="line.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath="prof.c" | |||
> | |||
</File> | |||
<File | |||
RelativePath="string.c" | |||
> | |||
@@ -0,0 +1,106 @@ | |||
/* | |||
* libcaca Colour ASCII-Art library | |||
* Copyright (c) 2009 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | |||
* | |||
* $Id$ | |||
* | |||
* This library is free software. It comes without any warranty, to | |||
* the extent permitted by applicable law. You can redistribute it | |||
* and/or modify it under the terms of the Do What The Fuck You Want | |||
* To Public License, Version 2, as published by Sam Hocevar. See | |||
* http://sam.zoy.org/wtfpl/COPYING for more details. | |||
*/ | |||
/* | |||
* This file contains profiling functions. They are not supposed to be | |||
* built with release versions. | |||
*/ | |||
#include "config.h" | |||
#if !defined(__KERNEL__) | |||
# include <stdio.h> | |||
# include <stdarg.h> | |||
# include <stdlib.h> | |||
#endif | |||
#include "caca.h" | |||
#include "caca_internals.h" | |||
#if defined PROF | |||
static struct caca_stat **stats = NULL; | |||
static int nstats = 0; | |||
void _caca_dump_stats(void) | |||
{ | |||
int i, j; | |||
fprintf(stderr, "** libcaca profiling stats **\n"); | |||
for (i = 0; i < nstats; i++) | |||
{ | |||
int64_t total = 0; | |||
for (j = 0; j < STAT_VALUES; j++) | |||
total += stats[i]->itable[j]; | |||
fprintf(stderr, " %s: last %i mean %i sliding mean %i\n", | |||
stats[i]->name, stats[i]->itable[0], | |||
(int)((total + STAT_VALUES / 2) / STAT_VALUES), | |||
stats[i]->imean); | |||
/*fprintf(stderr, "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i\n", | |||
stats[i]->itable[0], stats[i]->itable[1], stats[i]->itable[2], | |||
stats[i]->itable[3], stats[i]->itable[4], stats[i]->itable[5], | |||
stats[i]->itable[6], stats[i]->itable[7], stats[i]->itable[8], | |||
stats[i]->itable[9], stats[i]->itable[10], stats[i]->itable[11], | |||
stats[i]->itable[12], stats[i]->itable[13], stats[i]->itable[14], | |||
stats[i]->itable[15], stats[i]->itable[16], stats[i]->itable[17], | |||
stats[i]->itable[18], stats[i]->itable[19]);*/ | |||
} | |||
fprintf(stderr, "** %i counters dumped **\n", nstats); | |||
} | |||
void _caca_init_stat(struct caca_stat *s, const char *format, ...) | |||
{ | |||
int i; | |||
s->name = malloc(128 * sizeof(char)); | |||
va_list args; | |||
va_start(args, format); | |||
vsnprintf(s->name, 128, format, args); | |||
s->name[127] = '\0'; | |||
va_end(args); | |||
nstats++; | |||
stats = realloc(stats, nstats * sizeof(struct caca_stat *)); | |||
stats[nstats - 1] = s; | |||
for (i = 0; i < STAT_VALUES; i++) | |||
s->itable[i] = 0; | |||
s->imean = 0; | |||
} | |||
void _caca_fini_stat(struct caca_stat *s) | |||
{ | |||
int i, j; | |||
for (i = 0; i < nstats; i++) | |||
{ | |||
if (stats[i] == s) | |||
{ | |||
free(stats[i]->name); | |||
for (j = i + 1; j < nstats; j++) | |||
stats[j - 1] = stats[j]; | |||
nstats--; | |||
stats = realloc(stats, nstats * sizeof(struct caca_stats *)); | |||
return; | |||
} | |||
} | |||
} | |||
#endif | |||
@@ -90,8 +90,8 @@ AC_ARG_ENABLE(imlib2, | |||
dnl conditional builds | |||
AC_ARG_ENABLE(debug, | |||
[ --enable-debug build debug versions of the library (default no)]) | |||
AC_ARG_ENABLE(prof, | |||
[ --enable-prof activate built-in profiling (default no)]) | |||
AC_ARG_ENABLE(profiling, | |||
[ --enable-profiling activate built-in profiling (default no)]) | |||
AC_ARG_ENABLE(plugins, | |||
[ --enable-plugins make X11 and GL drivers plugins (default disabled)]) | |||
AC_ARG_ENABLE(doc, | |||
@@ -321,7 +321,7 @@ if test "${enable_debug}" = "yes"; then | |||
AC_DEFINE(DEBUG, 1, Define to 1 to activate debug) | |||
fi | |||
if test "${enable_prof}" = "yes"; then | |||
if test "${enable_profiling}" = "yes"; then | |||
AC_DEFINE(PROF, 1, Define to 1 to activate profiling) | |||
fi | |||