Qt: WLAN Statistics performance improvements.
authorGerald Combs <gerald@wireshark.org>
Wed, 26 Oct 2016 21:28:00 +0000 (14:28 -0700)
committerGerald Combs <gerald@wireshark.org>
Wed, 26 Oct 2016 23:18:06 +0000 (23:18 +0000)
In the WLAN statistics dialog, add our stations to the tree in the
background. This returns control to the user immediately after tapping.

Add notes about further performance improvements.

Change-Id: Ie7ff818b8d835ecb38f5ff702a0d0e8f2635abb2
Reviewed-on: https://code.wireshark.org/review/18495
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
ui/qt/wlan_statistics_dialog.cpp
ui/qt/wlan_statistics_dialog.h

index 1040c4c999adbe33177fca624dec2737e8449c90..4a3f18ccc903863e63820ed7a6eab6a4411b43c5 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <epan/dissectors/packet-ieee80211.h>
 
+#include <QElapsedTimer>
 #include <QTreeWidget>
 #include <QTreeWidgetItem>
 
@@ -491,7 +492,9 @@ static const QString node_col_11_title_ = QObject::tr("Comment");
 
 WlanStatisticsDialog::WlanStatisticsDialog(QWidget &parent, CaptureFile &cf, const char *filter) :
     TapParameterDialog(parent, cf, HELP_STATS_WLAN_TRAFFIC_DIALOG),
-    packet_count_(0)
+    packet_count_(0),
+    cur_network_(0),
+    add_station_timer_(0)
 {
     setWindowSubtitle(tr("Wireless LAN Statistics"));
     loadGeometry(parent.width() * 4 / 5, parent.height() * 3 / 4, "WlanStatisticsDialog");
@@ -535,12 +538,15 @@ WlanStatisticsDialog::WlanStatisticsDialog(QWidget &parent, CaptureFile &cf, con
         setDisplayFilter(filter);
     }
 
+    add_station_timer_ = new QElapsedTimer();
+
     connect(statsTreeWidget(), SIGNAL(itemSelectionChanged()),
             this, SLOT(updateHeaderLabels()));
 }
 
 WlanStatisticsDialog::~WlanStatisticsDialog()
 {
+    delete add_station_timer_;
 }
 
 void WlanStatisticsDialog::tapReset(void *ws_dlg_ptr)
@@ -567,6 +573,8 @@ gboolean WlanStatisticsDialog::tapPacket(void *ws_dlg_ptr, _packet_info *, epan_
 
     ws_dlg->packet_count_++;
 
+    // XXX This is very slow for large numbers of networks. We might be
+    // able to store networks in a cache keyed on BSSID+SSID instead.
     WlanNetworkTreeWidgetItem *wn_ti = NULL;
     for (int i = 0; i < ws_dlg->statsTreeWidget()->topLevelItemCount(); i++) {
         QTreeWidgetItem *ti = ws_dlg->statsTreeWidget()->topLevelItem(i);
@@ -634,16 +642,32 @@ void WlanStatisticsDialog::fillTree()
         return;
     }
 
+    statsTreeWidget()->setSortingEnabled(false);
     cap_file_.retapPackets();
     tapDraw(this);
     removeTapListeners();
+    statsTreeWidget()->setSortingEnabled(true);
+
+    // Don't freeze if we have a large number of stations.
+    cur_network_ = 0;
+    QTimer::singleShot(0, this, SLOT(addStationTreeItems()));
+}
 
-    for (int i = 0; i < statsTreeWidget()->topLevelItemCount(); i++) {
-        QTreeWidgetItem *ti = statsTreeWidget()->topLevelItem(i);
+static const int add_station_interval_ = 5; // ms
+void WlanStatisticsDialog::addStationTreeItems()
+{
+    add_station_timer_->start();
+    while (add_station_timer_->elapsed() < add_station_interval_ && cur_network_ < statsTreeWidget()->topLevelItemCount()) {
+        QTreeWidgetItem *ti = statsTreeWidget()->topLevelItem(cur_network_);
         if (ti->type() != wlan_network_row_type_) continue;
 
         WlanNetworkTreeWidgetItem *wn_ti = static_cast<WlanNetworkTreeWidgetItem*>(ti);
         wn_ti->addStations();
+        ++cur_network_;
+    }
+
+    if (cur_network_ < statsTreeWidget()->topLevelItemCount()) {
+        QTimer::singleShot(0, this, SLOT(addStationTreeItems()));
     }
 }
 
index e39f4b64273bf9fd6a5c84911540d81b29100ee4..670feda3b13287e3404a0ea1cfc35bc8606c659b 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "tap_parameter_dialog.h"
 
+class QElapsedTimer;
+
 class WlanStatisticsDialog : public TapParameterDialog
 {
     Q_OBJECT
@@ -36,6 +38,9 @@ protected:
 
 private:
     int packet_count_;
+    int cur_network_;
+    QElapsedTimer *add_station_timer_;
+
 
     // Callbacks for register_tap_listener
     static void tapReset(void *ws_dlg_ptr);
@@ -46,6 +51,7 @@ private:
 
 private slots:
     virtual void fillTree();
+    void addStationTreeItems();
     void updateHeaderLabels();
     void captureFileClosing();
 };