@@ -12,7 +12,7 @@ | |||||
# http://sam.zoy.org/wtfpl/COPYING for more details. | # http://sam.zoy.org/wtfpl/COPYING for more details. | ||||
# | # | ||||
# The latest version of this script can be found at the following place: | # 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 | # Die if an error occurs | ||||
set -e | set -e | ||||
@@ -45,6 +45,7 @@ libcaca_la_SOURCES = \ | |||||
graphics.c \ | graphics.c \ | ||||
event.c \ | event.c \ | ||||
time.c \ | time.c \ | ||||
prof.c \ | |||||
$(codec_source) \ | $(codec_source) \ | ||||
$(driver_source) \ | $(driver_source) \ | ||||
$(NULL) | $(NULL) | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* libcaca Colour ASCII-Art library | * 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 | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $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_sec = 0; | ||||
dp->timer.last_usec = 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; | dp->lastticks = 0; | ||||
/* Mouse position */ | /* Mouse position */ | ||||
@@ -347,6 +353,12 @@ static int caca_uninstall_driver(caca_display_t *dp) | |||||
if(dp->plugin) | if(dp->plugin) | ||||
dlclose(dp->plugin); | dlclose(dp->plugin); | ||||
#endif | #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; | return 0; | ||||
} | } | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* libcaca Colour ASCII-Art library | * 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 | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $Id$ | ||||
@@ -24,6 +24,7 @@ typedef struct caca_privevent caca_privevent_t; | |||||
typedef struct caca_figfont caca_figfont_t; | typedef struct caca_figfont caca_figfont_t; | ||||
#if !defined(_DOXYGEN_SKIP_ME) | #if !defined(_DOXYGEN_SKIP_ME) | ||||
# define STAT_VALUES 20 | |||||
# define EVENTBUF_LEN 10 | # define EVENTBUF_LEN 10 | ||||
# define MAX_DIRTY_COUNT 8 | # define MAX_DIRTY_COUNT 8 | ||||
#endif | #endif | ||||
@@ -144,6 +145,13 @@ struct caca_timer | |||||
int last_sec, last_usec; | int last_sec, last_usec; | ||||
}; | }; | ||||
/* Statistic structure for profiling */ | |||||
struct caca_stat | |||||
{ | |||||
char *name; | |||||
int imean, itable[STAT_VALUES]; | |||||
}; | |||||
/* Private event structure */ | /* Private event structure */ | ||||
struct caca_privevent | struct caca_privevent | ||||
{ | { | ||||
@@ -204,6 +212,10 @@ struct caca_display | |||||
/* Framerate handling */ | /* Framerate handling */ | ||||
int delay, rendertime; | int delay, rendertime; | ||||
caca_timer_t timer; | 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; | int lastticks; | ||||
struct events | struct events | ||||
@@ -249,4 +261,11 @@ extern int _pop_event(caca_display_t *, caca_privevent_t *); | |||||
/* Internal window functions */ | /* Internal window functions */ | ||||
extern void _caca_set_term_title(char const *); | 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__ */ | #endif /* __CACA_INTERNALS_H__ */ |
@@ -20,11 +20,25 @@ | |||||
#if defined PROF && !defined __KERNEL__ | #if defined PROF && !defined __KERNEL__ | ||||
# define PROFILING_VARS | # 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 START_PROF(obj, fn) | ||||
# define STOP_PROF(obj, fn) | # define STOP_PROF(obj, fn) | ||||
#else | #else | ||||
# define PROFILING_VARS | # define PROFILING_VARS | ||||
# define STAT_IADD(s) do { } while(0) | |||||
# define START_PROF(obj, fn) do { } while(0) | # define START_PROF(obj, fn) do { } while(0) | ||||
# define STOP_PROF(obj, fn) do { } while(0) | # define STOP_PROF(obj, fn) do { } while(0) | ||||
#endif | #endif | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* libcaca Colour ASCII-Art library | * 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 | * All Rights Reserved | ||||
* | * | ||||
* $Id$ | * $Id$ | ||||
@@ -67,24 +67,38 @@ int caca_get_event(caca_display_t *dp, int event_mask, | |||||
{ | { | ||||
caca_privevent_t privevent; | caca_privevent_t privevent; | ||||
caca_timer_t timer = {0, 0}; | 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) | if(!event_mask) | ||||
return 0; | |||||
goto end; | |||||
if(timeout > 0) | if(timeout > 0) | ||||
_caca_getticks(&timer); | _caca_getticks(&timer); | ||||
for( ; ; ) | 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 we got the event we wanted, return */ | ||||
if(privevent.type & event_mask) | if(privevent.type & event_mask) | ||||
{ | { | ||||
if(ev) | if(ev) | ||||
memcpy(ev, &privevent, sizeof(privevent)); | memcpy(ev, &privevent, sizeof(privevent)); | ||||
return ret; | |||||
goto end; | |||||
} | } | ||||
/* If there is no timeout, sleep and try again. */ | /* 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; | privevent.type = CACA_EVENT_NONE; | ||||
if(ev) | if(ev) | ||||
memcpy(ev, &privevent, sizeof(privevent)); | memcpy(ev, &privevent, sizeof(privevent)); | ||||
return 0; | |||||
ret = 0; | |||||
goto end; | |||||
} | } | ||||
/* Otherwise sleep a bit. Our granularity is far too high for values | /* Otherwise sleep a bit. Our granularity is far too high for values | ||||
* below 10000 microseconds so we cheat a bit. */ | * 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); | 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. | /** \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) | int caca_refresh_display(caca_display_t *dp) | ||||
{ | { | ||||
#if defined PROF | |||||
caca_timer_t proftimer = { 0, 0 }; | |||||
#endif | |||||
#if !defined(_DOXYGEN_SKIP_ME) | #if !defined(_DOXYGEN_SKIP_ME) | ||||
#define IDLE_USEC 5000 | |||||
# define IDLE_USEC 5000 | |||||
#endif | #endif | ||||
int ticks = dp->lastticks + _caca_getticks(&dp->timer); | int ticks = dp->lastticks + _caca_getticks(&dp->timer); | ||||
#if defined PROF | |||||
_caca_getticks(&proftimer); | |||||
#endif | |||||
dp->drv.display(dp); | dp->drv.display(dp); | ||||
#if defined PROF | |||||
STAT_IADD(&dp->display_stat, _caca_getticks(&proftimer)); | |||||
#endif | |||||
/* Invalidate the dirty rectangle */ | /* Invalidate the dirty rectangle */ | ||||
caca_clear_dirty_rect_list(dp->cv); | caca_clear_dirty_rect_list(dp->cv); | ||||
@@ -164,6 +173,9 @@ int caca_refresh_display(caca_display_t *dp) | |||||
_caca_handle_resize(dp); | _caca_handle_resize(dp); | ||||
} | } | ||||
#if defined PROF | |||||
_caca_getticks(&proftimer); | |||||
#endif | |||||
/* Wait until dp->delay + time of last call */ | /* Wait until dp->delay + time of last call */ | ||||
ticks += _caca_getticks(&dp->timer); | ticks += _caca_getticks(&dp->timer); | ||||
for(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); | _caca_sleep(IDLE_USEC); | ||||
} | } | ||||
#if defined PROF | |||||
STAT_IADD(&dp->wait_stat, _caca_getticks(&proftimer)); | |||||
#endif | |||||
/* Update the render time */ | /* Update the render time */ | ||||
dp->rendertime = ticks; | dp->rendertime = ticks; | ||||
@@ -182,6 +197,10 @@ int caca_refresh_display(caca_display_t *dp) | |||||
if(dp->lastticks > (int)dp->delay) | if(dp->lastticks > (int)dp->delay) | ||||
dp->lastticks = 0; | dp->lastticks = 0; | ||||
#if defined PROF | |||||
_caca_dump_stats(); | |||||
#endif | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -484,6 +484,10 @@ | |||||
RelativePath="line.c" | RelativePath="line.c" | ||||
> | > | ||||
</File> | </File> | ||||
<File | |||||
RelativePath="prof.c" | |||||
> | |||||
</File> | |||||
<File | <File | ||||
RelativePath="string.c" | 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 | dnl conditional builds | ||||
AC_ARG_ENABLE(debug, | AC_ARG_ENABLE(debug, | ||||
[ --enable-debug build debug versions of the library (default no)]) | [ --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, | AC_ARG_ENABLE(plugins, | ||||
[ --enable-plugins make X11 and GL drivers plugins (default disabled)]) | [ --enable-plugins make X11 and GL drivers plugins (default disabled)]) | ||||
AC_ARG_ENABLE(doc, | AC_ARG_ENABLE(doc, | ||||
@@ -321,7 +321,7 @@ if test "${enable_debug}" = "yes"; then | |||||
AC_DEFINE(DEBUG, 1, Define to 1 to activate debug) | AC_DEFINE(DEBUG, 1, Define to 1 to activate debug) | ||||
fi | fi | ||||
if test "${enable_prof}" = "yes"; then | |||||
if test "${enable_profiling}" = "yes"; then | |||||
AC_DEFINE(PROF, 1, Define to 1 to activate profiling) | AC_DEFINE(PROF, 1, Define to 1 to activate profiling) | ||||
fi | fi | ||||