aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2017-11-14 15:58:32 -0800
committerAnders Broman <a.broman58@gmail.com>2017-11-16 06:11:55 +0000
commitac1d52aff5bdf74600ddc2f8f06ceccf9d2037a6 (patch)
treef36410bffc6f0a13a2562e5b2b9d548636c67ecf
parent665eb78729c91b4056b3e58af4407f51df603f55 (diff)
Register protocols and handoffs in separate threads.
Instead of interleaving protocol registrations and status callbacks in the main thread, move protocol registrations to a worker thread. Do the same with protocol handoffs. This *should* be safe since the status callbacks only update the UI. This reduces startup time by about 200ms on my laptop: Run OS Thread? Time 1 macOS N 340 ms 2 macOS N 260 ms 3 macOS N 252 ms 4 macOS Y 147 ms 5 macOS Y 146 ms 6 macOS Y 142 ms 7 Win 7 N 80 samples 8 Win 7 N 56 samples 9 Win 7 N 75 samples 10 Win 7 Y 31 samples 11 Win 7 Y 2 samples 12 Win 7 Y 0 samples macOS was sampled using Instruments. Windows 7 was sampled using the Visual Studio 2015 profiler. We should do the same thing with our capture and tap event loops, but that will likely require quite a bit more work. Change-Id: Iac9a81d8f71668f5979b524744a03f6d80aee893 Reviewed-on: https://code.wireshark.org/review/24447 Reviewed-by: Gerald Combs <gerald@wireshark.org> Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--register.h32
-rwxr-xr-xtools/make-dissector-reg.py88
-rw-r--r--ui/qt/splash_overlay.cpp28
3 files changed, 116 insertions, 32 deletions
diff --git a/register.h b/register.h
index deaa9cf..6ace1e4 100644
--- a/register.h
+++ b/register.h
@@ -24,19 +24,43 @@ typedef enum {
RA_DISSECTORS, /* Initializing dissectors */
RA_LISTENERS, /* Tap listeners */
RA_EXTCAP, /* extcap register preferences */
- RA_REGISTER, /* Built-in register */
- RA_PLUGIN_REGISTER, /* Plugin register */
- RA_HANDOFF, /* Built-in handoff */
- RA_PLUGIN_HANDOFF, /* Plugin handoff */
+ RA_REGISTER, /* Built-in dissector registration */
+ RA_PLUGIN_REGISTER, /* Plugin dissector registration */
+ RA_HANDOFF, /* Built-in dissector handoff */
+ RA_PLUGIN_HANDOFF, /* Plugin dissector handoff */
RA_LUA_PLUGINS, /* Lua plugin register */
RA_LUA_DEREGISTER, /* Lua plugin deregister */
RA_PREFERENCES, /* Module preferences */
RA_INTERFACES /* Local interfaces */
} register_action_e;
+#define RA_BASE_COUNT (RA_INTERFACES - 3) // RA_EXTCAP, RA_LUA_PLUGINS, RA_LUA_DEREGISTER
+
typedef void (*register_cb)(register_action_e action, const char *message, gpointer client_data);
+/** Call each dissector's protocol registration routine.
+ *
+ * Each routine is called in alphabetical order from a worker thread.
+ * Registration routines might call any number of routines which are not
+ * thread safe, such as wmem_alloc. Callbacks should handle themselves
+ * accordingly.
+ *
+ * @param register_cb Callback routine which is called for each protocol.
+ * Messages have the format "proto_register_XXX".
+ * @param client_data Data pointer for the callback.
+ */
WS_DLL_PUBLIC void register_all_protocols(register_cb cb, gpointer client_data);
+
+/** Call each dissector's protocol handoff routine.
+ *
+ * Each routine is called from a worker thread. Registration routines
+ * might call any number of routines which are not thread safe, such as
+ * wmem_alloc. Callbacks should handle themselves accordingly.
+ *
+ * @param register_cb Callback routine which is called for each protocol.
+ * Messages have the format "proto_reg_handoff_XXX".
+ * @param client_data Data pointer for the callback.
+ */
WS_DLL_PUBLIC void register_all_protocol_handoffs(register_cb cb, gpointer client_data);
extern void register_all_tap_listeners(void);
WS_DLL_PUBLIC gulong register_count(void);
diff --git a/tools/make-dissector-reg.py b/tools/make-dissector-reg.py
index 7b4c296..dadb27b 100755
--- a/tools/make-dissector-reg.py
+++ b/tools/make-dissector-reg.py
@@ -211,7 +211,9 @@ WS_DLL_PUBLIC_DEF const gchar plugin_release[] = VERSION_RELEASE;
else:
reg_code += """
#include "register.h"
+#include "ws_attributes.h"
+#include <glib.h>
"""
for symbol in regs['proto_reg']:
@@ -227,19 +229,61 @@ plugin_register (void)
"""
else:
reg_code += """
-#define CALLBACK_REGISTER(proto, data) \\
- if (cb) cb(RA_REGISTER, proto, data)
+static const char *cur_cb_name = NULL;
+//static GMutex register_cb_mtx;
+static GAsyncQueue *register_cb_done_q;
+
+#define CB_WAIT_TIME (150 * 1000) // microseconds
+
+static void set_cb_name(const char *proto) {
+ // g_mutex_lock(register_cb_mtx);
+ cur_cb_name = proto;
+ // g_mutex_unlock(register_cb_mtx);
+}
+
+static void *register_all_protocols_worker(void *arg _U_);
void
register_all_protocols(register_cb cb, gpointer cb_data)
{
+ const char *cb_name;
+ register_cb_done_q = g_async_queue_new();
+ gboolean called_back = FALSE;
+
+#if GLIB_CHECK_VERSION(2,31,0)
+ g_thread_new("register_all_protocols_worker", &register_all_protocols_worker, NULL);
+#else
+ g_thread_create(&register_all_protocols_worker, TRUE, FALSE, NULL);
+#endif
+ while (!g_async_queue_timeout_pop(register_cb_done_q, CB_WAIT_TIME)) {
+ // g_mutex_lock(register_cb_mtx);
+ cb_name = cur_cb_name;
+ // g_mutex_unlock(register_cb_mtx);
+ if (cb && cb_name) {
+ cb(RA_REGISTER, cb_name, cb_data);
+ called_back = TRUE;
+ }
+ }
+ if (cb && !called_back) {
+ cb(RA_REGISTER, "Registration finished", cb_data);
+ }
+}
+
+void
+*register_all_protocols_worker(void *arg _U_)
+{
"""
for symbol in regs['proto_reg']:
if registertype != "plugin" and registertype != "plugin_wtap":
- reg_code += " CALLBACK_REGISTER(\"%s\", cb_data);\n" % (symbol)
+ reg_code += " set_cb_name(\"%s\");\n" % (symbol)
reg_code += " %s();\n" % (symbol)
+if registertype != "plugin" and registertype != "plugin_wtap":
+ reg_code += """
+ g_async_queue_push(register_cb_done_q, GINT_TO_POINTER(TRUE));
+ return NULL;
+"""
reg_code += "}\n\n"
@@ -258,19 +302,51 @@ plugin_reg_handoff(void)
"""
else:
reg_code += """
-#define CALLBACK_HANDOFF(proto, data) \\
- if (cb) cb(RA_HANDOFF, proto, data)
+static void *register_all_protocol_handoffs_worker(void *arg _U_);
void
register_all_protocol_handoffs(register_cb cb, gpointer cb_data)
{
+ cur_cb_name = NULL;
+ const char *cb_name;
+ gboolean called_back = FALSE;
+
+#if GLIB_CHECK_VERSION(2,31,0)
+ g_thread_new("register_all_protocol_hadoffss_worker", &register_all_protocol_handoffs_worker, NULL);
+#else
+ g_thread_create(&register_all_protocol_handoffs_worker, TRUE, FALSE, NULL);
+#endif
+ while (!g_async_queue_timeout_pop(register_cb_done_q, CB_WAIT_TIME)) {
+ // g_mutex_lock(register_cb_mtx);
+ cb_name = cur_cb_name;
+ // g_mutex_unlock(register_cb_mtx);
+ if (cb && cb_name) {
+ cb(RA_HANDOFF, cb_name, cb_data);
+ called_back = TRUE;
+ }
+ }
+ if (cb && !called_back) {
+ cb(RA_HANDOFF, "Registration finished", cb_data);
+ }
+
+ g_async_queue_unref(register_cb_done_q);
+}
+
+void
+*register_all_protocol_handoffs_worker(void *arg _U_)
+{
"""
for symbol in regs['handoff_reg']:
if registertype != "plugin" and registertype != "plugin_wtap":
- reg_code += " CALLBACK_HANDOFF(\"%s\", cb_data);\n" % (symbol)
+ reg_code += " set_cb_name(\"%s\");\n" % (symbol)
reg_code += " %s();\n" % (symbol)
+if registertype != "plugin" and registertype != "plugin_wtap":
+ reg_code += """
+ g_async_queue_push(register_cb_done_q, GINT_TO_POINTER(TRUE));
+ return NULL;
+"""
reg_code += "}\n"
if registertype == "plugin":
diff --git a/ui/qt/splash_overlay.cpp b/ui/qt/splash_overlay.cpp
index af1a765..3399bea 100644
--- a/ui/qt/splash_overlay.cpp
+++ b/ui/qt/splash_overlay.cpp
@@ -40,11 +40,6 @@
// Uncomment to slow the update progress
//#define THROTTLE_STARTUP 1
-/*
- * Update frequency for the splash screen, given in milliseconds.
- */
-static int info_update_freq_ = 100;
-
void splash_update(register_action_e action, const char *message, void *) {
emit wsApp->registerUpdate(action, message);
}
@@ -58,17 +53,14 @@ SplashOverlay::SplashOverlay(QWidget *parent) :
{
so_ui_->setupUi(this);
- // 6 for:
- // dissectors, listeners, registering plugins, handingoff plugins,
- // preferences, and interfaces
- int register_add = 6;
+ int register_max = RA_BASE_COUNT;
#ifdef HAVE_LUA
- register_add += wslua_count_plugins(); /* get count of lua plugins */
+ register_max++;
#endif
#ifdef HAVE_EXTCAP
- register_add += extcap_count() + 1; /* Count of extcap binaries + registration message */
+ register_max++;
#endif
- so_ui_->progressBar->setMaximum((int)register_count() + register_add);
+ so_ui_->progressBar->setMaximum(register_max);
elapsed_timer_.start();
QColor bg = QColor(tango_aluminium_6);
@@ -97,12 +89,6 @@ SplashOverlay::SplashOverlay(QWidget *parent) :
"}"
));
-#ifndef THROTTLE_STARTUP
- // Check for a remote connection
- if (display_is_remote())
- info_update_freq_ = 1000;
-#endif
-
connect(wsApp, SIGNAL(splashUpdate(register_action_e,const char*)),
this, SLOT(splashUpdate(register_action_e,const char*)));
}
@@ -133,10 +119,8 @@ void SplashOverlay::splashUpdate(register_action_e action, const char *message)
ThrottleThread::msleep(10);
#endif
- register_cur_++;
- if (last_action_ == action && elapsed_timer_.elapsed() < info_update_freq_ && register_cur_ != so_ui_->progressBar->maximum()) {
- /* Only update every splash_register_freq milliseconds */
- return;
+ if (last_action_ != action) {
+ register_cur_++;
}
last_action_ = action;