Commit c8f73cd6 authored by Clément Stenac's avatar Clément Stenac

Add a timing facility (Refs:#473)

It is only available in debug mode.

To use: stats_TimerStart( vlc_object_t* , char *name );
stats_TimerStop( vlc_object_t *, char *name );

stats_TimerDump( vlc_object_t* , char *name ) will print a line

TIMER name : last_time - total_time / number of samples (average time)

stats_TimersDumpAll is not implemented yet
 
parent 822000a1
......@@ -420,6 +420,7 @@ typedef struct counter_t counter_t;
typedef struct counter_sample_t counter_sample_t;
typedef struct stats_handler_t stats_handler_t;
typedef struct input_stats_t input_stats_t;
typedef struct global_stats_t global_stats_t;
/*****************************************************************************
......
......@@ -207,13 +207,17 @@ VLC_EXPORT( void, __msg_Unsubscribe, ( vlc_object_t *, msg_subscription_t * ) );
* @{
*/
/****************************
* Generic stats stuff
****************************/
enum
{
STATS_LAST,
STATS_COUNTER,
STATS_MAX,
STATS_MIN,
STATS_DERIVATIVE
STATS_DERIVATIVE,
STATS_TIMER
};
struct counter_sample_t
......@@ -246,17 +250,17 @@ struct stats_handler_t
VLC_EXPORT( void, stats_HandlerDestroy, (stats_handler_t*) );
#define stats_Update( a,b,c) __stats_Update( VLC_OBJECT( a ), b, c )
VLC_EXPORT( int, __stats_Update, (vlc_object_t*, char *, vlc_value_t) );
VLC_EXPORT( int, __stats_Update, (vlc_object_t*, const char *, vlc_value_t) );
#define stats_Create( a,b,c,d ) __stats_Create( VLC_OBJECT(a), b, c, d )
VLC_EXPORT( int, __stats_Create, (vlc_object_t*, char *, int, int) );
VLC_EXPORT( int, __stats_Create, (vlc_object_t*, const char *, int, int) );
#define stats_Get( a,b,c,d ) __stats_Create( VLC_OBJECT(a), b, c, d )
VLC_EXPORT( int, __stats_Get, (vlc_object_t*, int, char *, vlc_value_t*) );
VLC_EXPORT( int, __stats_Get, (vlc_object_t*, int, const char *, vlc_value_t*) );
#define stats_CounterGet( a,b,c) __stats_CounterGet( VLC_OBJECT(a), b, c )
VLC_EXPORT( counter_t*, __stats_CounterGet, (vlc_object_t*, int, char * ) );
VLC_EXPORT( counter_t*, __stats_CounterGet, (vlc_object_t*, int, const char * ) );
#define stats_GetInteger( a,b,c,d ) __stats_GetInteger( VLC_OBJECT(a), b, c, d )
static inline int __stats_GetInteger( vlc_object_t *p_obj, int i_id,
char *psz_name, int *value )
const char *psz_name, int *value )
{
vlc_value_t val;
int i_ret = __stats_Get( p_obj, i_id, psz_name, &val );
......@@ -266,7 +270,7 @@ static inline int __stats_GetInteger( vlc_object_t *p_obj, int i_id,
#define stats_GetFloat(a,b,c,d ) __stats_GetFloat( VLC_OBJECT(a), b, c, d )
static inline int __stats_GetFloat( vlc_object_t *p_obj, int i_id,
char *psz_name, float *value )
const char *psz_name, float *value )
{
vlc_value_t val;
int i_ret = __stats_Get( p_obj, i_id, psz_name, &val );
......@@ -274,22 +278,25 @@ static inline int __stats_GetFloat( vlc_object_t *p_obj, int i_id,
return i_ret;
}
#define stats_UpdateInteger( a,b,c ) __stats_UpdateInteger( VLC_OBJECT(a),b,c )
static inline int __stats_UpdateInteger( vlc_object_t *p_obj, char *psz_name,
int i )
static inline int __stats_UpdateInteger( vlc_object_t *p_obj,
const char *psz_name, int i )
{
vlc_value_t val;
val.i_int = i;
return __stats_Update( p_obj, psz_name, val );
}
#define stats_UpdateFloat( a,b,c ) __stats_UpdateFloat( VLC_OBJECT(a),b,c )
static inline int __stats_UpdateFloat( vlc_object_t *p_obj, char *psz_name,
float f )
static inline int __stats_UpdateFloat( vlc_object_t *p_obj,
const char *psz_name, float f )
{
vlc_value_t val;
val.f_float = f;
return __stats_Update( p_obj, psz_name, val );
}
/******************
* Input stats
******************/
struct input_stats_t
{
......@@ -328,3 +335,39 @@ struct input_stats_t
VLC_EXPORT( void, stats_ComputeInputStats, (input_thread_t*, input_stats_t*) );
VLC_EXPORT( void, stats_ReinitInputStats, (input_stats_t *) );
VLC_EXPORT( void, stats_DumpInputStats, (input_stats_t *) );
/********************
* Global stats
*******************/
struct global_stats_t
{
vlc_mutex_t lock;
float f_input_bitrate;
float f_output_bitrate;
int i_http_clients;
};
#define stats_ComputeGlobalStats( a,b) __stats_ComputeGlobalStats( VLC_OBJECT(a),b)
VLC_EXPORT( void, __stats_ComputeGlobalStats, (vlc_object_t*,global_stats_t*));
/*********
* Timing
********/
#ifdef DEBUG
#define stats_TimerStart(a,b) __stats_TimerStart( VLC_OBJECT(a), b )
#define stats_TimerStop(a,b) __stats_TimerStop( VLC_OBJECT(a), b )
#define stats_TimerDump(a,b) __stats_TimerDump( VLC_OBJECT(a), b )
#define stats_TimersDumpAll(a) __stats_TimersDumpAll( VLC_OBJECT(a) )
#else
#define stats_TimerStart(a,b) {}
#define stats_TimerStop(a,b) {}
#define stats_TimerDump(a,b) {}
#define stats_TimersDumpAll(a) {}
#endif
VLC_EXPORT( void,__stats_TimerStart, (vlc_object_t*, const char *) );
VLC_EXPORT( void,__stats_TimerStop, (vlc_object_t*, const char *) );
VLC_EXPORT( void,__stats_TimerDump, (vlc_object_t*, const char *) );
VLC_EXPORT( void,__stats_TimersDumpAll, (vlc_object_t*) );
......@@ -65,7 +65,7 @@ int playlist_ItemSetName (playlist_item_t *, char *);
void __osd_MenuShow (vlc_object_t *);
httpd_url_t * httpd_UrlNewUnique (httpd_host_t *, const char *psz_url, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl);
void httpd_ClientModeStream (httpd_client_t *cl);
int __stats_Create (vlc_object_t*, char *, int, int);
int __stats_Create (vlc_object_t*, const char *, int, int);
void httpd_RedirectDelete (httpd_redirect_t *);
void __sout_CfgParse (vlc_object_t *, char *psz_prefix, const char **ppsz_options, sout_cfg_t *);
vlm_media_t * vlm_MediaNew (vlm_t *, const char *, int);
......@@ -122,8 +122,8 @@ void vlm_MessageDelete (vlm_message_t *);
void vout_SynchroDecode (vout_synchro_t *);
int playlist_Delete (playlist_t *, int);
void aout_FiltersPlay (aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_buffer_t ** pp_input_buffer);
int __stats_Update (vlc_object_t*, char *, vlc_value_t);
int __stats_Get (vlc_object_t*, int, char *, vlc_value_t*);
int __stats_Update (vlc_object_t*, const char *, vlc_value_t);
int __stats_Get (vlc_object_t*, int, const char *, vlc_value_t*);
char* httpd_ClientIP (httpd_client_t *cl, char *psz_ip);
int __intf_UserProgress (vlc_object_t*, const char*, const char*, float);
void httpd_FileDelete (httpd_file_t *);
......@@ -136,6 +136,7 @@ stream_t * __stream_UrlNew (vlc_object_t *p_this, const char *psz_url);
sout_mux_t * sout_MuxNew (sout_instance_t*, char *, sout_access_out_t *);
stream_t * __stream_DemuxNew (vlc_object_t *p_obj, char *psz_demux, es_out_t *out);
int vout_ShowTextRelative (vout_thread_t *, int, char *, text_style_t *, int, int, int, mtime_t);
void __stats_TimerDump (vlc_object_t*, const char *);
int block_FifoPut (block_fifo_t *, block_t *);
int playlist_ItemAddParent (playlist_item_t *, int,playlist_item_t *);
int __var_Create (vlc_object_t *, const char *, int);
......@@ -147,7 +148,7 @@ int vlc_getnameinfo (const struct sockaddr *, int, char *, int, int *, int);
int vlm_ExecuteCommand (vlm_t *, const char *, vlm_message_t **);
char * config_GetUserDir (void);
httpd_stream_t * httpd_StreamNew (httpd_host_t *, const char *psz_url, const char *psz_mime, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl);
counter_t* __stats_CounterGet (vlc_object_t*, int, char *);
counter_t* __stats_CounterGet (vlc_object_t*, int, const char *);
int __config_GetType (vlc_object_t *, const char *);
void __vlc_thread_ready (vlc_object_t *);
int playlist_Export (playlist_t *, const char *, const char *);
......@@ -201,6 +202,7 @@ int vlm_Save (vlm_t *, const char *);
int ACL_AddNet (vlc_acl_t *p_acl, const char *psz_ip, int i_len, vlc_bool_t b_allow);
void AddMD5 (struct md5_s *, const uint8_t *, uint32_t);
void config_Duplicate (module_t *, module_config_t *);
void __stats_TimerStart (vlc_object_t*, const char *);
block_t * __block_New (vlc_object_t *, int);
void xml_Delete (xml_t *);
void __msg_Warn (vlc_object_t *, const char *, ... ) ATTRIBUTE_FORMAT( 2, 3);
......@@ -214,6 +216,7 @@ void __intf_UserProgressUpdate (vlc_object_t*, int, const char*, float);
void __msg_Generic (vlc_object_t *, int, int, const char *, const char *, ... ) ATTRIBUTE_FORMAT( 5, 6);
int vlc_closedir_wrapper (void *);
int playlist_ServicesDiscoveryAdd (playlist_t *, const char *);
void __stats_ComputeGlobalStats (vlc_object_t*,global_stats_t*);
char * vlc_strndup (const char *s, size_t n);
void vout_PlacePicture (vout_thread_t *, unsigned int, unsigned int, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
float __config_GetFloat (vlc_object_t *, const char *);
......@@ -370,6 +373,7 @@ subpicture_t * spu_SortSubpictures (spu_t *, mtime_t);
playlist_item_t * playlist_LockItemGetByInput (playlist_t *,input_item_t *);
int __net_vaPrintf (vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, va_list args);
int vlm_MediaControl (vlm_t *, vlm_media_t *, const char *, const char *, const char *);
void __stats_TimersDumpAll (vlc_object_t*);
vlc_bool_t vout_SynchroChoose (vout_synchro_t *, int, int, vlc_bool_t);
int playlist_RecursiveNodeSort (playlist_t *, playlist_item_t *,int, int);
int64_t vlc_atoll (const char *nptr);
......@@ -410,6 +414,7 @@ void aout_FormatsPrint (aout_instance_t * p_aout, const char * psz_text, const a
char * FromUTF32 (const wchar_t *);
void __vout_OSDMessage (vlc_object_t *, int, char *, ...);
void intf_StopThread (intf_thread_t *);
void __stats_TimerStop (vlc_object_t*, const char *);
stream_t * __stream_MemoryNew (vlc_object_t *p_obj, uint8_t *p_buffer, int64_t i_size, vlc_bool_t i_preserve_memory);
void mwait (mtime_t date);
void __config_ResetAll (vlc_object_t *);
......@@ -880,18 +885,24 @@ struct module_symbols_t
int (*__intf_UserProgress_inner) (vlc_object_t*, const char*, const char*, float);
void (*__intf_UserProgressUpdate_inner) (vlc_object_t*, int, const char*, float);
void (*__intf_UserHide_inner) (vlc_object_t *, int);
int (*__stats_Create_inner) (vlc_object_t*, char *, int, int);
int (*__stats_Update_inner) (vlc_object_t*, char *, vlc_value_t);
int (*__stats_Get_inner) (vlc_object_t*, int, char *, vlc_value_t*);
int (*__stats_Create_inner) (vlc_object_t*, const char *, int, int);
int (*__stats_Update_inner) (vlc_object_t*, const char *, vlc_value_t);
int (*__stats_Get_inner) (vlc_object_t*, int, const char *, vlc_value_t*);
void (*stats_ComputeInputStats_inner) (input_thread_t*, input_stats_t*);
void (*stats_DumpInputStats_inner) (input_stats_t *);
void (*stats_ReinitInputStats_inner) (input_stats_t *);
counter_t* (*__stats_CounterGet_inner) (vlc_object_t*, int, char *);
counter_t* (*__stats_CounterGet_inner) (vlc_object_t*, int, const char *);
void *__stats_CounterGet_deprecated;
input_thread_t * (*__input_CreateThread2_inner) (vlc_object_t *, input_item_t *, char *);
void (*stats_HandlerDestroy_inner) (stats_handler_t*);
vlc_t * (*vlc_current_object_inner) (int);
void (*__var_OptionParse_inner) (vlc_object_t *, const char *);
void *__stats_TimerDumpAll_deprecated;
void (*__stats_TimerDump_inner) (vlc_object_t*, const char *);
void (*__stats_TimerStart_inner) (vlc_object_t*, const char *);
void (*__stats_ComputeGlobalStats_inner) (vlc_object_t*,global_stats_t*);
void (*__stats_TimerStop_inner) (vlc_object_t*, const char *);
void (*__stats_TimersDumpAll_inner) (vlc_object_t*);
};
# if defined (__PLUGIN__)
# define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
......@@ -1323,6 +1334,11 @@ struct module_symbols_t
# define stats_HandlerDestroy (p_symbols)->stats_HandlerDestroy_inner
# define vlc_current_object (p_symbols)->vlc_current_object_inner
# define __var_OptionParse (p_symbols)->__var_OptionParse_inner
# define __stats_TimerDump (p_symbols)->__stats_TimerDump_inner
# define __stats_TimerStart (p_symbols)->__stats_TimerStart_inner
# define __stats_ComputeGlobalStats (p_symbols)->__stats_ComputeGlobalStats_inner
# define __stats_TimerStop (p_symbols)->__stats_TimerStop_inner
# define __stats_TimersDumpAll (p_symbols)->__stats_TimersDumpAll_inner
# elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
/******************************************************************
* STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
......@@ -1757,8 +1773,14 @@ struct module_symbols_t
((p_symbols)->stats_HandlerDestroy_inner) = stats_HandlerDestroy; \
((p_symbols)->vlc_current_object_inner) = vlc_current_object; \
((p_symbols)->__var_OptionParse_inner) = __var_OptionParse; \
((p_symbols)->__stats_TimerDump_inner) = __stats_TimerDump; \
((p_symbols)->__stats_TimerStart_inner) = __stats_TimerStart; \
((p_symbols)->__stats_ComputeGlobalStats_inner) = __stats_ComputeGlobalStats; \
((p_symbols)->__stats_TimerStop_inner) = __stats_TimerStop; \
((p_symbols)->__stats_TimersDumpAll_inner) = __stats_TimersDumpAll; \
(p_symbols)->net_ConvertIPv4_deprecated = NULL; \
(p_symbols)->__stats_CounterGet_deprecated = NULL; \
(p_symbols)->__stats_TimerDumpAll_deprecated = NULL; \
# endif /* __PLUGIN__ */
# endif /* HAVE_SHARED_LIBVLC */
......
......@@ -33,7 +33,7 @@
* Local prototypes
*****************************************************************************/
static counter_t *GetCounter( stats_handler_t *p_handler, int i_object_id,
char *psz_name );
const char *psz_name );
static int stats_CounterUpdate( stats_handler_t *p_handler,
counter_t *p_counter,
vlc_value_t val );
......@@ -80,7 +80,7 @@ void stats_HandlerDestroy( stats_handler_t *p_stats )
* STATS_MAX (keep the maximum passed value), STATS_MIN, or STATS_DERIVATIVE
* (keep a time derivative of the value)
*/
int __stats_Create( vlc_object_t *p_this, char *psz_name, int i_type,
int __stats_Create( vlc_object_t *p_this, const char *psz_name, int i_type,
int i_compute_type )
{
counter_t *p_counter;
......@@ -123,7 +123,8 @@ int __stats_Create( vlc_object_t *p_this, char *psz_name, int i_type,
* \param val the vlc_value union containing the new value to aggregate. For
* more information on how data is aggregated, \see __stats_Create
*/
int __stats_Update( vlc_object_t *p_this, char *psz_name, vlc_value_t val )
int __stats_Update( vlc_object_t *p_this, const char *psz_name,
vlc_value_t val )
{
int i_ret;
counter_t *p_counter;
......@@ -162,7 +163,8 @@ int __stats_Update( vlc_object_t *p_this, char *psz_name, vlc_value_t val )
* retrieved value
* \return an error code
*/
int __stats_Get( vlc_object_t *p_this, int i_object_id, char *psz_name, vlc_value_t *val )
int __stats_Get( vlc_object_t *p_this, int i_object_id,
const char *psz_name, vlc_value_t *val )
{
counter_t *p_counter;
......@@ -241,7 +243,7 @@ int __stats_Get( vlc_object_t *p_this, int i_object_id, char *psz_name, vlc_valu
* \return the counter, or NULL if not found (or handler not created yet)
*/
counter_t *__stats_CounterGet( vlc_object_t *p_this, int i_object_id,
char *psz_name )
const char *psz_name )
{
counter_t *p_counter;
......@@ -328,6 +330,7 @@ void stats_ComputeInputStats( input_thread_t *p_input,
vlc_mutex_unlock( &p_stats->lock );
}
void stats_ReinitInputStats( input_stats_t *p_stats )
{
p_stats->i_read_packets = p_stats->i_read_bytes =
......@@ -358,6 +361,121 @@ void stats_DumpInputStats( input_stats_t *p_stats )
vlc_mutex_unlock( &p_stats->lock );
}
void __stats_ComputeGlobalStats( vlc_object_t *p_obj,
global_stats_t *p_stats )
{
vlc_list_t *p_list;
int i_index;
vlc_mutex_lock( &p_stats->lock );
p_list = vlc_list_find( p_obj, VLC_OBJECT_INPUT, FIND_CHILD );
if( p_list )
{
for( i_index = 0; i_index < p_list->i_count ; i_index ++ )
{
float f_in = 0, f_out = 0;
p_obj = (vlc_object_t *)p_list->p_values[i_index].p_object;
stats_GetFloat( p_obj, p_obj->i_object_id, "input_bitrate",
&f_in );
stats_GetFloat( p_obj, p_obj->i_object_id, "sout_send_bitrate",
&f_out );
p_stats->f_input_bitrate += f_in;
p_stats->f_output_bitrate += f_out;
}
vlc_list_release( p_list );
}
vlc_mutex_unlock( &p_stats->lock );
}
void stats_ReinitGlobalStats( global_stats_t *p_stats )
{
p_stats->f_input_bitrate = p_stats->f_output_bitrate = 0.0;
}
void __stats_TimerStart( vlc_object_t *p_obj, const char *psz_name )
{
counter_t *p_counter = stats_CounterGet( p_obj,
p_obj->p_vlc->i_object_id,
psz_name );
if( !p_counter )
{
counter_sample_t *p_sample;
stats_Create( p_obj->p_vlc, psz_name, VLC_VAR_TIME, STATS_TIMER );
p_counter = stats_CounterGet( p_obj, p_obj->p_vlc->i_object_id,
psz_name );
if( !p_counter ) return;
/* 1st sample : if started: start_date, else last_time, b_started */
p_sample = (counter_sample_t *)malloc( sizeof( counter_sample_t ) );
INSERT_ELEM( p_counter->pp_samples, p_counter->i_samples,
p_counter->i_samples, p_sample );
p_sample->date = 0; p_sample->value.b_bool = 0;
/* 2nd sample : global_time, i_samples */
p_sample = (counter_sample_t *)malloc( sizeof( counter_sample_t ) );
INSERT_ELEM( p_counter->pp_samples, p_counter->i_samples,
p_counter->i_samples, p_sample );
p_sample->date = 0; p_sample->value.i_int = 0;
}
if( p_counter->pp_samples[0]->value.b_bool == VLC_TRUE )
{
msg_Warn( p_obj, "timer %s was already started !", psz_name );
return;
}
p_counter->pp_samples[0]->value.b_bool = VLC_TRUE;
p_counter->pp_samples[0]->date = mdate();
}
void __stats_TimerStop( vlc_object_t *p_obj, const char *psz_name )
{
counter_t *p_counter = stats_CounterGet( p_obj,
p_obj->p_vlc->i_object_id,
psz_name );
if( !p_counter || p_counter->i_samples != 2 )
{
msg_Err( p_obj, "timer %s does not exist", psz_name );
return;
}
p_counter->pp_samples[0]->value.b_bool = VLC_FALSE;
p_counter->pp_samples[1]->value.i_int += 1;
p_counter->pp_samples[0]->date = mdate() - p_counter->pp_samples[0]->date;
p_counter->pp_samples[1]->date += p_counter->pp_samples[0]->date;
}
void __stats_TimerDump( vlc_object_t *p_obj, const char *psz_name )
{
mtime_t last, total;
int i_total;
counter_t *p_counter = stats_CounterGet( p_obj,
p_obj->p_vlc->i_object_id,
psz_name );
if( !p_counter || p_counter->i_samples != 2 )
{
msg_Err( p_obj, "timer %s does not exist", psz_name );
return;
}
i_total = p_counter->pp_samples[1]->value.i_int;
total = p_counter->pp_samples[1]->date;
if( p_counter->pp_samples[0]->value.b_bool == VLC_TRUE )
{
last = mdate() - p_counter->pp_samples[0]->date;
i_total += 1;
total += last;
}
else
{
last = p_counter->pp_samples[0]->date;
}
msg_Dbg( p_obj, "TIMER %s : %.3f ms - Total %.3f ms / %i intvls (Avg %.3f ms)",
psz_name, (float)last/1000, (float)total/1000, i_total,
(float)(total)/(1000*(float)i_total ) );
}
void __stats_TimersDumpAll( vlc_object_t *p_obj )
{
}
/********************************************************************
* Following functions are local
......@@ -493,7 +611,7 @@ static int stats_CounterUpdate( stats_handler_t *p_handler,
}
static counter_t *GetCounter( stats_handler_t *p_handler, int i_object_id,
char *psz_name )
const char *psz_name )
{
int i;
for( i = 0; i< p_handler->i_counters; i++ )
......
......@@ -907,7 +907,6 @@ static playlist_item_t * NextItem( playlist_t *p_playlist )
/* Calculate time needed */
int64_t start = mdate();
#endif
/* Handle quickly a few special cases */
/* No items to play */
......@@ -1181,6 +1180,7 @@ static playlist_item_t * NextItem( playlist_t *p_playlist )
{
msg_Info( p_playlist, "nothing to play" );
}
return p_new;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment