/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* profiler.c: vim script profiler
*/
#include "vim.h"
#if defined(FEAT_EVAL) || defined(PROTO)
# if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
/*
* Store the current time in "tm".
*/
void
profile_start(proftime_T *tm)
{
# ifdef MSWIN
QueryPerformanceCounter(tm);
# else
gettimeofday(tm, NULL);
# endif
}
/*
* Compute the elapsed time from "tm" till now and store in "tm".
*/
void
profile_end(proftime_T *tm)
{
proftime_T now;
# ifdef MSWIN
QueryPerformanceCounter(&now);
tm->QuadPart = now.QuadPart - tm->QuadPart;
# else
gettimeofday(&now, NULL);
tm->tv_usec = now.tv_usec - tm->tv_usec;
tm->tv_sec = now.tv_sec - tm->tv_sec;
if (tm->tv_usec < 0)
{
tm->tv_usec += 1000000;
--tm->tv_sec;
}
# endif
}
/*
* Subtract the time "tm2" from "tm".
*/
void
profile_sub(proftime_T *tm, proftime_T *tm2)
{
# ifdef MSWIN
tm->QuadPart -= tm2->QuadPart;
# else
tm->tv_usec -= tm2->tv_usec;
tm->tv_sec -= tm2->tv_sec;
if (tm->tv_usec < 0)
{
tm->tv_usec += 1000000;
--tm->tv_sec;
}
# endif
}
/*
* Return a string that represents the time in "tm".
* Uses a static buffer!
*/
char *
profile_msg(proftime_T *tm)
{
static char buf[50];
# ifdef MSWIN
LARGE_INTEGER fr;
QueryPerformanceFrequency(&fr);
sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
# else
sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
# endif
return buf;
}
# if defined(FEAT_FLOAT) || defined(PROTO)
/*
* Return a float that represents the time in "tm".
*/
float_T
profile_float(proftime_T *tm)
{
# ifdef MSWIN
LARGE_INTEGER fr;
QueryPerformanceFrequency(&fr);
return (float_T)tm->QuadPart / (float_T)fr.QuadPart;
# else
return (float_T)tm->tv_sec + (float_T)tm->tv_usec / 1000000.0;
# endif
}
# endif
/*
* Put the time "msec" past now in "tm".
*/
void
profile_setlimit(long msec, proftime_T *tm)
{
if (msec <= 0) // no limit
profile_zero(tm);
else
{
# ifdef MSWIN
LARGE_INTEGER fr;
QueryPerformanceCounter(tm);
QueryPerformanceFrequency(&fr);
tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
# else
long usec;
gettimeofday(tm, NULL);
usec = (long)tm->tv_usec + (long)msec * 1000;
tm->tv_usec = usec % 1000000L;
tm->tv_sec += usec / 1000000L;
# endif
}
}
/*
* Return TRUE if the current time is past "tm".
*/
int
profile_passed_limit(proftime_T *tm)
{
proftime_T now;
# ifdef MSWIN
if (tm->QuadPart == 0) // timer was not set
return FALSE;
QueryPerformanceCounter(&now);
return (now.QuadPart > tm->QuadPart);
# else
if (tm->tv_sec == 0) // timer was not set
return FALSE;
gettimeofday(&now, NULL);
return (now.tv_sec > tm->tv_sec
|| (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
# endif
}
/*
* Set the time in "tm" to zero.
*/
void
profile_zero(proftime_T *tm)
{
# ifdef MSWIN
tm->QuadPart = 0;
# else
tm->tv_usec = 0;
tm->tv_sec = 0;
# endif
}
# endif // FEAT_PROFILE || FEAT_RELTIME
#if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT) && defined(FEAT_PROFILE)
# if defined(HAVE_MATH_H)
# include <math.h>
# endif
/*
* Divide the time "tm" by "count" and store in "tm2".
*/
void
profile_divide(proftime_T *tm, int count, proftime_T *tm2)
{
if (count == 0)
profile_zero(tm2);
else
{