Commit e56148c4 authored by Peter Wu's avatar Peter Wu Committed by Anders Broman

Follow Stream: ensure linear performance with many packets

Reverse the payload chunks list to achieve a running time of O(n) rather
than O(n²) for insertion of all chunks. Executing a RelWithDebInfo+ASAN
build with `tshark -r chargen-session.pcapng.gz -qz follow,tcp,hex,0`
previously took 11m5s to complete, but now finishes in 16 seconds.

Tested using a capture file with 152k TCP packets (from bug 11777).
Backport note: must update ui/gtk/follow_stream.c too.

Change-Id: Icf70d45f33d4399e53209fb6199d3809608c8d99
Reviewed-on: https://code.wireshark.org/review/28595
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: 's avatarAnders Broman <a.broman58@gmail.com>
(cherry picked from commit c40c26c04c6a39ef7867a35c50293c666255c9a4)
 [Peter: updated ui/gtk/follow_stream.c for master-2.6]
Reviewed-on: https://code.wireshark.org/review/28642
parent 76568277
......@@ -514,8 +514,8 @@ ssl_follow_tap_listener(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _
appl_data->plain_data,
appl_data->data_len);
/* Append the record to the follow_info structure. */
follow_info->payload = g_list_append(follow_info->payload, follow_record);
/* Add the record to the follow_info structure. */
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
follow_info->bytes_written[from] += appl_data->data_len;
}
......
......@@ -1000,7 +1000,7 @@ check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 a
fragment->data->data + new_pos,
new_frag_size);
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
}
follow_info->seq[is_server] += (fragment->data->len - new_pos);
......@@ -1018,7 +1018,7 @@ check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 a
if( EQ_SEQ(fragment->seq, follow_info->seq[is_server]) ) {
/* this fragment fits the stream */
if( fragment->data->len > 0 ) {
follow_info->payload = g_list_append(follow_info->payload, fragment);
follow_info->payload = g_list_prepend(follow_info->payload, fragment);
}
follow_info->seq[is_server] += fragment->data->len;
......@@ -1046,7 +1046,7 @@ check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 a
follow_record->seq = lowest_seq;
follow_info->seq[is_server] = lowest_seq;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
return TRUE;
}
......@@ -1093,7 +1093,7 @@ follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,
follow_info->seq[follow_record->is_server]++;
follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
return FALSE;
}
......@@ -1140,7 +1140,7 @@ follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,
follow_info->seq[follow_record->is_server]++;
if (data_length > 0) {
follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
added_follow_record = TRUE;
}
......
......@@ -142,7 +142,7 @@ follow_info_free(follow_info_t* follow_info)
GList *cur;
follow_record_t *follow_record;
for(cur = follow_info->payload; cur; cur = g_list_next(cur)) {
for (cur = follow_info->payload; cur; cur = g_list_next(cur)) {
if(cur->data) {
follow_record = (follow_record_t *)cur->data;
if(follow_record->data)
......@@ -206,7 +206,7 @@ follow_tvb_tap_listener(void *tapdata, packet_info *pinfo,
/* update stream counter */
follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
return FALSE;
}
......
......@@ -84,7 +84,7 @@ typedef struct {
typedef struct _follow_info {
show_stream_t show_stream;
char *filter_out_filter;
GList *payload;
GList *payload; /* "follow_record_t" entries, in reverse order. */
guint bytes_written[2]; /* Index with FROM_CLIENT or FROM_SERVER for readability. */
guint32 seq[2]; /* TCP only */
GList *fragments[2]; /* TCP only */
......
......@@ -2591,7 +2591,7 @@ sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
printf(",\"payloads\":[");
for (cur = follow_info->payload; cur; cur = g_list_next(cur))
for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur))
{
follow_record = (follow_record_t *) cur->data;
......
......@@ -183,9 +183,9 @@ static void follow_draw(void *contextp)
else
printf("Node 1: %s:%u\n", buf, follow_info->server_port);
for (cur = follow_info->payload, chunk = 1;
for (cur = g_list_last(follow_info->payload), chunk = 1;
cur != NULL;
cur = g_list_next(cur), chunk++)
cur = g_list_previous(cur), chunk++)
{
follow_record = (follow_record_t *)cur->data;
if (!follow_record->is_server) {
......
......@@ -119,7 +119,7 @@ follow_common_read_stream(follow_info_t *follow_info,
GByteArray *buffer = g_byte_array_new();
for (cur = follow_info->payload; cur; cur = g_list_next(cur)) {
for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur)) {
follow_record = (follow_record_t *)cur->data;
skip = FALSE;
if (!follow_record->is_server) {
......
......@@ -1001,7 +1001,7 @@ FollowStreamDialog::readFollowStream()
elapsed_timer.start();
for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) {
for (cur = g_list_last(follow_info_.payload); cur; cur = g_list_previous(cur)) {
if (dialogClosed()) break;
follow_record = (follow_record_t *)cur->data;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment