Merge branch 'master' into yaz-728
[yaz-moved-to-github.git] / src / timing.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file timing.c
8  * \brief Timing Utilities
9  */
10
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #ifdef WIN32
16 #include <windows.h>
17 #endif
18 #include <stdlib.h>
19
20 #if HAVE_SYS_TIMES_H
21 #include <sys/times.h>
22 #endif
23 #if HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif
26 #include <time.h>
27
28 #include <yaz/xmalloc.h>
29 #include <yaz/timing.h>
30
31 struct yaz_timing {
32 #if HAVE_SYS_TIMES_H
33     struct tms tms1, tms2;
34 #endif
35 #if HAVE_SYS_TIME_H
36     struct timeval start_time, end_time;
37 #else
38 #ifdef WIN32
39     LONGLONG start_time, end_time;
40     LONGLONG start_time_sys, start_time_user;
41     LONGLONG end_time_sys, end_time_user;
42 #endif
43 #endif
44     double real_sec, user_sec, sys_sec;
45 };
46
47 yaz_timing_t yaz_timing_create(void)
48 {
49     yaz_timing_t t = (yaz_timing_t) xmalloc(sizeof(*t));
50     yaz_timing_start(t);
51     return t;
52 }
53
54 #ifdef WIN32
55 static void get_process_time(ULONGLONG *lp_user, ULONGLONG *lp_sys)
56 {
57     FILETIME create_t, exit_t, sys_t, user_t;
58     ULARGE_INTEGER li;
59
60     GetProcessTimes(GetCurrentProcess(), &create_t, &exit_t, &sys_t, &user_t);
61     li.LowPart = user_t.dwLowDateTime;
62     li.HighPart = user_t.dwHighDateTime;
63     *lp_user = li.QuadPart;
64
65     li.LowPart = sys_t.dwLowDateTime;
66     li.HighPart = sys_t.dwHighDateTime;
67     *lp_sys = li.QuadPart;
68 }
69 static void get_date_as_largeinteger(LONGLONG *lp)
70 {
71     FILETIME f;
72     ULARGE_INTEGER li;
73     GetSystemTimeAsFileTime(&f);
74     li.LowPart = f.dwLowDateTime;
75     li.HighPart = f.dwHighDateTime;
76
77     *lp = li.QuadPart;
78 }
79 #endif
80
81 void yaz_timing_start(yaz_timing_t t)
82 {
83 #if HAVE_SYS_TIMES_H
84     times(&t->tms1);
85     t->user_sec = 0.0;
86     t->sys_sec = 0.0;
87 #else
88     t->user_sec = -1.0;
89     t->sys_sec = -1.0;
90 #endif
91     t->real_sec = -1.0;
92 #if HAVE_SYS_TIME_H
93     gettimeofday(&t->start_time, 0);
94     t->real_sec = 0.0;
95 #else
96 #ifdef WIN32
97     t->real_sec = 0.0;
98     t->user_sec = 0.0;
99     t->sys_sec = 0.0;
100     get_date_as_largeinteger(&t->start_time);
101     get_process_time(&t->start_time_user, &t->start_time_sys);
102 #endif
103 #endif
104 }
105
106 void yaz_timing_stop(yaz_timing_t t)
107 {
108 #if HAVE_SYS_TIMES_H
109     times(&t->tms2);
110
111     t->user_sec = (double) (t->tms2.tms_utime - t->tms1.tms_utime)/100;
112     t->sys_sec = (double) (t->tms2.tms_stime - t->tms1.tms_stime)/100;
113 #endif
114 #if HAVE_SYS_TIME_H
115     gettimeofday(&t->end_time, 0);
116     t->real_sec = ((t->end_time.tv_sec - t->start_time.tv_sec) * 1000000.0 +
117                    t->end_time.tv_usec - t->start_time.tv_usec) / 1000000;
118 #else
119 #ifdef WIN32
120     get_date_as_largeinteger(&t->end_time);
121     t->real_sec = (t->end_time - t->start_time) / 10000000.0;
122
123     get_process_time(&t->end_time_user, &t->end_time_sys);
124     t->user_sec = (t->end_time_user - t->start_time_user) / 10000000.0;
125     t->sys_sec = (t->end_time_sys - t->start_time_sys) / 10000000.0;
126 #endif
127 #endif
128 }
129
130 double yaz_timing_get_real(yaz_timing_t t)
131 {
132     return t->real_sec;
133 }
134
135 double yaz_timing_get_user(yaz_timing_t t)
136 {
137     return t->user_sec;
138 }
139
140 double yaz_timing_get_sys(yaz_timing_t t)
141 {
142     return t->sys_sec;
143 }
144
145 void yaz_timing_destroy(yaz_timing_t *tp)
146 {
147     if (*tp)
148     {
149         xfree(*tp);
150         *tp = 0;
151     }
152 }
153
154 /*
155  * Local variables:
156  * c-basic-offset: 4
157  * c-file-style: "Stroustrup"
158  * indent-tabs-mode: nil
159  * End:
160  * vim: shiftwidth=4 tabstop=8 expandtab
161  */
162