scaffolding
[oweals/gnunet.git] / src / stream / perf_stream_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011, 2012 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file stream/perf_stream_api.c
23  * @brief performance benchmarks for stream api
24  * @author Sree Harsha Totakura
25  */
26
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         */
37 /*       through                                                                        */
38 /*       STREAM_API->MESH_API->MESH_SERVICE->CORE1..CORE2..CORE3->MESH_API->STREAM_API. */
39 /****************************************************************************************/
40
41 #include "platform.h"
42 #include "gnunet_common.h"
43 #include "gnunet_util_lib.h"
44 #include "gnunet_testbed_service.h"
45
46   
47 /**
48  * Simple struct to keep track of progress, and print a
49  * nice little percentage meter for long running tasks.
50  */
51 struct ProgressMeter
52 {
53   unsigned int total;
54
55   unsigned int modnum;
56
57   unsigned int dotnum;
58
59   unsigned int completed;
60
61   int print;
62
63   char *startup_string;
64 };
65
66
67 /**
68  * Steps in testing
69  */
70 enum TestStep
71 {
72   /**
73    * Single hop loopback testing
74    */
75   TEST_STEP_1_HOP,
76
77   /**
78    * Testing with 2 peers
79    */
80   TEST_STEP_2_HOP,
81
82   /**
83    * Testing with 3 peers
84    */
85   TEST_STEP_3_HOP
86 };
87
88 /**
89  * Maximum size of the data which we will transfer during tests
90  */
91 #define DATA_SIZE 65536      /* 64KB */
92
93 /**
94  * Random data block. Should generate data first
95  */
96 static uint32_t data[DATA_SIZE / 4];     /* 64KB array */
97
98 /**
99  * Payload sizes to test each major test with
100  */
101 static uint16_t payload_size[] = 
102 { 20, 500, 2000, 7000, 13000, 25000, 56000, 64000 };
103
104 /**
105  * Handle for the progress meter
106  */
107 static struct ProgressMeter *meter;
108
109 /**
110  * Current step of testing
111  */
112 static enum TestStep test_step;
113
114 /**
115  * Index for choosing payload size
116  */
117 unsigned int payload_size_index;
118
119 /**
120  * Create a meter to keep track of the progress of some task.
121  *
122  * @param total the total number of items to complete
123  * @param start_string a string to prefix the meter with (if printing)
124  * @param print GNUNET_YES to print the meter, GNUNET_NO to count
125  *              internally only
126  *
127  * @return the progress meter
128  */
129 static struct ProgressMeter *
130 create_meter (unsigned int total, char *start_string, int print)
131 {
132   struct ProgressMeter *ret;
133
134   ret = GNUNET_malloc (sizeof (struct ProgressMeter));
135   ret->print = print;
136   ret->total = total;
137   ret->modnum = total / 4;
138   if (ret->modnum == 0)         /* Divide by zero check */
139     ret->modnum = 1;
140   ret->dotnum = (total / 50) + 1;
141   if (start_string != NULL)
142     ret->startup_string = GNUNET_strdup (start_string);
143   else
144     ret->startup_string = GNUNET_strdup ("");
145
146   return ret;
147 }
148
149
150 /**
151  * Update progress meter (increment by one).
152  *
153  * @param meter the meter to update and print info for
154  *
155  * @return GNUNET_YES if called the total requested,
156  *         GNUNET_NO if more items expected
157  */
158 static int
159 update_meter (struct ProgressMeter *meter)
160 {
161   if (meter->print == GNUNET_YES)
162   {
163     if (meter->completed % meter->modnum == 0)
164     {
165       if (meter->completed == 0)
166       {
167         FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string);
168       }
169       else
170         FPRINTF (stdout, "%d%%",
171                  (int) (((float) meter->completed / meter->total) * 100));
172     }
173     else if (meter->completed % meter->dotnum == 0)
174       FPRINTF (stdout, "%s",  ".");
175
176     if (meter->completed + 1 == meter->total)
177       FPRINTF (stdout, "%d%%]\n", 100);
178     fflush (stdout);
179   }
180   meter->completed++;
181
182   if (meter->completed == meter->total)
183     return GNUNET_YES;
184   if (meter->completed > meter->total)
185     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n");
186   return GNUNET_NO;
187 }
188
189
190 /**
191  * Reset progress meter.
192  *
193  * @param meter the meter to reset
194  *
195  * @return GNUNET_YES if meter reset,
196  *         GNUNET_SYSERR on error
197  */
198 static int
199 reset_meter (struct ProgressMeter *meter)
200 {
201   if (meter == NULL)
202     return GNUNET_SYSERR;
203
204   meter->completed = 0;
205   return GNUNET_YES;
206 }
207
208
209 /**
210  * Release resources for meter
211  *
212  * @param meter the meter to free
213  */
214 static void
215 free_meter (struct ProgressMeter *meter)
216 {
217   GNUNET_free_non_null (meter->startup_string);
218   GNUNET_free (meter);
219 }
220
221
222 /**
223  * Initialize framework and start test
224  *
225  * @param cls closure
226  * @param cfg configuration of the peer that was started
227  * @param peer identity of the peer that was created
228  */
229 static void
230 run (void *cls, 
231      const struct GNUNET_CONFIGURATION_Handle *cfg,
232      struct GNUNET_TESTING_Peer *peer)
233 {
234   GNUNET_break (0);
235 }
236
237
238 /**
239  * Main function
240  */
241 int main (int argc, char **argv)
242 {
243   unsigned int count;
244   int ret;
245
246   meter = create_meter ((sizeof (data) / 4), "Generating random data\n", GNUNET_YES);
247   for (count=0; count < (sizeof (data) / 4); count++)
248   {
249     data[count] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
250                                             UINT32_MAX);
251     update_meter (meter);
252   }
253   reset_meter (meter);
254   free_meter (meter);
255   test_step = TEST_STEP_1_HOP;
256   for (payload_size_index = 0; 
257        payload_size_index < (sizeof (payload_size) / sizeof (uint16_t));
258        payload_size_index++)
259   {
260     ret = GNUNET_TESTING_peer_run ("test_stream_big", "test_stream_local.conf",
261                                    &run, NULL);
262     if (0 != ret)
263       break;
264   }
265   test_step = TEST_STEP_2_HOP;
266   for (payload_size_index = 0; 
267        payload_size_index < (sizeof (payload_size) / sizeof (uint16_t));
268        payload_size_index++)
269   {
270     /* Initialize testbed here */
271   }
272   test_step = TEST_STEP_3_HOP;
273   for (payload_size_index = 0; 
274        payload_size_index < (sizeof (payload_size) / sizeof (uint16_t));
275        payload_size_index++)
276   {
277     /* Initialize testbed here */
278   }
279   return ret;
280 }