forked from osmocom/wireshark
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>
This commit is contained in:
parent
665eb78729
commit
ac1d52aff5
32
register.h
32
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);
|
||||
|
|
|
@ -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", ®ister_all_protocols_worker, NULL);
|
||||
#else
|
||||
g_thread_create(®ister_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", ®ister_all_protocol_handoffs_worker, NULL);
|
||||
#else
|
||||
g_thread_create(®ister_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":
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue