]> git.puffer.fish Git - mirror/frr.git/commitdiff
sharpd: add "logpump" to bulk test logging 5713/head
authorDavid Lamparter <equinox@diac24.net>
Tue, 10 Dec 2019 16:23:25 +0000 (17:23 +0100)
committerDavid Lamparter <equinox@diac24.net>
Tue, 24 Mar 2020 14:58:36 +0000 (15:58 +0100)
This just generates log messages in bulk for testing logging backend
performance.  It's in sharpd so the full "context" of being in a daemon
is available (e.g. different logging configs, parallel load in the main
thread.)

Signed-off-by: David Lamparter <equinox@diac24.net>
configure.ac
sharpd/sharp_logpump.c [new file with mode: 0644]
sharpd/sharp_vty.c
sharpd/sharp_vty.h
sharpd/subdir.am

index 41d1911c372cef42bbabd2e41b0608fae3a7b946..d1391c67b2ca9d50e04ee8e73959cf41e163b24e 100755 (executable)
@@ -2006,6 +2006,10 @@ AC_CHECK_DECL([CLOCK_MONOTONIC],
         AC_DEFINE([HAVE_CLOCK_MONOTONIC], [1], [Have monotonic clock])
 ], [AC_MSG_RESULT([no])], [FRR_INCLUDES])
 
+AC_SEARCH_LIBS([clock_nanosleep], [rt], [
+  AC_DEFINE([HAVE_CLOCK_NANOSLEEP], [1], [Have clock_nanosleep()])
+])
+
 dnl --------------------------------------
 dnl checking for flex and bison
 dnl --------------------------------------
diff --git a/sharpd/sharp_logpump.c b/sharpd/sharp_logpump.c
new file mode 100644 (file)
index 0000000..d07e2d2
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * testing log message generator
+ * Copyright (C) 2019-2020  David Lamparter for NetDEF, Inc.
+ *
+ * This program 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 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "vty.h"
+#include "command.h"
+#include "prefix.h"
+#include "nexthop.h"
+#include "log.h"
+#include "thread.h"
+#include "vrf.h"
+#include "zclient.h"
+#include "frr_pthread.h"
+
+#include "sharpd/sharp_vty.h"
+
+/* this is quite hacky, but then again it's a test tool and it does its job. */
+static struct frr_pthread *lpt;
+
+static unsigned long lp_duration;
+static unsigned lp_frequency;
+static unsigned lp_burst;
+static size_t lp_ctr, lp_expect;
+static struct rusage lp_rusage;
+static struct vty *lp_vty;
+
+extern struct thread_master *master;
+
+static int logpump_done(struct thread *thread)
+{
+       double x;
+
+       vty_out(lp_vty, "\nlogpump done\n");
+       vty_out(lp_vty, "%9zu messages written\n", lp_ctr);
+       x = (double)lp_ctr / (double)lp_expect * 100.;
+       vty_out(lp_vty, "%9zu messages targeted = %5.1lf%%\n", lp_expect, x);
+
+       x = lp_rusage.ru_utime.tv_sec * 1000000 + lp_rusage.ru_utime.tv_usec;
+       x /= (double)lp_ctr;
+       vty_out(lp_vty, "%6llu.%06u usr %9.1lfns/msg\n",
+               (unsigned long long)lp_rusage.ru_utime.tv_sec,
+               (unsigned)lp_rusage.ru_utime.tv_usec, x * 1000.);
+
+       x = lp_rusage.ru_stime.tv_sec * 1000000 + lp_rusage.ru_stime.tv_usec;
+       x /= (double)lp_ctr;
+       vty_out(lp_vty, "%6llu.%06u sys %9.1lfns/msg\n",
+               (unsigned long long)lp_rusage.ru_stime.tv_sec,
+               (unsigned)lp_rusage.ru_stime.tv_usec, x * 1000.);
+
+       frr_pthread_stop(lpt, NULL);
+       frr_pthread_destroy(lpt);
+       lpt = NULL;
+       return 0;
+}
+
+static void *logpump_run(void *arg)
+{
+       struct timespec start, next, now;
+       unsigned long delta, period;
+
+       period = 1000000000L / lp_frequency;
+
+       clock_gettime(CLOCK_MONOTONIC, &start);
+       next = start;
+       do {
+               for (size_t inburst = 0; inburst < lp_burst; inburst++)
+                       zlog_debug("log pump: %zu (burst %zu)",
+                                  lp_ctr++, inburst);
+
+               clock_gettime(CLOCK_MONOTONIC, &now);
+               delta = (now.tv_sec - start.tv_sec) * 1000000000L
+                       + (now.tv_nsec - start.tv_nsec);
+
+               next.tv_nsec += period;
+               if (next.tv_nsec > 1000000000L) {
+                       next.tv_sec++;
+                       next.tv_nsec -= 1000000000L;
+               }
+#ifdef HAVE_CLOCK_NANOSLEEP
+               clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
+#else
+               struct timespec slpdur;
+
+               slpdur.tv_sec = next.tv_sec - now.tv_sec;
+               slpdur.tv_nsec = next.tv_nsec - now.tv_nsec;
+               if (slpdur.tv_nsec < 0) {
+                       slpdur.tv_sec--;
+                       slpdur.tv_nsec += 1000000000L;
+               }
+
+               nanosleep(&slpdur, NULL);
+#endif
+       } while (delta < lp_duration);
+
+#ifdef RUSAGE_THREAD
+       getrusage(RUSAGE_THREAD, &lp_rusage);
+#else
+       getrusage(RUSAGE_SELF, &lp_rusage);
+#endif
+
+       thread_add_timer_msec(master, logpump_done, NULL, 0, NULL);
+       return NULL;
+}
+
+static int logpump_halt(struct frr_pthread *fpt, void **res)
+{
+       return 0;
+}
+
+/* default frr_pthread attributes */
+static const struct frr_pthread_attr attr = {
+       .start = logpump_run,
+       .stop = logpump_halt,
+};
+
+void sharp_logpump_run(struct vty *vty, unsigned duration, unsigned frequency,
+                      unsigned burst)
+{
+       if (lpt != NULL) {
+               vty_out(vty, "logpump already running\n");
+               return;
+       }
+
+       vty_out(vty, "starting logpump...\n");
+       vty_out(vty, "keep this VTY open and press Enter to see results\n");
+
+       lp_vty = vty;
+       lp_duration = duration * 1000000000UL;
+       lp_frequency = frequency;
+       lp_burst = burst;
+       lp_expect = duration * frequency * burst;
+       lp_ctr = 0;
+
+       lpt = frr_pthread_new(&attr, "logpump", "logpump");
+       frr_pthread_run(lpt, NULL);
+}
index fd2e37e6751d0b541abe1bb8bece803b895f6649..aa3d85624bf5c49b62f1a05dce01701b61ef3455 100644 (file)
@@ -460,6 +460,22 @@ DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
        }
 }
 
