REST: nothing triggers rest
[oweals/gnunet.git] / src / gns / gnunet-gns-benchmark.c
index f1efaac096465addf8bd1ac523c3d056b0adb106..77066fd3f83594cf7006ecc01f49461bda9497e8 100644 (file)
@@ -2,20 +2,20 @@
      This file is part of GNUnet
      Copyright (C) 2018 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 /**
  * @file src/gns/gnunet-gns-benchmark.c
@@ -84,7 +84,7 @@ struct Request
    * this struct (optimizing memory consumption by reducing
    * total number of allocations).
    */
-  char *hostname;
+  const char *hostname;
 
   /**
    * While we are fetching the record, the value is set to the
@@ -96,12 +96,12 @@ struct Request
    * Observed latency, set once we got a reply.
    */
   struct GNUNET_TIME_Relative latency;
-  
+
   /**
    * Category of the request.
    */
   enum RequestCategory cat;
-  
+
 };
 
 
@@ -176,6 +176,15 @@ static struct GNUNET_TIME_Relative request_delay;
  */
 static struct GNUNET_TIME_Relative timeout;
 
+/**
+ * Number of requests we have concurrently active.
+ */
+static unsigned int active_cnt;
+
+/**
+ * Look for GNS2DNS records specifically?
+ */
+static int g2d;
 
 /**
  * Free @a req and data structures reachable from it.
@@ -210,6 +219,10 @@ process_result (void *cls,
   (void) gns_tld;
   (void) rd_count;
   (void) rd;
+  active_cnt--;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got response for request `%s'\n",
+              req->hostname);
   req->lr = NULL;
   req->latency = GNUNET_TIME_absolute_get_duration (req->op_start_time);
   GNUNET_CONTAINER_DLL_remove (act_head,
@@ -237,6 +250,7 @@ process_queue (void *cls)
   struct GNUNET_TIME_Relative duration;
 
   (void) cls;
+  t = NULL;
   /* check for expired requests */
   while (NULL != (req = act_head))
   {
@@ -246,13 +260,17 @@ process_queue (void *cls)
     GNUNET_CONTAINER_DLL_remove (act_head,
                                 act_tail,
                                 req);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failing request `%s' due to timeout\n",
+                req->hostname);
     failures[req->cat]++;
+    active_cnt--;
     free_request (req);
   }
   if (NULL == (req = todo_head))
   {
     struct GNUNET_TIME_Absolute at;
-    
+
     if (NULL == (req = act_head))
     {
       GNUNET_SCHEDULER_shutdown ();
@@ -272,10 +290,17 @@ process_queue (void *cls)
                                    act_tail,
                                    req);
   lookups[req->cat]++;
+  active_cnt++;
   req->op_start_time = GNUNET_TIME_absolute_get ();
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting request `%s' (%u in parallel)\n",
+              req->hostname,
+              active_cnt);
   req->lr = GNUNET_GNS_lookup_with_tld (gns,
                                        req->hostname,
-                                       GNUNET_GNSRECORD_TYPE_ANY,
+                                       g2d
+                                        ? GNUNET_GNSRECORD_TYPE_GNS2DNS
+                                        : GNUNET_GNSRECORD_TYPE_ANY,
                                        GNUNET_GNS_LO_DEFAULT,
                                        &process_result,
                                        req);
@@ -286,7 +311,29 @@ process_queue (void *cls)
 
 
 /**
- * Clean up and terminate the process.
+ * Compare two requests by latency for qsort().
+ *
+ * @param c1 pointer to `struct Request *`
+ * @param c2 pointer to `struct Request *`
+ * @return -1 if c1<c2, 1 if c1>c2, 0 if c1==c2.
+ */
+static int
+compare_req (const void *c1,
+            const void *c2)
+{
+  const struct Request *r1 = *(void **) c1;
+  const struct Request *r2 = *(void **) c2;
+
+  if (r1->latency.rel_value_us < r2->latency.rel_value_us)
+    return -1;
+  if (r1->latency.rel_value_us > r2->latency.rel_value_us)
+    return 1;
+  return 0;
+}
+
+
+/**
+ * Output statistics, then clean up and terminate the process.
  *
  * @param cls NULL
  */
