blob: 81d543ea7e7727d2993db1103587ed7b8f4e05d8 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id: tsx_bench.c 4420 2013-03-05 11:59:54Z bennylp $ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include "test.h"
21#include <pjsip.h>
22#include <pjlib.h>
23
24#define THIS_FILE "tsx_uas_test.c"
25
26
27static pjsip_module mod_tsx_user;
28
29static int uac_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed)
30{
31 unsigned i;
32 pjsip_tx_data *request;
33 pjsip_transaction **tsx;
34 pj_timestamp t1, t2, elapsed;
35 pjsip_via_hdr *via;
36 pj_status_t status;
37
38 /* Create the request first. */
39 pj_str_t str_target = pj_str("sip:someuser@someprovider.com");
40 pj_str_t str_from = pj_str("\"Local User\" <sip:localuser@serviceprovider.com>");
41 pj_str_t str_to = pj_str("\"Remote User\" <sip:remoteuser@serviceprovider.com>");
42 pj_str_t str_contact = str_from;
43
44 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method,
45 &str_target, &str_from, &str_to,
46 &str_contact, NULL, -1, NULL,
47 &request);
48 if (status != PJ_SUCCESS) {
49 app_perror(" error: unable to create request", status);
50 return status;
51 }
52
53 via = (pjsip_via_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_VIA,
54 NULL);
55
56 /* Create transaction array */
57 tsx = (pjsip_transaction**) pj_pool_zalloc(request->pool, working_set * sizeof(pj_pool_t*));
58
59 pj_bzero(&mod_tsx_user, sizeof(mod_tsx_user));
60 mod_tsx_user.id = -1;
61
62 /* Benchmark */
63 elapsed.u64 = 0;
64 pj_get_timestamp(&t1);
65 for (i=0; i<working_set; ++i) {
66 status = pjsip_tsx_create_uac(&mod_tsx_user, request, &tsx[i]);
67 if (status != PJ_SUCCESS)
68 goto on_error;
69 /* Reset branch param */
70 via->branch_param.slen = 0;
71 }
72 pj_get_timestamp(&t2);
73 pj_sub_timestamp(&t2, &t1);
74 pj_add_timestamp(&elapsed, &t2);
75
76 p_elapsed->u64 = elapsed.u64;
77 status = PJ_SUCCESS;
78
79on_error:
80 for (i=0; i<working_set; ++i) {
81 if (tsx[i]) {
82 pj_timer_heap_t *th;
83
84 pjsip_tsx_terminate(tsx[i], 601);
85 tsx[i] = NULL;
86
87 th = pjsip_endpt_get_timer_heap(endpt);
88 pj_timer_heap_poll(th, NULL);
89 }
90 }
91 pjsip_tx_data_dec_ref(request);
92 flush_events(2000);
93 return status;
94}
95
96
97
98static int uas_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed)
99{
100 unsigned i;
101 pjsip_tx_data *request;
102 pjsip_via_hdr *via;
103 pjsip_rx_data rdata;
104 pj_sockaddr_in remote;
105 pjsip_transaction **tsx;
106 pj_timestamp t1, t2, elapsed;
107 char branch_buf[80] = PJSIP_RFC3261_BRANCH_ID "0000000000";
108 pj_status_t status;
109
110 /* Create the request first. */
111 pj_str_t str_target = pj_str("sip:someuser@someprovider.com");
112 pj_str_t str_from = pj_str("\"Local User\" <sip:localuser@serviceprovider.com>");
113 pj_str_t str_to = pj_str("\"Remote User\" <sip:remoteuser@serviceprovider.com>");
114 pj_str_t str_contact = str_from;
115
116 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method,
117 &str_target, &str_from, &str_to,
118 &str_contact, NULL, -1, NULL,
119 &request);
120 if (status != PJ_SUCCESS) {
121 app_perror(" error: unable to create request", status);
122 return status;
123 }
124
125 /* Create Via */
126 via = pjsip_via_hdr_create(request->pool);
127 via->sent_by.host = pj_str("192.168.0.7");
128 via->sent_by.port = 5061;
129 via->transport = pj_str("udp");
130 via->rport_param = 1;
131 via->recvd_param = pj_str("192.168.0.7");
132 pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*)via);
133
134
135 /* Create "dummy" rdata from the tdata */
136 pj_bzero(&rdata, sizeof(pjsip_rx_data));
137 rdata.tp_info.pool = request->pool;
138 rdata.msg_info.msg = request->msg;
139 rdata.msg_info.from = (pjsip_from_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
140 rdata.msg_info.to = (pjsip_to_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL);
141 rdata.msg_info.cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL);
142 rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
143 rdata.msg_info.via = via;
144
145 pj_sockaddr_in_init(&remote, 0, 0);
146 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
147 &remote, sizeof(pj_sockaddr_in),
148 NULL, &rdata.tp_info.transport);
149 if (status != PJ_SUCCESS) {
150 app_perror(" error: unable to get loop transport", status);
151 return status;
152 }
153
154
155 /* Create transaction array */
156 tsx = (pjsip_transaction**) pj_pool_zalloc(request->pool, working_set * sizeof(pj_pool_t*));
157
158 pj_bzero(&mod_tsx_user, sizeof(mod_tsx_user));
159 mod_tsx_user.id = -1;
160
161
162 /* Benchmark */
163 elapsed.u64 = 0;
164 pj_get_timestamp(&t1);
165 for (i=0; i<working_set; ++i) {
166 via->branch_param.ptr = branch_buf;
167 via->branch_param.slen = PJSIP_RFC3261_BRANCH_LEN +
168 pj_ansi_sprintf(branch_buf+PJSIP_RFC3261_BRANCH_LEN,
169 "-%d", i);
170 status = pjsip_tsx_create_uas(&mod_tsx_user, &rdata, &tsx[i]);
171 if (status != PJ_SUCCESS)
172 goto on_error;
173
174 }
175 pj_get_timestamp(&t2);
176 pj_sub_timestamp(&t2, &t1);
177 pj_add_timestamp(&elapsed, &t2);
178
179 p_elapsed->u64 = elapsed.u64;
180 status = PJ_SUCCESS;
181
182on_error:
183 for (i=0; i<working_set; ++i) {
184 if (tsx[i]) {
185 pj_timer_heap_t *th;
186
187 pjsip_tsx_terminate(tsx[i], 601);
188 tsx[i] = NULL;
189
190 th = pjsip_endpt_get_timer_heap(endpt);
191 pj_timer_heap_poll(th, NULL);
192
193 }
194 }
195 pjsip_tx_data_dec_ref(request);
196 flush_events(2000);
197 return status;
198}
199
200
201
202int tsx_bench(void)
203{
204 enum { WORKING_SET=10000, REPEAT = 4 };
205 unsigned i, speed;
206 pj_timestamp usec[REPEAT], min, freq;
207 char desc[250];
208 int status;
209
210 status = pj_get_timestamp_freq(&freq);
211 if (status != PJ_SUCCESS)
212 return status;
213
214
215 /*
216 * Benchmark UAC
217 */
218 PJ_LOG(3,(THIS_FILE, " benchmarking UAC transaction creation:"));
219 for (i=0; i<REPEAT; ++i) {
220 PJ_LOG(3,(THIS_FILE, " test %d of %d..",
221 i+1, REPEAT));
222 PJ_LOG(3,(THIS_FILE, " number of current tsx: %d",
223 pjsip_tsx_layer_get_tsx_count()));
224 status = uac_tsx_bench(WORKING_SET, &usec[i]);
225 if (status != PJ_SUCCESS)
226 return status;
227 }
228
229 min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF);
230 for (i=0; i<REPEAT; ++i) {
231 if (usec[i].u64 < min.u64) min.u64 = usec[i].u64;
232 }
233
234
235 /* Report time */
236 pj_ansi_sprintf(desc, "Time to create %d UAC transactions, in miliseconds",
237 WORKING_SET);
238 report_ival("create-uac-time", (unsigned)(min.u64 * 1000 / freq.u64), "msec", desc);
239
240
241 /* Write speed */
242 speed = (unsigned)(freq.u64 * WORKING_SET / min.u64);
243 PJ_LOG(3,(THIS_FILE, " UAC created at %d tsx/sec", speed));
244
245 pj_ansi_sprintf(desc, "Number of UAC transactions that potentially can be created per second "
246 "with <tt>pjsip_tsx_create_uac()</tt>, based on the time "
247 "to create %d simultaneous transactions above.",
248 WORKING_SET);
249
250 report_ival("create-uac-tsx-per-sec",
251 speed, "tsx/sec", desc);
252
253
254
255 /*
256 * Benchmark UAS
257 */
258 PJ_LOG(3,(THIS_FILE, " benchmarking UAS transaction creation:"));
259 for (i=0; i<REPEAT; ++i) {
260 PJ_LOG(3,(THIS_FILE, " test %d of %d..",
261 i+1, REPEAT));
262 PJ_LOG(3,(THIS_FILE, " number of current tsx: %d",
263 pjsip_tsx_layer_get_tsx_count()));
264 status = uas_tsx_bench(WORKING_SET, &usec[i]);
265 if (status != PJ_SUCCESS)
266 return status;
267 }
268
269 min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF);
270 for (i=0; i<REPEAT; ++i) {
271 if (usec[i].u64 < min.u64) min.u64 = usec[i].u64;
272 }
273
274
275 /* Report time */
276 pj_ansi_sprintf(desc, "Time to create %d UAS transactions, in miliseconds",
277 WORKING_SET);
278 report_ival("create-uas-time", (unsigned)(min.u64 * 1000 / freq.u64), "msec", desc);
279
280
281 /* Write speed */
282 speed = (unsigned)(freq.u64 * WORKING_SET / min.u64);
283 PJ_LOG(3,(THIS_FILE, " UAS created at %d tsx/sec", speed));
284
285 pj_ansi_sprintf(desc, "Number of UAS transactions that potentially can be created per second "
286 "with <tt>pjsip_tsx_create_uas()</tt>, based on the time "
287 "to create %d simultaneous transactions above.",
288 WORKING_SET);
289
290 report_ival("create-uas-tsx-per-sec",
291 speed, "tsx/sec", desc);
292
293 return PJ_SUCCESS;
294}
295