+DEFPY (logpump,
+       logpump_cmd,
+       "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
+       "Sharp Routing Protocol\n"
+       "Generate bulk log messages for testing\n"
+       "Duration of run (s)\n"
+       "Duration of run (s)\n"
+       "Frequency of bursts (s^-1)\n"
+       "Frequency of bursts (s^-1)\n"
+       "Number of log messages per each burst\n"
+       "Number of log messages per each burst\n")
+{
+       sharp_logpump_run(vty, duration, frequency, burst);
+       return CMD_SUCCESS;
+}
+
 void sharp_vty_init(void)
 {
        install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
@@ -471,6 +487,7 @@ void sharp_vty_init(void)
        install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
        install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
        install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
+       install_element(ENABLE_NODE, &logpump_cmd);
 
        install_element(VIEW_NODE, &show_debugging_sharpd_cmd);
 
index d4af095e89da5e1bb7298cbe8ed36d591e95bfe8..0d1327259c6511ce122e85ae7edbbfe443c98dcd 100644 (file)
 #define __SHARP_VTY_H__
 
 extern void sharp_vty_init(void);
+
+struct vty;
+
+extern void sharp_logpump_run(struct vty *vty, unsigned duration,
+                             unsigned frequency, unsigned burst);
+
 #endif
index 89b183d832c7f982dc29794626e5e84c908b9075..8b32b2370c80c328f233cbd1a724a0efb08b6a9a 100644 (file)
@@ -14,6 +14,7 @@ sharpd_libsharp_a_SOURCES = \
        sharpd/sharp_nht.c \
        sharpd/sharp_zebra.c \
        sharpd/sharp_vty.c \
+       sharpd/sharp_logpump.c \
        # end
 
 noinst_HEADERS += \