2
* OpenVPN -- An application to securely tunnel IP networks
3
* over a single TCP/UDP port, with support for SSL/TLS-based
4
* session authentication and key exchange,
5
* packet encryption, packet authentication, and
8
* Copyright (C) 2002-2004 James Yonan <jim@yonan.net>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program (see the file COPYING included with this
22
* distribution); if not, write to the Free Software Foundation, Inc.,
23
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include "config-win32.h"
36
#ifdef ENABLE_PERFORMANCE_METRICS
44
#error ENABLE_PERFORMANCE_METRICS is incompatible with USE_PTHREAD
47
static const char *metric_names[] = {
48
"PERF_BIO_READ_PLAINTEXT",
49
"PERF_BIO_WRITE_PLAINTEXT",
50
"PERF_BIO_READ_CIPHERTEXT",
51
"PERF_BIO_WRITE_CIPHERTEXT",
52
"PERF_TLS_MULTI_PROCESS",
55
"PERF_MULTI_CREATE_INSTANCE",
56
"PERF_MULTI_CLOSE_INSTANCE",
57
"PERF_MULTI_SHOW_STATS",
67
"PERF_PROC_OUT_TUN_MTCP"
73
# define PS_METER_RUNNING 1
74
# define PS_METER_INTERRUPTED 2
88
struct perf perf[PERF_N];
91
static struct perf_set perf_set;
93
static void perf_print_state (int lev);
96
get_stack_index (int sdelta)
98
const int sindex = perf_set.stack_len + sdelta;
99
if (sindex >= 0 && sindex < STACK_N)
106
get_perf_index (int sdelta)
108
const int sindex = get_stack_index (sdelta);
111
const int pindex = perf_set.stack[sindex];
112
if (pindex >= 0 && pindex < PERF_N)
122
get_perf (int sdelta)
124
const int pindex = get_perf_index (sdelta);
126
return &perf_set.perf[pindex];
132
push_perf_index (int pindex)
134
const int sindex = get_stack_index (0);
135
const int newlen = get_stack_index (1);
136
if (sindex >= 0 && newlen >= 0
137
&& pindex >= 0 && pindex < PERF_N)
140
for (i = 0; i < sindex; ++i)
141
if (perf_set.stack[i] == pindex)
143
perf_print_state (M_INFO);
144
msg (M_FATAL, "PERF: push_perf_index %s failed",
145
metric_names [pindex]);
148
perf_set.stack[sindex] = pindex;
149
perf_set.stack_len = newlen;
152
msg (M_FATAL, "PERF: push_perf_index: stack push error");
156
pop_perf_index (void)
158
const int newlen = get_stack_index (-1);
161
perf_set.stack_len = newlen;
164
msg (M_FATAL, "PERF: pop_perf_index: stack pop error");
168
state_must_be (const struct perf *p, const int wanted)
170
if (p->state != wanted)
171
msg (M_FATAL, "PERF: bad state actual=%d wanted=%d",
177
update_sofar (struct perf *p)
179
struct timeval current;
180
ASSERT (!gettimeofday (¤t, NULL));
181
p->sofar += (double) tv_subtract (¤t, &p->start, 600) / 1000000.0;
182
tv_clear (&p->start);
186
perf_start (struct perf *p)
188
state_must_be (p, PS_INITIAL);
189
ASSERT (!gettimeofday (&p->start, NULL));
191
p->state = PS_METER_RUNNING;
195
perf_stop (struct perf *p)
197
state_must_be (p, PS_METER_RUNNING);
200
if (p->sofar > p->max)
204
p->state = PS_INITIAL;
208
perf_interrupt (struct perf *p)
210
state_must_be (p, PS_METER_RUNNING);
212
p->state = PS_METER_INTERRUPTED;
216
perf_resume (struct perf *p)
218
state_must_be (p, PS_METER_INTERRUPTED);
219
ASSERT (!gettimeofday (&p->start, NULL));
220
p->state = PS_METER_RUNNING;
229
ASSERT (SIZE(metric_names) == PERF_N);
230
push_perf_index (type);
232
prev = get_perf (-2);
238
perf_interrupt (prev);
248
prev = get_perf (-2);
261
perf_output_results (void)
264
msg (M_INFO, "LATENCY PROFILE (mean and max are in milliseconds)");
265
for (i = 0; i < PERF_N; ++i)
267
struct perf *p = &perf_set.perf[i];
270
const double mean = p->sum / p->count;
271
msg (M_INFO, "%s n=%.0f mean=%.3f max=%.3f", metric_names[i], p->count, mean*1000.0, p->max*1000.0);
277
perf_print_state (int lev)
279
struct gc_arena gc = gc_new ();
281
msg (lev, "PERF STATE");
283
for (i = 0; i < perf_set.stack_len; ++i)
285
const int j = perf_set.stack[i];
286
const struct perf *p = &perf_set.perf[j];
287
msg (lev, "[%d] %s state=%d start=%s sofar=%f sum=%f max=%f count=%f",
291
tv_string (&p->start, &gc),
301
static void dummy(void) {}