| @@ -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 | ||||