2 This file is part of GNUnet.
3 (C) 2011, 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file stream/perf_stream_api.c
23 * @brief performance benchmarks for stream api
24 * @author Sree Harsha Totakura
27 /****************************************************************************************/
28 /* Test is setup into the following major steps: */
29 /* 1. Measurements over loopback (1 hop). i.e. we use only one peer and open */
30 /* stream connections over loopback. Messages will go through */
31 /* STREAM_API->MESH_API->MESH_SERVICE->MESH_API->STREAM_API. */
32 /* 2. Measurements over 2 peers (2 hops). We use testbed to create 2 peers, */
33 /* connect them and then create stream connections. Messages will go through */
34 /* STREAM_API->MESH_API->MESH_SERVICE->CORE1.....CORE2->MESH_API->STREAM_API */
35 /* 3. Measurements over 3 peers (3 hops). We use testbed to create 3 peers, */
36 /* connect them in a line topology: peer1->peer2->peer3. Messages will go */
38 /* STREAM_API->MESH_API->MESH_SERVICE->CORE1..CORE2..CORE3->MESH_API->STREAM_API. */
39 /****************************************************************************************/
42 #include "gnunet_common.h"
43 #include "gnunet_util_lib.h"
44 #include "gnunet_testing_lib.h"
45 #include "gnunet_testbed_service.h"
46 #include "gnunet_stream_lib.h"
51 * Simple struct to keep track of progress, and print a
52 * nice little percentage meter for long running tasks.
62 unsigned int completed;
76 * Single hop loopback testing
81 * Testing with 2 peers
86 * Testing with 3 peers
92 * Structure for holding peer's sockets and IO Handles
97 * Peer's stream socket
99 struct GNUNET_STREAM_Socket *socket;
101 struct GNUNET_PeerIdentity self;
104 * Peer's io write handle
106 struct GNUNET_STREAM_IOWriteHandle *io_write_handle;
109 * Peer's io read handle
111 struct GNUNET_STREAM_IOReadHandle *io_read_handle;
114 * Bytes the peer has written
116 unsigned int bytes_wrote;
119 * Byte the peer has read
121 unsigned int bytes_read;
126 * Maximum size of the data which we will transfer during tests
128 #define DATA_SIZE 65536 /* 64KB */
131 * Listen socket of peer2
133 struct GNUNET_STREAM_ListenSocket *peer2_listen_socket;
136 * Handle to configuration during TEST_STEP_1_HOP
138 const struct GNUNET_CONFIGURATION_Handle *config;
141 * Placeholder for peer data
143 static struct PeerData peer_data[3];
146 * Task ID for abort task
148 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
151 * Random data block. Should generate data first
153 static uint32_t data[DATA_SIZE / 4]; /* 64KB array */
156 * Payload sizes to test each major test with
158 static uint16_t payload_size[] =
159 { 20, 500, 2000, 7000, 13000, 25000, 56000, 64000 };
162 * Handle for the progress meter
164 static struct ProgressMeter *meter;
167 * Current step of testing
169 static enum TestStep test_step;
172 * Index for choosing payload size
174 unsigned int payload_size_index;
177 * Create a meter to keep track of the progress of some task.
179 * @param total the total number of items to complete
180 * @param start_string a string to prefix the meter with (if printing)
181 * @param print GNUNET_YES to print the meter, GNUNET_NO to count
184 * @return the progress meter
186 static struct ProgressMeter *
187 create_meter (unsigned int total, char *start_string, int print)
189 struct ProgressMeter *ret;
191 ret = GNUNET_malloc (sizeof (struct ProgressMeter));
194 ret->modnum = total / 4;
195 if (ret->modnum == 0) /* Divide by zero check */
197 ret->dotnum = (total / 50) + 1;
198 if (start_string != NULL)
199 ret->startup_string = GNUNET_strdup (start_string);
201 ret->startup_string = GNUNET_strdup ("");
208 * Update progress meter (increment by one).
210 * @param meter the meter to update and print info for
212 * @return GNUNET_YES if called the total requested,
213 * GNUNET_NO if more items expected
216 update_meter (struct ProgressMeter *meter)
218 if (meter->print == GNUNET_YES)
220 if (meter->completed % meter->modnum == 0)
222 if (meter->completed == 0)
224 FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string);
227 FPRINTF (stdout, "%d%%",
228 (int) (((float) meter->completed / meter->total) * 100));
230 else if (meter->completed % meter->dotnum == 0)
231 FPRINTF (stdout, "%s", ".");
233 if (meter->completed + 1 == meter->total)
234 FPRINTF (stdout, "%d%%]\n", 100);
239 if (meter->completed == meter->total)
241 if (meter->completed > meter->total)
242 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n");
248 * Reset progress meter.
250 * @param meter the meter to reset
252 * @return GNUNET_YES if meter reset,
253 * GNUNET_SYSERR on error
256 reset_meter (struct ProgressMeter *meter)
259 return GNUNET_SYSERR;
261 meter->completed = 0;
267 * Release resources for meter
269 * @param meter the meter to free
272 free_meter (struct ProgressMeter *meter)
274 GNUNET_free_non_null (meter->startup_string);
280 * Something went wrong and timed out. Kill everything and set error flag
283 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
290 * Functions of this type are called upon new stream connection from other peers
292 * @param cls the closure from GNUNET_STREAM_listen
293 * @param socket the socket representing the stream
294 * @param initiator the identity of the peer who wants to establish a stream
296 * @return GNUNET_OK to keep the socket open, GNUNET_SYSERR to close the
297 * stream (the socket will be invalid after the call)
300 stream_listen_cb (void *cls, struct GNUNET_STREAM_Socket *socket,
301 const struct GNUNET_PeerIdentity *initiator)
309 * Listen success callback; connects a peer to stream as client
312 stream_connect (void)
319 * Initialize framework and start test
322 * @param cfg configuration of the peer that was started
323 * @param peer identity of the peer that was created
327 const struct GNUNET_CONFIGURATION_Handle *cfg,
328 struct GNUNET_TESTING_Peer *peer)
330 struct GNUNET_PeerIdentity self;
332 GNUNET_TESTING_peer_get_identity (peer, &self);
334 peer2_listen_socket =
335 GNUNET_STREAM_listen (config, 10, /* App port */ &stream_listen_cb, NULL,
336 GNUNET_STREAM_OPTION_SIGNAL_LISTEN_SUCCESS,
337 &stream_connect, GNUNET_STREAM_OPTION_END);
338 GNUNET_assert (NULL != peer2_listen_socket);
339 peer_data[1].self = self;
340 peer_data[2].self = self;
342 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
343 (GNUNET_TIME_UNIT_SECONDS, 60), &do_abort,
351 int main (int argc, char **argv)
357 meter = create_meter ((sizeof (data) / 4), "Generating random data\n", GNUNET_YES);
358 for (count=0; count < (sizeof (data) / 4); count++)
360 data[count] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
362 update_meter (meter);
366 test_step = TEST_STEP_1_HOP;
367 for (payload_size_index = 0;
368 payload_size_index < (sizeof (payload_size) / sizeof (uint16_t));
369 payload_size_index++)
371 GNUNET_asprintf (&pmsg, "Testing over loopback with payload size %hu\n",
372 payload_size[payload_size_index]);
373 meter = create_meter ((sizeof (data) / 4), pmsg, GNUNET_YES);
375 ret = GNUNET_TESTING_peer_run ("test_stream_big", "test_stream_local.conf",
381 test_step = TEST_STEP_2_HOP;
382 for (payload_size_index = 0;
383 payload_size_index < (sizeof (payload_size) / sizeof (uint16_t));
384 payload_size_index++)
386 /* Initialize testbed here */
388 test_step = TEST_STEP_3_HOP;
389 for (payload_size_index = 0;
390 payload_size_index < (sizeof (payload_size) / sizeof (uint16_t));
391 payload_size_index++)
393 /* Initialize testbed here */