/*
* perfos.c -- Perfos modules.
*
* Authors : Patrick Lecoanet.
* Creation date :
*
* $Id: perfos.c,v 1.13 2005/04/27 07:32:03 lecoanet Exp $
*/
/*
* Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
*
* See the file "Copyright" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#ifndef _WIN32
#include "perfos.h"
#include "List.h"
#include "Types.h"
#include <X11/Xutil.h>
static const char rcsid[] = "$Id: perfos.c,v 1.13 2005/04/27 07:32:03 lecoanet Exp $";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
static ZnList Chronos = NULL;
/*
**********************************************************************************
*
* HardwareSynchronize - Synchronise Xwindow.
*
**********************************************************************************
*/
static void
HardwareSynchronize(Display *test_display,
Drawable test_window)
{
/*XImage *image;*/
/* Synchronize yourself with the drawing engine by sending a
XGetImage one pixel square. */
/*
image = XGetImage(test_display, test_window, 0, 0, 1, 1, ~0, ZPixmap);
XDestroyImage(image);
*/
}
/*
**********************************************************************************
*
* GetUCTime - Return machine time. This is the sum of user and system
* times for the process so far.
*
**********************************************************************************
*/
static long
GetUCTime(void)
{
struct tms time;
times(&time);
return time.tms_utime + time.tms_stime;
}
/*
**********************************************************************************
*
* GetCurrentTime - Return current time.
*
**********************************************************************************
*/
static long
GetCurrentTime(void)
{
struct timeval start;
gettimeofday(&start, NULL);
return((start.tv_sec * 100) + (start.tv_usec / 10000));
}
/*
**********************************************************************************
*
* XGetCurrentTime - return current time after Xwindow synchronize.
*
**********************************************************************************
*/
static long
XGetCurrentTime(Display *display, Drawable window)
{
HardwareSynchronize(display, window);
return(GetCurrentTime());
}
/*
**********************************************************************************
*
* XCorrectionValue - Evaluate the correction value to apply
* to counter the client-server round trip
* time.
*
**********************************************************************************
*/
static long
XCorrectionValue(Display *display, Drawable window)
{
int i;
long start, stop;
start = GetCurrentTime();
for (i = 0; i < 5; i++) {
HardwareSynchronize(display, window);
}
stop = GetCurrentTime();
return((stop - start) / 5);
}
/*
**********************************************************************************
*
* ZnXStartChrono - Start a perf chrono with X synchronize.
*
**********************************************************************************
*/
void
ZnXStartChrono(ZnChrono chrono, Display *display, Drawable window)
{
chrono->current_correction = XCorrectionValue(display, window);
chrono->current_delay = XGetCurrentTime(display, window);
}
/*
**********************************************************************************
*
* ZnXStopChrono - Stop a perf chrono with X synchronize.
*
**********************************************************************************
*/
void
ZnXStopChrono(ZnChrono chrono, Display *display, Drawable window)
{
chrono->total_delay = chrono->total_delay +
(XGetCurrentTime(display, window) -
chrono->current_delay - chrono->current_correction);
chrono->actions++;
}
/*
**********************************************************************************
*
* ZnStartChrono - Start a perf chrono in user time.
*
**********************************************************************************
*/
void
ZnStartChrono(ZnChrono chrono)
{
chrono->current_delay = GetCurrentTime();
}
/*
**********************************************************************************
*
* ZnStopChrono - Stop a perf chrono in user time.
*
**********************************************************************************
*/
void
ZnStopChrono(ZnChrono chrono)
{
chrono->total_delay = chrono->total_delay + (GetCurrentTime() - chrono->current_delay);
chrono->actions++;
}
/*
**********************************************************************************
*
* ZnStartUCChrono - Start a perf chrono in uc time.
*
**********************************************************************************
*/
void
ZnStartUCChrono(ZnChrono chrono)
{
chrono->current_delay = GetUCTime();
}
/*
**********************************************************************************
*
* ZnStopUCChrono - Stop a perf chrono in uc time.
*
**********************************************************************************
*/
void
ZnStopUCChrono(ZnChrono chrono)
{
chrono->total_delay = chrono->total_delay + (GetUCTime() - chrono->current_delay);
chrono->actions++;
}
/*
**********************************************************************************
*
* ZnPrintChronos - Print the currently available stats on all
* chronos registered so far.
*
**********************************************************************************
*/
void
ZnPrintChronos(void)
{
int i, cnt;
ZnChrono *chrs;
cnt = ZnListSize(Chronos);
chrs = (ZnChrono *) ZnListArray(Chronos);
for (i = 0; i < cnt; i++) {
if (chrs[i]->actions != 0) {
printf("%s : %ld ms on %d times\n",
chrs[i]->message,
chrs[i]->total_delay * 10 / chrs[i]->actions,
chrs[i]->actions);
}
}
}
/*
**********************************************************************************
*
* ZnGetChrono - Return the number of runs and the total time of the Chrono.
*
**********************************************************************************
*/
void
ZnGetChrono(ZnChrono chrono,
long *time,
int *actions)
{
if (time) {
*time = chrono->total_delay*10;
}
if (actions) {
*actions = chrono->actions;
}
}
/*
**********************************************************************************
*
* ZnResetChronos - Reset all chronos or only the specified.
*
**********************************************************************************
*/
void
ZnResetChronos(ZnChrono chrono)
{
int i, cnt;
ZnChrono *chrs;
if (chrono) {
chrono->actions = 0;
chrono->total_delay = 0;
}
else {
cnt = ZnListSize(Chronos);
chrs = (ZnChrono *) ZnListArray(Chronos);
for (i = 0; i < cnt; i++) {
chrs[i]->actions = 0;
chrs[i]->total_delay = 0;
}
}
}
/*
**********************************************************************************
*
* ZnNewChrono - Return a new initialized chrono associated with
* message.
*
**********************************************************************************
*/
ZnChrono
ZnNewChrono(char *message)
{
ZnChrono new;
if (!Chronos) {
Chronos = ZnListNew(8, sizeof(ZnChrono));
}
new = (ZnChrono) ZnMalloc(sizeof(ZnChronoRec));
new->actions = 0;
new->total_delay = 0;
new->message = message;
ZnListAdd(Chronos, &new, ZnListTail);
return new;
}
/*
**********************************************************************************
*
* ZnFreeChrono - Free the resources of a chrono.
*
**********************************************************************************
*/
void
ZnFreeChrono(ZnChrono chrono)
{
int i;
ZnChrono *chrs = ZnListArray(Chronos);
ZnFree(chrono);
for (i = ZnListSize(Chronos)-1; i >= 0; i--) {
if (chrs[i] == chrono) {
ZnListDelete(Chronos, i);
break;
}
}
}
#endif /* _WIN32 */