@@ -294,13 +341,66 @@ static void
 do_shutdown (void *cls)
 {
   struct Request *req;
+  struct Request **ra[RC_MAX];
+  unsigned int rp[RC_MAX];
 
   (void) cls;
-  /* FIXME: calculate statistics */
-  if (NULL != gns)
+  for (enum RequestCategory rc = 0;rc < RC_MAX;rc++)
   {
-    GNUNET_GNS_disconnect (gns);
-    gns = NULL;
+    ra[rc] = GNUNET_new_array (replies[rc],
+                              struct Request *);
+    rp[rc] = 0;
+  }
+  for (req = succ_head;NULL != req; req = req->next)
+  {
+    GNUNET_assert (rp[req->cat] < replies[req->cat]);
+    ra[req->cat][rp[req->cat]++] = req;
+  }
+  for (enum RequestCategory rc = 0;rc < RC_MAX;rc++)
+  {
+    unsigned int off;
+
+    fprintf (stdout,
+            "Category %u\n",
+            rc);
+    fprintf (stdout,
+            "\tlookups: %u replies: %u failures: %u\n",
+            lookups[rc],
+            replies[rc],
+            failures[rc]);
+    if (0 == rp[rc])
+      continue;
+    qsort (ra[rc],
+          rp[rc],
+          sizeof (struct Request *),
+          &compare_req);
+    latency_sum[rc] = GNUNET_TIME_relative_divide (latency_sum[rc],
+                                                   replies[rc]);
+    fprintf (stdout,
+            "\taverage: %s\n",
+            GNUNET_STRINGS_relative_time_to_string (latency_sum[rc],
+                                                    GNUNET_YES));
+    off = rp[rc] * 50 / 100;
+    fprintf (stdout,
+            "\tmedian(50): %s\n",
+            GNUNET_STRINGS_relative_time_to_string (ra[rc][off]->latency,
+                                                    GNUNET_YES));
+    off = rp[rc] * 75 / 100;
+    fprintf (stdout,
+            "\tquantile(75): %s\n",
+            GNUNET_STRINGS_relative_time_to_string (ra[rc][off]->latency,
+                                                    GNUNET_YES));
+    off = rp[rc] * 90 / 100;
+    fprintf (stdout,
+            "\tquantile(90): %s\n",
+            GNUNET_STRINGS_relative_time_to_string (ra[rc][off]->latency,
+                                                    GNUNET_YES));
+    off = rp[rc] * 99 / 100;
+    fprintf (stdout,
+            "\tquantile(99): %s\n",
+            GNUNET_STRINGS_relative_time_to_string (ra[rc][off]->latency,
+                                                    GNUNET_YES));
+    GNUNET_free (ra[rc]);
   }
   if (NULL != t)
   {
@@ -328,6 +428,11 @@ do_shutdown (void *cls)
                                 req);
     free_request (req);
   }
+  if (NULL != gns)
+  {
+    GNUNET_GNS_disconnect (gns);
+    gns = NULL;
+  }
 }
 
 
@@ -358,9 +463,9 @@ queue (const char *hostname,
   req = GNUNET_malloc (sizeof (struct Request) + hlen);
   req->cat = cat;
   req->hostname = (char *) &req[1];
-  memcpy (req->hostname,
-         hostname,
-         hlen);
+  GNUNET_memcpy (&req[1],
+                 hostname,
+                 hlen);
   GNUNET_CONTAINER_DLL_insert (todo_head,
                               todo_tail,
                               req);
@@ -377,33 +482,46 @@ process_stdin (void *cls)
 {
   static struct GNUNET_TIME_Absolute last;
   static uint64_t idot;
-  char hn[270];
+  unsigned int cat;
+  char hn[256];
+  char in[270];
 
   (void) cls;
   t = NULL;
   while (NULL !=
-         fgets (hn,
-                sizeof (hn),
+         fgets (in,
+                sizeof (in),
                 stdin))
   {
-    if (strlen(hn) > 0)
-      hn[strlen(hn)-1] = '\0'; /* eat newline */
+    if (strlen(in) > 0)
+      hn[strlen(in)-1] = '\0'; /* eat newline */
+    if ( (2 != sscanf (in,
+                      "%u %255s",
+                      &cat,
+                      hn)) ||
+        (cat >= RC_MAX) )
+    {
+      fprintf (stderr,
+              "Malformed input line `%s', skipping\n",
+              in);
+      continue;
+    }
     if (0 == idot)
       last = GNUNET_TIME_absolute_get ();
     idot++;
-    if (0 == idot % 10000)
+    if (0 == idot % 100000)
     {
       struct GNUNET_TIME_Relative delta;
 
       delta = GNUNET_TIME_absolute_get_duration (last);
       last = GNUNET_TIME_absolute_get ();
       fprintf (stderr,
-              "Imported 10000 records in %s\n",
+              "Read 100000 domain names in %s\n",
               GNUNET_STRINGS_relative_time_to_string (delta,
                                                       GNUNET_YES));
     }
     queue (hn,
-          RC_SHARED); // FIXME: parse input line!
+          (enum RequestCategory) cat);
   }
   fprintf (stderr,
            "Done reading %llu domain names\n",
@@ -468,6 +586,10 @@ main (int argc,
                                         "RELATIVETIME",
                                         gettext_noop ("how long to wait for an answer"),
                                         &timeout),
+    GNUNET_GETOPT_option_flag ('2',
+                               "g2d",
+                               gettext_noop ("look for GNS2DNS records instead of ANY"),
+                               &g2d),
     GNUNET_GETOPT_OPTION_END
   };
 
@@ -487,8 +609,6 @@ main (int argc,
                          NULL))
     ret = 1;
   GNUNET_free ((void*) argv);
-  fprintf (stderr,
-           "Statistics here\n");
   return ret;
 }