diff --git a/configure.ac b/configure.ac index 2fd124576..a42cd6553 100644 --- a/configure.ac +++ b/configure.ac @@ -906,12 +906,12 @@ AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stddef.h sys/file.h sys/param # Check time and resources headers and functions: AC_STRUCT_TM AC_STRUCT_TIMEZONE -AC_CHECK_FUNCS([localtime]) +AC_CHECK_FUNCS([time localtime]) -AC_CHECK_FUNCS([ftime gettimeofday]) -# Do not use time or getrusage function for CPU time measurement under OpenMP +AC_CHECK_FUNCS([queryperformancecounter clock_gettime gettimeofday ftime]) +# Do not use times or getrusage function for CPU time measurement under OpenMP if test "x$enable_openmp" = xno; then - AC_CHECK_FUNCS([time getrusage]) + AC_CHECK_FUNCS([times getrusage]) fi AC_CHECK_FUNCS([utimes]) AC_CHECK_FUNCS([getrlimit ulimit], [break]) diff --git a/src/frontend/resource.c b/src/frontend/resource.c index 09b40863b..2b69b75fb 100644 --- a/src/frontend/resource.c +++ b/src/frontend/resource.c @@ -77,19 +77,13 @@ init_rlimits(void) ft_ckspace(); } +PerfTimer timer; void init_time(void) { -#ifdef HAVE_GETRUSAGE -#else -# ifdef HAVE_TIMES -# else -# ifdef HAVE_FTIME - ftime(&timebegin); -# endif -# endif -#endif + perf_timer_get_time(&timebegin); + perf_timer_start(&timer); } @@ -169,38 +163,33 @@ printres(char *name) if (!name || eq(name, "totalcputime") || eq(name, "cputime")) { int total_sec, total_msec; -# ifdef HAVE_GETRUSAGE - int ret; - struct rusage ruse; - memset(&ruse, 0, sizeof(ruse)); - ret = getrusage(RUSAGE_SELF, &ruse); - if (ret == -1) - perror("getrusage(): "); +#if defined (USE_OMP) \ + || defined (HAVE_QUERYPERFORMANCECOUNTER) || defined(HAVE_CLOCK_GETTIME) \ + || defined (HAVE_GETTIMEOFDAY) || defined(HAVE_TIMES) \ + || defined (HAVE_GETRUSAGE) || defined(HAVE_FTIME) - total_sec = (int) (ruse.ru_utime.tv_sec + ruse.ru_stime.tv_sec); - total_msec = (int) (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec) / 1000; - cpu_elapsed = "CPU"; -# else -# ifdef HAVE_TIMES - struct tms ruse; - times(&ruse); - clock_t x = ruse.tms_utime + ruse.tms_stime; - clock_t hz = (clock_t) sysconf(_SC_CLK_TCK); - total_sec = x / hz; - total_msec = ((x % hz) * 1000) / hz; - cpu_elapsed = "CPU"; -# else -# ifdef HAVE_FTIME - struct timeb timenow; - ftime(&timenow); - timediff(&timenow, &timebegin, &total_sec, &total_msec); + perf_timer_stop(&timer); + perf_timer_elapsed_sec_ms(&timer, &total_sec, &total_msec); + +#ifdef USE_OMP cpu_elapsed = "elapsed"; -# else -# define NO_RUDATA -# endif -# endif -# endif +#elif defined(HAVE_QUERYPERFORMANCECOUNTER) + cpu_elapsed = "elapsed"; +#elif defined(HAVE_CLOCK_GETTIME) + cpu_elapsed = "elapsed"; +#elif defined(HAVE_GETTIMEOFDAY) + cpu_elapsed = "elapsed"; +#elif defined(HAVE_TIMES) + cpu_elapsed = "CPU"; +#elif defined(HAVE_GETRUSAGE) + cpu_elapsed = "CPU"; +#elif defined(HAVE_FTIME) + cpu_elapsed = "elapsed"; +#endif +#else +# define NO_RUDATA +#endif #ifndef NO_RUDATA diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index 0937f597d..842a90e4f 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -117,15 +117,17 @@ # include # include # endif -#else -# ifdef HAVE_TIMES -# include -# include -# else -# ifdef HAVE_FTIME -# include -# endif -# endif +#endif + +#ifdef HAVE_TIMES +# include +# include +#endif +#ifdef HAVE_GETTIMEOFDAY +# include +#endif +#ifdef HAVE_FTIME +# include #endif #ifdef HAVE_UNISTD_H diff --git a/src/misc/misc_time.c b/src/misc/misc_time.c index 415089956..0f55d9a29 100644 --- a/src/misc/misc_time.c +++ b/src/misc/misc_time.c @@ -8,35 +8,28 @@ Copyright 1990 Regents of the University of California. All rights reserved. #include "ngspice/ngspice.h" #include + +#if defined(HAS_WINGUI) || defined(__MINGW32__) || defined(_MSC_VER) +#ifdef HAVE_QUERYPERFORMANCECOUNTER +#define WIN32_LEAN_AND_MEAN + /* + * The ngspice.h file included above defines BOOLEAN (via bool.h) and this + * clashes with the definition obtained from windows.h (via winnt.h). + * However, BOOLEAN is not used by this file so we can work round this problem + * by undefining BOOLEAN before including windows.h + * SJB - April 2005 + */ +#undef BOOLEAN +#include +#endif +#endif + #include "misc_time.h" -#ifdef HAVE_LOCALTIME -#include +#ifdef USE_OMP +#include #endif -#ifdef HAVE_GETRUSAGE -# include -# include -# include -#else -# ifdef HAVE_TIMES -# include -# include -# include -# else -# ifdef HAVE_FTIME -/* default to ftime if we can't get real CPU times */ -# include -# include -# endif -# endif -#endif - -#ifdef HAVE_FTIME -# include -#endif - - /* Return the date. Return value is static data. */ char * @@ -68,15 +61,13 @@ datestring(void) /* return time interval in seconds and milliseconds */ -#ifdef HAVE_FTIME +PerfTime timebegin; -struct timeb timebegin; - -void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec) +void timediff(PerfTime *now, PerfTime *begin, int *sec, int *msec) { - *msec = (int) now->millitm - (int) begin->millitm; - *sec = (int) now->time - (int) begin->time; + *msec = (int) now->milliseconds - (int) begin->milliseconds; + *sec = (int) now->seconds - (int) begin->seconds; if (*msec < 0) { *msec += 1000; (*sec)--; @@ -85,8 +76,6 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec) } -#endif - /* * How many seconds have elapsed in running time. * This is the routine called in IFseconds @@ -95,39 +84,65 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec) double seconds(void) { -#ifdef HAVE_GETRUSAGE - int ret; - struct rusage ruse; - - memset(&ruse, 0, sizeof(ruse)); - ret = getrusage(RUSAGE_SELF, &ruse); - if(ret == -1) { - perror("getrusage(): "); - return 1; - } - return ((double)ruse.ru_utime.tv_sec + (double) ruse.ru_utime.tv_usec / 1000000.0); +#ifdef USE_OMP + // Usage of OpenMP time function + return omp_get_wtime(); +#elif defined(HAVE_QUERYPERFORMANCECOUNTER) + // Windows (MSC and mingw) specific implementation + LARGE_INTEGER frequency, counter; + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&counter); + return (double)counter.QuadPart / frequency.QuadPart; +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec + ts.tv_nsec / 1e9; +#elif defined(HAVE_GETTIMEOFDAY) + // Usage of gettimeofday + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1e6; +#elif defined(HAVE_TIMES) + // Usage of times + struct tms t; + clock_t ticks = times(&t); + return (double)ticks / sysconf(_SC_CLK_TCK); +#elif defined(HAVE_GETRUSAGE) + // Usage of getrusage + struct rusage usage; + getrusage(RUSAGE_SELF, &usage); + return usage.ru_utime.tv_sec + usage.ru_utime.tv_usec / 1e6; +#elif defined(HAVE_FTIME) + // Usage of ftime + struct timeb tb; + ftime(&tb); + return tb.time + tb.millitm / 1000.0; #else -#ifdef HAVE_TIMES - - struct tms tmsbuf; - - times(&tmsbuf); - return((double) tmsbuf.tms_utime / HZ); - -#else -#ifdef HAVE_FTIME - struct timeb timenow; - int sec, msec; - - ftime(&timenow); - timediff(&timenow, &timebegin, &sec, &msec); - return(sec + (double) msec / 1000.0); - -#else /* unknown */ - /* don't know how to do this in general. */ - return(-1.0); /* Obvious error condition */ - -#endif /* !FTIME */ -#endif /* !SYSV */ -#endif /* !BSD */ + #error "No timer function available." +#endif +} + +void perf_timer_start(PerfTimer *timer) +{ + timer->start = seconds(); +} + +void perf_timer_stop(PerfTimer *timer) +{ + timer->end = seconds(); +} + +void perf_timer_elapsed_sec_ms(const PerfTimer *timer, int *seconds, int *milliseconds) +{ + double elapsed = timer->end - timer->start; + *seconds = (int)elapsed; + *milliseconds = (int)((elapsed - *seconds) * 1000.0); +} + +void perf_timer_get_time(PerfTime *time) +{ + double secs = seconds(); + time->seconds = (int)secs; + time->milliseconds = (int)((secs - time->seconds) * 1000.0); + } diff --git a/src/misc/misc_time.h b/src/misc/misc_time.h index 95cc1bcb2..7b96dd593 100644 --- a/src/misc/misc_time.h +++ b/src/misc/misc_time.h @@ -9,12 +9,23 @@ char * datestring(void); double seconds(void); -#ifdef HAVE_FTIME +typedef struct { + double start; + double end; +} PerfTimer; -extern struct timeb timebegin; +typedef struct { + int seconds; + int milliseconds; +} PerfTime; -void timediff(struct timeb *, struct timeb *, int *, int *); - -#endif +void perf_timer_start(PerfTimer *); +void perf_timer_stop(PerfTimer *); +void perf_timer_elapsed_sec_ms(const PerfTimer *, int *, int *); +void perf_timer_get_time(PerfTime *); + +extern PerfTime timebegin; + +void timediff(PerfTime *, PerfTime *, int *, int *); #endif diff --git a/src/sharedspice.c b/src/sharedspice.c index ae2d48adf..381805417 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -155,10 +155,6 @@ static bool cont_condition; #include "ngspice/stringskip.h" #include "frontend/variable.h" -#ifdef HAVE_FTIME -#include -#endif - /* To interupt a spice run */ #include typedef void (*sighandler)(int); @@ -1908,26 +1904,32 @@ void SetAnalyse( static unsigned int ng_id1 = 0, ng_id2 = 0; bool thread1; -#ifdef HAVE_FTIME - struct timeb timenow; /* actual time stamp */ +#if defined (USE_OMP) \ +|| defined (HAVE_QUERYPERFORMANCECOUNTER) \ +|| defined (HAVE_CLOCK_GETTIME) \ +|| defined (HAVE_GETTIMEOFDAY) \ +|| defined (HAVE_TIMES) \ +|| defined (HAVE_GETRUSAGE) \ +|| defined (HAVE_FTIME) + PerfTime timenow; /* actual time stamp */ int diffsec, diffmillisec; /* differences actual minus prev. time stamp */ int result; /* return value from callback function */ char* s; /* outputs to callback function */ int OldPercent; /* Previous progress value */ char OldAn[128]; /* Previous analysis type */ char olds[128]; /* previous output */ - static struct timeb timebefore; /* previous time stamp */ + static PerfTime timebefore; /* previous time stamp */ /* thread 1 */ static int OldPercent1 = -2; /* Previous progress value */ static char OldAn1[128]; /* Previous analysis type */ static char olds1[128]; /* previous output */ - static struct timeb timebefore1; /* previous time stamp */ + static PerfTime timebefore1; /* previous time stamp */ /* thread2 */ static int OldPercent2 = -2; /* Previous progress value */ static char OldAn2[128]; /* Previous analysis type */ static char olds2[128]; /* previous output */ - static struct timeb timebefore2; /* previous time stamp */ + static PerfTime timebefore2; /* previous time stamp */ /*set the two thread ids */ unsigned int ng_idl = threadid_self(); @@ -1945,20 +1947,16 @@ void SetAnalyse( strcpy(OldAn, OldAn1); strcpy(olds, olds1); OldPercent = OldPercent1; - timebefore.dstflag = timebefore1.dstflag; - timebefore.millitm = timebefore1.millitm; - timebefore.time = timebefore1.time; - timebefore.timezone = timebefore1.timezone; + timebefore.milliseconds = timebefore1.milliseconds; + timebefore.seconds = timebefore1.seconds; } else if (ng_idl == ng_id2) { thread1 = FALSE; strcpy(OldAn, OldAn2); strcpy(olds, olds2); OldPercent = OldPercent2; - timebefore.dstflag = timebefore2.dstflag; - timebefore.millitm = timebefore2.millitm; - timebefore.time = timebefore2.time; - timebefore.timezone = timebefore2.timezone; + timebefore.milliseconds = timebefore2.milliseconds; + timebefore.seconds = timebefore2.seconds; } else return; @@ -1972,7 +1970,7 @@ void SetAnalyse( return; /* get actual time */ - ftime(&timenow); + perf_timer_get_time(&timenow); timediff(&timenow, &timebefore, &diffsec, &diffmillisec); s = TMALLOC(char, 128); @@ -2023,16 +2021,12 @@ void SetAnalyse( sprintf( s, "%s: %3.1f%%", Analyse, (double)DecaPercent/10.); } if (thread1) { - timebefore1.dstflag = timenow.dstflag; - timebefore1.millitm = timenow.millitm; - timebefore1.time = timenow.time; - timebefore1.timezone = timenow.timezone; + timebefore1.milliseconds = timenow.milliseconds; + timebefore1.seconds = timenow.seconds; } else { - timebefore2.dstflag = timenow.dstflag; - timebefore2.millitm = timenow.millitm; - timebefore2.time = timenow.time; - timebefore2.timezone = timenow.timezone; + timebefore2.milliseconds = timenow.milliseconds; + timebefore2.seconds = timenow.seconds; } /* info when previous analysis period has finished */ if (strcmp(OldAn, Analyse)) { diff --git a/src/winmain.c b/src/winmain.c index 1bf3bb5fb..619ab468a 100644 --- a/src/winmain.c +++ b/src/winmain.c @@ -38,7 +38,7 @@ #include "hist_info.h" /* history management */ #include "ngspice/bool.h" /* bool defined as unsigned char */ -#include "misc/misc_time.h" /* timediff */ +#include "misc/misc_time.h" /* timer functions and structure */ #include "ngspice/memory.h" /* TMALLOC */ #include "winmain.h" @@ -220,8 +220,8 @@ SetAnalyse(char *Analyse, /* in: analysis type */ static int OldPercent = -2; /* Previous progress value */ static char OldAn[128]; /* Previous analysis type */ char s[128], t[128]; /* outputs to analysis window and task bar */ - static struct timeb timebefore; /* previous time stamp */ - struct timeb timenow; /* actual time stamp */ + static PerfTime timebefore; /* previous time stamp */ + PerfTime timenow; /* actual time stamp */ int diffsec, diffmillisec; /* differences actual minus prev. time stamp */ WaitForIdle(); @@ -232,7 +232,7 @@ SetAnalyse(char *Analyse, /* in: analysis type */ return; /* get actual time */ - ftime(&timenow); + perf_timer_get_time(&timenow); timediff(&timenow, &timebefore, &diffsec, &diffmillisec); OldPercent = DecaPercent; @@ -255,10 +255,8 @@ SetAnalyse(char *Analyse, /* in: analysis type */ sprintf(s, " %s: %3.1f%%", Analyse, (double)DecaPercent/10.); sprintf(t, "%s %3.1f%%", PACKAGE_STRING, (double)DecaPercent/10.); } - timebefore.dstflag = timenow.dstflag; - timebefore.millitm = timenow.millitm; - timebefore.time = timenow.time; - timebefore.timezone = timenow.timezone; + timebefore.milliseconds = timenow.milliseconds; + timebefore.seconds = timenow.seconds; /* info when previous analysis period has finished */ if (strcmp(OldAn, Analyse)) { if ((ft_nginfo || ft_ngdebug) && (strcmp(OldAn, ""))) diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 81707d84d..575a45346 100644 --- a/visualc/src/include/ngspice/config.h +++ b/visualc/src/include/ngspice/config.h @@ -163,6 +163,9 @@ /* Define to 1 if you have the `fork' function. */ /* #undef HAVE_FORK */ +/* Define to 1 if you have the `queryperformancecounter' function. */ +#define HAVE_QUERYPERFORMANCECOUNTER 1 + /* Define to 1 if you have the `ftime' function. */ #define HAVE_FTIME 1